实验一
实验任务1:
源代码:

1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 6 // 模板函数声明 7 template<typename T> 8 void output(const T &c); 9 10 void test1(); 11 void test2(); 12 void test3(); 13 14 int main() { 15 std::cout << "测试1: \n"; 16 test1(); 17 18 std::cout << "\n测试2: \n"; 19 test2(); 20 21 std::cout << "\n测试3: \n"; 22 test3(); 23 } 24 25 // 输出容器对象c中的元素 26 template <typename T> 27 void output(const T &c) { 28 for(auto &i : c) 29 std::cout << i << ' '; 30 std::cout << '\n'; 31 } 32 33 // 测试1:组合使用算法库、迭代器、string反转字符串 34 void test1() { 35 using namespace std; 36 37 string s0{"0123456789"}; 38 cout << "s0 = " << s0 << endl; 39 40 string s1(s0); 41 // 反转s1自身 42 reverse(s1.begin(), s1.end()); 43 cout << "s1 = " << s1 << endl; 44 45 string s2(s0.size(), ' '); 46 // 将s0反转后结果拷贝到s2,s0自身不变 47 reverse_copy(s0.begin(), s0.end(), s2.begin()); 48 cout << "s2 = " << s2 << endl; 49 } 50 51 // 测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据 52 void test2() { 53 using namespace std; 54 55 vector<int> v0{2, 0, 4, 9}; 56 cout << "v0: "; output(v0); 57 58 vector<int> v1{v0}; 59 reverse(v1.begin(), v1.end()); 60 cout << "v1: "; output(v1); 61 62 vector<int> v2{v0}; 63 reverse_copy(v0.begin(), v0.end(), v2.begin()); 64 cout << "v2: "; output(v2); 65 } 66 67 // 测试3:组合使用算法库、迭代器、vector实现元素旋转移位 68 void test3() { 69 using namespace std; 70 71 vector<int> v0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 72 cout << "v0: "; output(v0); 73 74 vector<int> v1{v0}; 75 // 将[v1.begin(), v1.end())区间内元素循环左移1位 76 rotate(v1.begin(), v1.begin()+1, v1.end()); 77 cout << "v1: "; output(v1); 78 79 vector<int> v2{v0}; 80 // 将[v1.begin(), v1.end())区间内元素循环左移2位 81 rotate(v2.begin(), v2.begin()+2, v2.end()); 82 cout << "v2: "; output(v2); 83 84 vector<int> v3{v0}; 85 // 将[v1.begin(), v1.end())区间内元素循环右移1位 86 rotate(v3.begin(), v3.end()-1, v3.end()); 87 cout << "v3: "; output(v3); 88 89 vector<int> v4{v0}; 90 // 将[v1.begin(), v1.end())区间内元素循环右移2位 91 rotate(v4.begin(), v4.end()-2, v4.end()); 92 cout << "v4: "; output(v4); 93 }
运行截图:
1.reverse和reverse_copy有什么区别?
reverse是反转原序列,原序列改变了;reverse_copy是将原序列反转后复制入新序列,原序列未改变。
2.rotate算法是如何改变元素顺序的?它的三个参数分别代表什么?
将(begen,end)区间内的元素进行循环移位,将中间参数位置以及之后的元素移动到起始,原首元素到中间参数元素的前一个元素的部分会被移至序列末尾。第一个参数是初始范围的起点,第二个参数是位移分界点,第三个参数是初始范围的终点。
实验任务2:
源代码:

#include <iostream> #include <vector> #include <algorithm> #include <numeric> #include <iomanip> #include <cstdlib> #include <ctime> // 模板函数声明 template<typename T> void output(const T &c); int generate_random_number(); void test1(); void test2(); int main() { std::srand(std::time(0)); // 添加随机种子 std::cout << "测试1: \n"; test1(); std::cout << "\n测试2: \n"; test2(); } // 输出容器对象c中的元素 template <typename T> void output(const T &c) { for (auto &i : c) std::cout << i << ' '; std::cout << '\n'; } // 返回[0, 100]区间内的一个随机整数 int generate_random_number() { return std::rand() % 101; } // 测试1:对容器类对象指定迭代器区间赋值、排序 void test1() { using namespace std; vector<int> v0(10); // 创建一个动态数组对象v0,对象大小为10 generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0 cout << "v0: "; output(v0); vector<int> v1{v0}; sort(v1.begin(), v1.end()); // 对整个vector排序 cout << "v1: "; output(v1); vector<int> v2{v0}; sort(v2.begin() + 1, v2.end() - 1); // 只对中间部分排序,不包含首尾元素 cout << "v2: "; output(v2); } // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 void test2() { using namespace std; vector<int> v0(10); generate(v0.begin(), v0.end(), generate_random_number); cout << "v0: "; output(v0); // 求最大值和最小值 auto min_iter = min_element(v0.begin(), v0.end()); auto max_iter = max_element(v0.begin(), v0.end()); cout << "最小值: " << *min_iter << endl; cout << "最大值: " << *max_iter << 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.0) / v0.size(); cout << "均值: " << fixed << setprecision(2) << avg1 << endl; sort(v0.begin(), v0.end()); double avg2 = accumulate(v0.begin() + 1, v0.end() - 1, 0.0) / (v0.size() - 2); cout << "去掉最大值、最小值之后,均值: " << avg2 << endl; }
运行截图:
问题1:
generrater算法用于通过调用指定的生成函数,为容器中的每个元素赋值。
问题2:
minmax_element可以在遍历一遍后找出最小和最大元素,相比min_element和max_element时间复杂度更低,效率更高。
问题3:
效果是一样的,lambda中的[]是捕获列表,()是参数列表,{return std::rand()%101;}是函数体。
实验任务3:
源代码:

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cctype> 5 6 unsigned char func(unsigned char c); 7 8 void test1(); 9 void test2(); 10 11 int main() { 12 std::cout << "测试1:字符串大小写转换\n"; 13 test1(); 14 15 std::cout << "\n测试2:字符变换\n"; 16 test2(); 17 } 18 19 unsigned char func(unsigned char c) { 20 if (c == 'z') 21 return 'a'; 22 if (c == 'Z') 23 return 'A'; 24 if (std::isalpha(c)) 25 return static_cast<unsigned char>(c + 1); 26 return c; 27 } 28 29 void test1() { 30 std::string s1{"Hello world 2049!"}; 31 std::cout << "s1 = " << s1 << '\n'; 32 33 std::string s2; 34 for (auto c : s1) 35 s2 += std::tolower(c); 36 std::cout << "s2 = " << s2 << '\n'; 37 38 std::string s3; 39 for (auto c : s1) 40 s3 += std::toupper(c); 41 std::cout << "s3 = " << s3 << '\n'; 42 } 43 44 void test2() { 45 std::string s1{"I love cosmos!"}; 46 std::cout << "s1 = " << s1 << '\n'; 47 48 std::string s2(s1.size(), ' '); 49 std::transform(s1.begin(), s1.end(), 50 s2.begin(), 51 func); 52 std::cout << "s2 = " << s2 << '\n'; 53 }
运行截图:
问题一:
若输入字符是'z'
,返回'a'
;若输入字符是'Z'
,返回'A'
。对于其他字母字符返回该字符的下一个字符
问题二:
tolower将大写字母变成小写,toupper将小写字母变成大写
问题三:
第 1 个参数:输入序列的起始
第 2 个参数:输入序列的结束
第 3 个参数:输出序列的起始,存放转换后的结果
第 4 个参数:用于转换的函数
如果把第 3 个参数s2.begin()
改成s1.begin()
,那么转换后的结果会直接覆盖原字符串中的内容,而不是输出到新的字符串中
实验任务4:
源代码:

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 bool is_palindrome(const std::string &s); 5 bool is_palindrome_ignore_case(const std::string &s); 6 7 int main() { 8 using namespace std; 9 string s; 10 11 // 多组输入,直到按下Ctrl+Z结束测试 12 while (cin >> s) { 13 cout << boolalpha 14 << "区分大小写: " << is_palindrome(s) << "\n" 15 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 16 } 17 } 18 19 // 函数is_palindrome定义 20 bool is_palindrome(const std::string &s) { 21 int left = 0; 22 int right = s.size() - 1; 23 while (left < right) { 24 if (s[left] != s[right]) { 25 return false; 26 } 27 left++; 28 right--; 29 } 30 return true; 31 } 32 // 函数is_palindrome_ignore_case定义 33 bool is_palindrome_ignore_case(const std::string &s) { 34 int left = 0; 35 int right = s.size() - 1; 36 while (left < right) { 37 if (toupper(s[left]) != toupper(s[right])) { 38 return false; 39 } 40 left++; 41 right--; 42 } 43 return true; 44 }
运行截图:
问题:
可以改用 getline(cin, s)
函数进行输入
实验任务5:
源代码:

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 5 std::string dec2n(int x, int n = 2); 6 7 int main() { 8 int x; 9 while(std::cin >> x) { 10 std::cout << "十进制: " << x << '\n' 11 << "二进制: " << dec2n(x) << '\n' 12 << "八进制: " << dec2n(x, 8) << '\n' 13 << "十二进制: " << dec2n(x, 12) << '\n' 14 << "十六进制: " << dec2n(x, 16) << '\n' 15 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 16 } 17 } 18 //函数dec2的定义 19 std:: string dec2n(int x,int n){ 20 if(x==0) 21 return "0"; 22 const std::string num = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 23 std::string result; 24 while(x>0){ 25 int remainder=x%n; 26 result=result+num[remainder]; 27 x/=n; 28 } 29 std::reverse(result.begin(), result.end()); 30 return result; 31 }
运行截图:
实验任务6:
源代码:

1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <algorithm> 5 6 using namespace std; 7 8 template <typename T> 9 void output(const T &c) { 10 for (auto &i : c) 11 cout << i << ' '; 12 cout << '\n'; 13 } 14 15 int main() { 16 int x = 1; 17 //初始化v0 18 vector<string>v0; 19 for(char ch='a';ch<='z';++ch) 20 v0.push_back(string(1,ch)); 21 cout<<" "; output(v0); 22 //建新组temp将v0中字符大写 23 vector<string> temp=v0; 24 for(string &s:temp){ 25 for(char &c:s) 26 c=toupper(c); 27 } 28 rotate(temp.begin(), temp.begin()+1, temp.end()); 29 while (x <=26) { 30 //数字对齐 31 if(x<10) 32 cout <<" "<< x << " "; 33 else{ 34 cout<< x << " "; 35 } 36 37 output(temp); 38 x++; 39 rotate(temp.begin(), temp.begin()+1, temp.end()); 40 } 41 return 0; 42 }
运行截图:
实验任务7:
源代码:

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cstdlib> 5 #include <ctime> 6 #include <iomanip> 7 using namespace std; 8 int main(){ 9 srand(time(0)); 10 int count=0; 11 double total=10; 12 for(int i=0;i<total;i++){ 13 //取随机数及运算符 14 int num1=rand()%10+1; 15 int num2=rand()%10+1; 16 int op=rand()%4; 17 int uanswer,canswer; 18 char oper; 19 //减法 20 if(op==1){ 21 if(num1<num2) 22 swap(num1,num2); 23 oper='-'; 24 canswer=num1-num2; 25 //除法 26 } 27 else if(op==3){ 28 while(num1%num2!=0||num2==0){ 29 num1=rand()%10+1; 30 num2=rand()%10+1; 31 } 32 oper='/'; 33 canswer=num1/num2; 34 } 35 //加法 36 else if(op==0){ 37 oper='+'; 38 canswer=num1+num2; 39 } 40 //乘法 41 else if(op==2){ 42 oper='*'; 43 canswer=num1*num2; 44 } 45 cout<<num1<<oper<<num2<<'='; 46 cin>>uanswer; 47 if(uanswer==canswer) 48 count++; 49 50 } 51 //计算正确率 52 double accuracy=static_cast<double>(count)/total*100; 53 cout<<"正确率:"<<fixed<<setprecision(2)<<accuracy<<"%"<<endl; 54 return 0; 55 }
运行截图: