实验1 现代C++编程初体验
实验1 现代C++编程初体验
实验一
源代码:
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 6 template<typename T> 7 void output(const T& c); 8 9 void test1(); 10 void test2(); 11 void test3(); 12 13 int main() { 14 std::cout << "测试1: \n"; 15 test1(); 16 17 std::cout << "\n测试2: \n"; 18 test2(); 19 20 std::cout << "\n测试3: \n"; 21 test3(); 22 } 23 24 template <typename T> 25 void output(const T& c) { 26 for (auto& i : c) 27 std::cout << i << ' '; 28 std::cout << '\n'; 29 } 30 31 void test1() { 32 using namespace std; 33 34 string s0{ "0123456789" }; 35 cout << "s0 = " << s0 << endl; 36 37 string s1(s0); 38 reverse(s1.begin(), s1.end()); 39 cout << "s1 = " << s1 << endl; 40 41 string s2(s0.size(), ' '); 42 reverse_copy(s0.begin(), s0.end(), s2.begin()); 43 cout << "s2 = " << s2 << endl; 44 } 45 46 void test2() { 47 using namespace std; 48 49 vector<int> v0{ 2, 0, 4, 9 }; 50 cout << "v0: "; output(v0); 51 52 vector<int> v1(v0); 53 reverse(v1.begin(), v1.end()); 54 cout << "v1: "; output(v1); 55 56 vector<int> v2(v0); 57 reverse_copy(v0.begin(), v0.end(), v2.begin()); 58 cout << "v2: "; output(v2); 59 } 60 61 void test3() { 62 using namespace std; 63 64 vector<int> v0{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 65 cout << "v0: "; output(v0); 66 67 vector<int> v1(v0); 68 rotate(v1.begin(), v1.begin() + 1, v1.end()); 69 cout << "v1: "; output(v1); 70 71 vector<int> v2(v0); 72 rotate(v2.begin(), v2.begin() + 2, v2.end()); 73 cout << "v2: "; output(v2); 74 75 vector<int> v3(v0); 76 rotate(v3.begin(), v3.end() - 1, v3.end()); 77 cout << "v3: "; output(v3); 78 79 vector<int> v4(v0); 80 rotate(v4.begin(), v4.end() - 2, v4.end()); 81 cout << "v4: "; output(v4); 82 }
运行测试截图:
回答问题:
问题1:reverse 和 reverse_copy 有什么区别?
答:reverse直接反转了输入的字符串元素,修改了原容器本身;
reverse_copy将输入的字符串元素反转后复制到目标容器,不修改原容器内容。
问题2: rotate 算法是如何改变元素顺序的?它的三个参数分别代表什么?
答:rotate算法调整了元素顺序:把从第一个参数位置开始,到第二个参数位置之前的所有元素,整体移到第三个参数位置的后面。
第一个参数:要移位的元素范围的起始处
第二个参数:移位后,放在最前面的元素的原来位置
第三个参数:要移位的元素范围的结束处,即最后一个元素的下一位
实验二
源代码:
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <numeric> 5 #include <iomanip> 6 #include <cstdlib> 7 #include <ctime> 8 9 template<typename T> 10 void output(const T &c); 11 12 int generate_random_number(); 13 void test1(); 14 void test2(); 15 16 int main() { 17 std::srand(std::time(0)); 18 std::cout << "测试1: \n"; 19 test1(); 20 21 std::cout << "\n测试2: \n"; 22 test2(); 23 } 24 25 template <typename T> 26 void output(const T &c) { 27 for(auto &i : c) 28 std::cout << i << ' '; 29 std::cout << '\n'; 30 } 31 32 int generate_random_number() { 33 return std::rand() % 101; 34 } 35 36 void test1() { 37 using namespace std; 38 39 vector<int> v0(10); 40 generate(v0.begin(), v0.end(), generate_random_number); 41 cout << "v0: "; output(v0); 42 43 vector<int> v1{v0}; 44 sort(v1.begin(), v1.end()); 45 cout << "v1: "; output(v1); 46 47 vector<int> v2{v0}; 48 sort(v2.begin()+1, v2.end()-1); 49 cout << "v2: "; output(v2); 50 } 51 52 void test2() { 53 using namespace std; 54 55 vector<int> v0(10); 56 generate(v0.begin(), v0.end(), generate_random_number); 57 cout << "v0: "; output(v0); 58 59 auto min_iter = min_element(v0.begin(), v0.end()); 60 auto max_iter = max_element(v0.begin(), v0.end()); 61 cout << "最小值: " << *min_iter << endl; 62 cout << "最大值: " << *max_iter << endl; 63 64 auto ans = minmax_element(v0.begin(), v0.end()); 65 cout << "最小值: " << *(ans.first) << endl; 66 cout << "最大值: " << *(ans.second) << endl; 67 68 double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size(); 69 cout << "均值: " << fixed << setprecision(2) << avg1 << endl; 70 71 sort(v0.begin(), v0.end()); 72 double avg2 = accumulate(v0.begin()+1, v0.end()-1, 0.0) / (v0.size()-2); 73 cout << "去掉最大值、最小值之后,均值: " << avg2 << endl; 74 }
运行测试截图:
回答问题:
1 generate(v0.begin(), v0.end(), [](){return std::rand()%101;});
答:用法:这是一个无参数的 lambda 表达式,功能与自定义函数 generate_random_number 完全相同,都是生成一个 0-100 范围的随机数;
使用场景:当代码逻辑简单、且只当前位置使用一次 时,用 lambda 表达式更简洁,无需单独定义函数,减少代码编写者负担。
实验三
源代码:
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 23 if (c == 'Z') 24 return 'A'; 25 26 if (std::isalpha(c)) 27 return static_cast<unsigned char>(c + 1); 28 29 return c; 30 } 31 32 void test1() { 33 std::string s1{"Hello world 2049!"}; 34 std::cout << "s1 = " << s1 << '\n'; 35 36 std::string s2; 37 for (auto c : s1) 38 s2 += std::tolower(c); 39 std::cout << "s2 = " << s2 << '\n'; 40 41 std::string s3; 42 for (auto c : s1) 43 s3 += std::toupper(c); 44 std::cout << "s3 = " << s3 << '\n'; 45 } 46 47 void test2() { 48 std::string s1{"I love cosmos!"}; 49 std::cout << "s1 = " << s1 << '\n'; 50 51 std::string s2(s1.size(), ' '); 52 std::transform(s1.begin(), s1.end(), 53 s2.begin(), 54 func); 55 std::cout << "s2 = " << s2 << '\n'; 56 }
测试运行截图:
回答问题:
实验四
源代码:
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cctype> 5 6 bool is_palindrome(const std::string& s); 7 bool is_palindrome_ignore_case(const std::string& s); 8 9 int main() { 10 using namespace std; 11 string s; 12 13 // 多组输入,直到按下Ctrl+Z结束测试 14 while (cin >> s) { 15 cout << "区分大小写:" << boolalpha << is_palindrome(s) << "\n"; 16 cout << "不区分大小写:" << is_palindrome_ignore_case(s) << "\n\n"; 17 } 18 } 19 // 函数is_palindrome定义 20 bool is_palindrome(const std::string& s) { 21 int left = 0, right = s.size() - 1; 22 while (left < right) { 23 if (s[left] != s[right]) { 24 return false; 25 } 26 left++; 27 right--; 28 } 29 return true; 30 } 31 // 函数is_palindrome_ignore_case定义 32 bool is_palindrome_ignore_case(const std::string& s) { 33 std::string temp = s; 34 std::transform(temp.begin(), temp.end(), temp.begin(), ::tolower); 35 int left = 0, right = temp.size() - 1; 36 while (left < right) { 37 if (temp[left] != temp[right]) { 38 return false; 39 } 40 left++; 41 right--; 42 } 43 return true; 44 }
运行测试截图:
回答问题:
实验五
源代码:
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 19 // 函数dec2n定义 20 std::string dec2n(int x, int n) { 21 if (x == 0) { 22 return "0"; 23 } 24 25 std::string result; 26 while (x > 0) { 27 int remainder = x % n; 28 char digit; 29 30 if (remainder < 10) { 31 digit = '0' + remainder; 32 } 33 else { 34 digit = 'A' + remainder - 10; 35 } 36 37 result.push_back(digit); 38 x /= n; 39 } 40 41 std::reverse(result.begin(), result.end()); 42 return result; 43 }
测试运行截图:
实验六
源代码:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 int main() { 6 cout << " "; 7 for (int i = 0; i < 26; i++) { 8 cout << char('a' + i); 9 if (i < 25) cout << " "; 10 } 11 cout << endl; 12 13 string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 14 for (int i = 1; i <= 26; i++) { 15 cout << i; 16 17 for (int j = 0; j < 26; j++) { 18 int index = (j + i) % 26; 19 cout << " " << str[index]; 20 } 21 cout << endl; 22 } 23 24 return 0; 25 }
测试运行截图:
实验七:
源代码:
1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <iomanip> 5 using namespace std; 6 7 int main() { 8 srand(static_cast<unsigned int>(time(0))); 9 10 int correctCount = 0; 11 const int questions = 10; 12 13 for (int i = 0; i < questions; ++i) { 14 int num1 = rand() % 10 + 1; 15 int num2 = rand() % 10 + 1; 16 int op = rand() % 4; 17 18 int answer, canswer; 19 char opChar; 20 21 switch (op) { 22 case 0: 23 opChar = '+'; 24 canswer = num1 + num2; 25 break; 26 case 1: 27 if (num1 < num2) { 28 swap(num1, num2); 29 } 30 opChar = '-'; 31 canswer = num1 - num2; 32 break; 33 case 2: 34 opChar = '*'; 35 canswer = num1 * num2; 36 break; 37 case 3: 38 while (num2 == 0 || num1 % num2 != 0) { 39 num1 = rand() % 10 + 1; 40 num2 = rand() % 10 + 1; 41 } 42 opChar = '/'; 43 44 canswer = num1 / num2; 45 break; 46 } 47 48 cout << num1 << " " << opChar << " " << num2 << " = "; 49 cin >> answer; 50 51 if (answer == canswer) { 52 correctCount++; 53 } 54 } 55 56 double accuracy = static_cast<double>(correctCount) / questions * 100; 57 cout << "正确率:" << fixed << setprecision(2) << accuracy << "%" << endl; 58 59 return 0; 60 }
测试运行截图:
实验总结:
(1)c++中有许多已经封装好的可以直接使用的函数,使得程序代码变得简洁,但是增加了程序员的记忆负担,需要在一次次的使用中加深印象并且学会使用(此事在前后端开发中亦有记载,什么功能都有,但是要用的时候记不起来)
(2)C++标准库的使用中容器与算法的分离设计有效的提升了代码灵活性,比如同样的sort算法,既能排序vector字段,也能排序string字段,泛用性强。
(3)这些实验灵活组合使用现代C++基础语言特性和标准库,使我慢慢开始从c语言到c++语法的转变并且能够用c++解决基础的编程问题。