实验1
任务1:
体会面向对象设计中封装、暴露接口(interface)、基于接口编程的意义
代码:// 现代C++标准库、算法库体验
// 本例用到以下内容:
// 1. 字符串string, 动态数组容器类vector、迭代器
// 2. 算法库:反转元素次序、旋转元素
// 3. 函数模板、const引用作为形参
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 声明
// 模板函数声明
template<typename T>
void output(const T &c);
// 普通函数声明
void test1();
void test2();
void test3();
int main() {
cout << "测试1: \n";
test1();
cout << "\n测试2: \n";
test2();
cout << "\n测试3: \n";
test3();
}
// 函数实现
// 输出容器对象c中的元素
template <typename T>
void output(const T &c) {
for(auto &i: c)
cout << i << " ";
cout << endl;
}
// 测试1
// 组合使用算法库、迭代器、string反转字符串
void test1() {
string s0{"0123456789"};
cout << "s0 = " << s0 << endl;
string s1{s0};
reverse(s1.begin(), s1.end()); // 反转指定迭代器区间的元素
cout << "s1 = " << s1 << endl;
string s2{s0};
reverse_copy(s0.begin(), s0.end(), s2.begin()); // 将指定迭代区间的元素拷贝到指定迭代器开始的目标区间,并且在复制过程中反转次序
cout << "s2 = " << s2 << endl;
}
// 测试2
// 组合使用算法库、迭代器、vector反转动态数组对象vector内数据
void test2() {
vector<int> v0{2, 0, 4, 9};
cout << "v0: ";
output(v0);
vector<int> v1{v0};
reverse(v1.begin(), v1.end());
cout << "v1: ";
output(v1);
vector<int> v2{v0};
reverse_copy(v0.begin(), v0.end(), v2.begin());
cout << "v2: ";
output(v2);
}
// 测试3
// 组合使用算法库、迭代器、vector实现元素旋转移位
void test3() {
vector<int> v0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << "v0: ";
output(v0);
vector<int> v1{v0};
rotate(v1.begin(), v1.begin()+1, v1.end()); // 旋转指定迭代器区间[v1.begin(), v1.end())之间的数据项,旋转后从迭代器v1.begin()+1位置的数据项开始
cout << "v1: ";
output(v1);
vector<int> v2{v0};
rotate(v2.begin(), v2.begin()+2, v2.end());
cout << "v2: ";
output(v2);
vector<int> v3{v0};
rotate(v3.begin(), v3.end()-1, v3.end());
cout << "v3: ";
output(v3);
vector<int> v4{v0};
rotate(v4.begin(), v4.end()-2, v4.end());
cout << "v4: ";
output(v4);
}
编译结果:
任务2:
体验使用C++标准库高效编程解决基础问题 (对指定区间进行排序、赋值;求最大值、最小值、均值)
代码:#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <iomanip>
using namespace std;
// 函数声明
// 模板函数声明
template<typename T>
void output(const T &c);
// 普通函数声明
int rand_int_100();
void test1();
void test2();
int main() {
cout << "测试1: \n";
test1();
cout << "\n测试2: \n";
test2();
}
// 函数实现
// 输出容器对象c中的元素
template <typename T>
void output(const T &c) {
for(auto &i: c)
cout << i << " ";
cout << endl;
}
// 返回[0, 100]区间内的一个随机整数
int rand_int_100() {
return rand() % 101;
}
// 测试1
// 对容器类对象指定迭代器区间进行赋值、排序
void test1() {
vector<int> v0(10); // 创建一个动态数组对象v0, 对象大小为10
generate(v0.begin(), v0.end(), rand_int_100); // 产生[0, 100]之间的随机整数赋值给指定迭代器区间[v0.begin(), v0.end())内的每个数据项
cout << "v0: ";
output(v0);
vector<int> v1{v0};
sort(v1.begin(), v1.end()); // 对指定迭代器区间[v1.begin(), v1.end())内数据项进行升序排序
cout << "v1: ";
output(v1);
vector<int> v2{v0};
sort(v2.begin()+1, v2.end()-1); // 对指定迭代器区间[v1.begin()+1, v1.end()-1)内数据项进行升序排序
cout << "v2: ";
output(v2);
}
// 测试2
// 对容器类对象指定迭代器区间进行赋值、计算最大值/最小值/均值
void test2() {
vector<int> v0(10);
generate(v0.begin(), v0.end(), rand_int_100);
cout << "v0: ";
output(v0);
auto iter1 = min_element(v0.begin(), v0.end());
cout << "最小值: " << *iter1 << endl;
auto iter2 = max_element(v0.begin(), v0.end());
cout << "最大值: " << *iter2 << endl;
auto ans = minmax_element(v0.begin(), v0.end());
cout << "最小值: " << *(ans.first) << endl;
cout << "最大值: " << *(ans.second) << endl;
double avg1 = accumulate(v0.begin(), v0.end(), 0)/v0.size();
cout << "均值: " << fixed << setprecision(2) << avg1 << endl;
cout << endl;
vector<int> v1{v0};
cout << "v0: ";
output(v0);
sort(v1.begin(), v1.end());
double avg2 = accumulate(v1.begin()+1, v1.end()-1, 0)/(v1.size()-2);
cout << "去掉最大值、最小值之后,均值: " << avg2 << endl;
}
编译结果:
任务3:
编写程序,实现判断回文串
代码:#include <iostream>
#include <string>
#include <algorithm>
bool is_palindrome(std::string s);
int main() {
using namespace std;
string s;
while(cin >> s) // 多组输入,直到按下Ctrl+Z后结束测试
cout << boolalpha << is_palindrome(s) << endl;
}
// 函数is_palindrom定义
// 待补足
// ×××
根据上面代码我们可知判断逻辑还未完成,所以我们只需要对翻转后的字符串与源字符串进行比较即可
待补全代码:bool is_palindrome(std::string s)
{
std::string reversed_s(s.rbegin(),s.rend());
return reversed_s == s;
}
编译结果:
任务4:
编写程序实现进制转换
代码:#include <iostream>
#include <string>
#include <algorithm>
std::string dec2n(int x, int n = 2);
int main() {
using namespace std;
int x;
while(cin >> x) {
cout << "十进制: " << x << endl;
cout << "二进制: " << dec2n(x) << endl;
cout << "八进制: " << dec2n(x, 8) << endl;
cout << "十六进制: " << dec2n(x, 16) << endl << endl;
}
}
// 函数dec2n定义
// 待补足
// ×××
当我们进行十进制数转换为其他进制时,被除数对除数进行取余操作,并在取余之后对被除数进行除10的操作,直到被除数商为0为止,这时候余数进行倒序排序便是被转换之后的数
但如果余数有大于10的怎么办呢?比如说我们进行10转16进制,这个时候我们要对余数进行处理,判断是否大于10,再按照A-F进行处理
待补全代码:std::string dec2n(int x,int n)
{
if(x==0) return "0";
std::string s;
char digit;
while(x!=0)
{
int reminder = x%n;
if(reminder<10)
{
digit = '0'+reminder;
} else
{
digit = 'A'+(reminder-10);
}
s+=digit;
x/=n;
}
std::string reversed_s(s.rbegin(),s.rend());
return reversed_s;
}
编译结果:
任务5:
编写一个程序,在屏幕上打印字母密文对照表。
代码:#include <iostream>
#include <iomanip>
using namespace std;
void outPassword() {
const int alphabetSize = 26;
char alphabetStart = 'a';
// 打印原始字母表作为标题行
cout << " " <<" ";
for (char x = alphabetStart; x <= alphabetStart + alphabetSize - 1; ++x) {
cout << setw(2) << x;
}
cout << endl;
// 打印凯撒密码表
for (int shift = 0; shift < alphabetSize; ++shift) {
cout << setw(2) << shift << " ";
for (char x = alphabetStart; x <= alphabetStart + alphabetSize - 1; ++x) {
char shiftedChar = 'a' + (x - alphabetStart + shift) % alphabetSize;
cout << setw(2) << shiftedChar;
}
cout << endl;
}
}
int main() {
outPassword();
return 0;
}
编译结果:
任务6:
编写一个程序,实现自动生成算术运算题目并自动评测。
代码:#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;
// 生成随机数,范围在[min, max]之间
int randInRange(int min, int max) {
return min + rand() % (max - min + 1);
}
// 生成随机的算术题目
void generateQuestion(int& num1, char& operation, int& num2, int& answer) {
int opType = rand() % 4; // 0: 加, 1: 减, 2: 乘, 3: 除
num1 = randInRange(1, 10);
num2 = 1; // 初始化为1,稍后再根据运算类型调整
answer = 0; // 初始化为0,稍后再计算正确答案
switch (opType) {
case 0: // 加法
operation = '+';
num2 = randInRange(1, 10);
answer = num1 + num2;
break;
case 1: // 减法
operation = '-';
num2 = randInRange(1, num1 - 1); // 确保num1 > num2
answer = num1 - num2;
break;
case 2: // 乘法
operation = '*';
num2 = randInRange(1, 10);
answer = num1 * num2;
break;
case 3: // 除法
operation = '/';
// 找到一个能整除num1的num2
for (int i = 1; i <= num1; ++i) {
if (num1 % i == 0) {
num2 = i;
answer = num1 / num2;
break;
}
}
// 注意:这里假设了总能找到一个除数(因为num1在1到10之间,所以总能被1整除)
// 在实际应用中,可能需要更复杂的逻辑来确保总能生成题目
break;
}
}
int main() {
srand(time(0)); // 以当前时间作为随机数种子,确保每次运行生成的题目不同
int correctCount = 0;
for (int i = 0; i < 10; ++i) {
int num1, num2, userAnswer, correctAnswer;
char operation;
generateQuestion(num1, operation, num2, correctAnswer);
// 输出题目
cout << num1 << " " << operation << " " << num2 << " = ";
cin >> userAnswer;
// 判断答案是否正确
if (userAnswer == correctAnswer) {
correctCount++;
}
}
// 计算并输出正确率
double accuracy = static_cast<double>(correctCount) / 10 * 100;
cout << fixed << setprecision(2) << "正确率: " << accuracy << "%" << endl;
return 0;
}
编译结果: