实验1 现代c++基础编程
任务1:
源代码task1.cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
template<typename T>
void output(const T &c);
void test1();
void test2();
void test3();
int main() {
std::cout << "测试1: \n";
test1();
std::cout << "\n测试2: \n";
test2();
std::cout << "\n测试3: \n";
test3();
}
template <typename T>
void output(const T &c) {
for(auto &i : c)
std::cout << i << ' ';
std::cout << '\n';
}
void test1() {
using namespace std;
string s0("0123456789");
cout << "s0 = " << s0 << endl;
string s1(s0);
reverse(s1.begin(), s1.end());
cout << "s1 = " << s1 << endl;
string s2(s0.size(), ' ');
reverse_copy(s0.begin(), s0.end(), s2.begin());
cout << "s2 = " << s2 << endl;
}
void test2() {
using namespace std;
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);
}
void test3() {
using namespace std;
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());
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);
}
运行结果截图:

问题:
reverse:原地反转,直接修改原容器。
reverse_copy:复制反转,不改变原容器,将反转结果复制到新容器中。
改变顺序:以中间迭代器为界,将后半部分元素移到前面,前半部分移到后面(循环左移)。
三个参数:first(区间起点),middle(旋转分界点,旋转后成为新首元素),last(区间终点)。
任务2:
源代码task2.cpp
#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();
}
template <typename T>
void output(const T &c) {
for(auto &i : c)
std::cout << i << ' ';
std::cout << '\n';
}
int generate_random_number() {
return std::rand() % 101;
}
void test1() {
using namespace std;
vector<int> v0(10);
generate(v0.begin(), v0.end(), generate_random_number);
cout << "v0: "; output(v0);
vector<int> v1(v0);
sort(v1.begin(), v1.end());
cout << "v1: "; output(v1);
vector<int> v2(v0);
sort(v2.begin()+1, v2.end()-1);
cout << "v2: "; output(v2);
}
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. 遍历指定区间,将无参函数的返回值依次赋值给区间内的每个元素(常用于填充数据)。
2.效率更高:只需遍历一次容器,就能同时找到最大值和最小值,减少了遍历次数。
3.适用于简短、只用一次的代码逻辑,无需单独定义函数,使代码更紧凑直观(如示例中的生成随机数)。
任务3:
源代码task3.cpp
#include <iostream> #include <string> #include <algorithm> #include <cctype> unsigned char func(unsigned char c); void test1(); void test2(); int main() { std::cout << "测试1: 字符串大小写转换\n"; test1(); std::cout << "\n测试2: 字符变换\n"; test2(); } unsigned char func(unsigned char c) { if(c == 'z') return 'a'; if(c == 'Z') return 'A'; if(std::isalpha(c)) return static_cast<unsigned char>(c+1); return c; } void test1() { std::string s1{"Hello World 2049!"}; std::cout << "s1 = " << s1 << '\n'; std::string s2; for(auto c : s1) s2 += std::tolower(c); std::cout << "s2 = " << s2 << '\n'; std::string s3; for(auto c : s1) s3 += std::toupper(c); std::cout << "s3 = " << s3 << '\n'; } void test2() { std::string s1{"I love cosmos!"}; std::cout << "s1 = " << s1 << '\n'; std::string s2(s1.size(), ' '); std::transform(s1.begin(), s1.end(), s2.begin(), func); std::cout << "s2 = " << s2 << '\n'; }
运行结果截图:

问题:
1.将字母替换为字母表中的下一个字母('z'变'a','Z'变'A'),非字母字符不变。
2.tolower:将大写字母转为小写。
toupper:将小写字母转为大写。
3.改为 s1.begin() 会将转换结果直接覆盖到原字符串 s1 上(原地修改);使用 s2.begin() 则是将结果存入新字符串,不改变原串。
任务4
源代码task4.cpp
#include <iostream> #include <string> #include <algorithm> bool is_palindrome(const std::string &s) { return std::equal(s.begin(), s.begin() + s.size() / 2, s.rbegin()); } bool is_palindrome_ignore_case(const std::string &s) { std::string s_lower = s; std::transform(s_lower.begin(), s_lower.end(), s_lower.begin(), ::tolower); return is_palindrome(s_lower); } int main() { using namespace std; string s; while(cin >> s) { cout << "区分大小写: " << (is_palindrome(s) ? "true" : "false") << "\n" << "不区分大小写: " << (is_palindrome_ignore_case(s) ? "true" : "false") << "\n\n"; } return 0; }
运行结果截图:

思考:输入带空格的字符串不能用 cin >> s,应该用 getline(cin, s),它会读取整行直到遇到换行符。
任务5
源代码task5.cpp
#include <iostream> #include <string> #include <algorithm> std::string dec2n(int x, int n = 2) { if (x == 0) return "0"; std::string res; const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; while (x > 0) { res += digits[x % n]; x /= n; } std::reverse(res.begin(), res.end()); return res; } int main() { int x; while (std::cin >> x) { std::cout << "十进制: " << x << '\n' << "二进制: " << dec2n(x) << '\n' << "八进制: " << dec2n(x, 8) << '\n' << "十二进制: " << dec2n(x, 12) << '\n' << "十六进制: " << dec2n(x, 16) << '\n' << "三十二进制: " << dec2n(x, 32) << "\n\n"; } return 0; }
运行结果截图:

任务6
源代码tassk6.cpp
#include <iostream> int main() { char letters[] = "abcdefghijklmnopqrstuvwxyz"; std::cout << " " << letters << '\n'; for (int i = 1; i <= 26; ++i) { if (i < 10) std::cout << ' '; std::cout << i << ' '; for (int j = 0; j < 26; ++j) { char upper_c = static_cast<char>('A' + (j + i - 1) % 26); std::cout << upper_c; } std::cout << '\n'; } return 0; }
运行结果截图:

任务7
源代码task7.cpp
#include <iostream> #include <cstdlib> #include <ctime> #include <iomanip> int main() { std::srand(std::time(0)); int correct_count = 0; char ops[] = {'+', '-', '*', '/'}; for (int i = 0; i < 10; ++i) { int a = std::rand() % 10 + 1; int b = std::rand() % 10 + 1; char op = ops[std::rand() % 4]; int ans = 0; if (op == '-') { if (a < b) std::swap(a, b); ans = a - b; } else if (op == '/') { ans = a / b; a = ans * b; } else if (op == '+') { ans = a + b; } else if (op == '*') { ans = a * b; } std::cout << a << " " << op << " " << b << " = "; int user_ans; std::cin >> user_ans; if (user_ans == ans) { correct_count++; } } double accuracy = (double)correct_count / 10.0 * 100; std::cout << "正确率: " << std::fixed << std::setprecision(2) << accuracy << "%" << std::endl; return 0; }
运行结果截图:

实验总结:这次实验让我感觉C++比C语言写起来省事多了。不用自己费劲写循环去处理数组和字符串,直接调用现成的vector、string和自带的算法(比如排序、反转)就能轻松搞定,代码又短又好读。我还体验了Lambda表达式和自动循环这些新写法,确实很灵活。不过也踩了点小坑,比如混用cin和getline读数据时会出错,得加ignore清理一下。总的来说,这次实验让我初步摸到了C++方便高效的编程路子。
浙公网安备 33010602011771号