考研计算机机试指南笔记
注意:该笔记并没有数据结构和图论部分的笔记(但是机试还真就考了二叉排序树。。)所以本帖子权当抛砖引玉。
考研计算机机试指南pdf自取:
链接:https://pan.baidu.com/s/1wKW08rRuwjcWyVPvmLwT3A?pwd=76c8
提取码:76c8
常用算法
排序
冒泡排序
日期类问题
计算日期间隔
#include <iostream>
#include <math.h>
# define ISYEAP(x) x % 4 == 0 && x % 100!= 0 || x % 400 == 0 ? 1 : 0
using namespace std;
int dayOfMonth[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
struct Date {
int day;
int month;
int year;
void nextDay() {
day++;
if (day > dayOfMonth[month][ISYEAP(year)]) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
};
int buf[10000][13][32];
int main() {
Date tmp;
int cnt = 0;
tmp.day = 1; tmp.month = 1; tmp.year = 0;
while(tmp.year < 10000) {
buf[tmp.year][tmp.month][tmp.day] = cnt;
tmp.nextDay();
cnt++;
}
int d1, m1, y1, d2, m2, y2;
while(scanf("%4d%2d%2d", &y1, &m1, &d1)!= EOF) {
scanf("%4d%2d%2d", &y2, &m2, &d2);
cout << abs(buf[y2][m2][d2] - buf[y1][m1][d1]) + 1 << endl;
}
return 0;
}
计算星期几
#include <iostream>
#include <math.h>
#include<string.h>
# define ISYEAP(x) x % 4 == 0 && x % 100!= 0 || x % 400 == 0 ? 1 : 0
using namespace std;
int dayOfMonth[13][2] = {
0,0,
31,31,
28,29,
31,31,
30,30,
31,31,
30,30,
31,31,
31,31,
30,30,
31,31,
30,30,
31,31
};
struct Date {
int day;
int month;
int year;
void nextDay() {
day++;
if (day > dayOfMonth[month][ISYEAP(year)]) {
day = 1;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
};
int buf[10000][13][32];
char monthName[13][20] = {
"",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
char weekName[7][20] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
int main() {
Date tmp;
int cnt = 0;
tmp.day = 1; tmp.month = 1; tmp.year = 0;
while(tmp.year < 10000) {
buf[tmp.year][tmp.month][tmp.day] = cnt;
tmp.nextDay();
cnt++;
}
int d, m, y;
char s[20];
while(scanf("%d %s %d", &d, s, &y)!= EOF) {
for(m = 1; m <= 12; m++) {
if(strcmp(s, monthName[m]) == 0) break;
}
int days = buf[y][m][d] - buf[2012][7][16];
days++;
cout << weekName[(days % 7 + 7) % 7] << endl;
}
return 0;
}
排版题
#include<iostream>
using namespace std;
int main(){
int outPutBuf[82][82];
char a, b;
int n;
bool firstCase = true;
while(cin >> n >> a >> b){
if(firstCase){
firstCase = false;
}
else{printf("\n");}
for(int i = 1, j = 1;i <= n;i+=2, j++){
int x = n/2 +1;
int y = x;
x -= j-1; y -= j-1;
char c = j%2 == 1? a : b;
for(int k = 1; k <= i; k++){
outPutBuf[x+k-1][y] = c;
outPutBuf[x][y+k-1] = c;
outPutBuf[x+k-1][y+i-1] = c;
outPutBuf[x+i-1][y+k-1] = c;
}
}
if(n !=1){
outPutBuf[1][1] = ' ';
outPutBuf[1][n] =' ';
outPutBuf[n][1] =' ';
outPutBuf[n][n] =' ';
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
printf("%c", outPutBuf[i][j]);
}
printf("\n");
}
}
return 0;
}
11 O X
XXXXXXXXX
XOOOOOOOOOX
XOXXXXXXXOX
XOXOOOOOXOX
XOXOXXXOXOX
XOXOXOXOXOX
XOXOXXXOXOX
XOXOOOOOXOX
XOXXXXXXXOX
XOOOOOOOOOX
XXXXXXXXX
查找
数学问题
找素数
平方法
bool judge(int x){
if(x <= 1) return false;
int bound = (int)sqrt(x);
for(int i = 2; i<=bound; i++){
if(x%i==0)return false;
}
return true;
}
埃氏筛法,太容易爆栈 了吧
bool mark[100001];
bool prime[100001];
int primeSize;
void init(){
primeSize = 0;
for(int i = 2; i <= 100000; i++){
if(mark[i] == false){
prime[primeSize++] = i;
if(i >= 1000) continue;
for(int j = i * i; j <= 100000; j+=i){
mark[j] = true;
}
}
}
}
“偶数长度的回文数”中只有11是素数,其他的都可以被11整除。
不存在 8 长度的素数。
分解素因数
#include <iostream>
using namespace std;
bool mark[100001]; // 标记数组,用于标记是否为素数
int prime[100001]; // 存储素数的数组
int primeSize; // 素数表的大小
// 初始化素数表
void init(){
// 初始化标记数组为false
for(int i = 0; i <= 100000; i++){
mark[i] = false;
}
primeSize = 0;
// 从2开始遍历到100000
for(int i = 2; i <= 100000; i++){
if(!mark[i]){
// 如果当前数未标记为非素数,则将其加入素数表
prime[primeSize++] = i;
if(i >= 1000) continue;
// 将当前素数的倍数标记为非素数
for(int j = i * i; j <= 100000; j += i){
mark[j] = true;
}
}
}
}
int main(){
init(); // 调用初始化函数初始化素数表
int n;
while(cin >> n){ // 不断读取输入的整数n
int ansPrime[30]; // 存储素因数的数组
int ansSize = 0; // 素因数个数
int ansNum[30]; // 存储素因数幂指数的数组
for(int i = 0; i < primeSize; i++){
if(n % prime[i] == 0){
// 当n能整除当前素数时
ansPrime[ansSize] = prime[i]; // 添加素因数到数组
ansNum[ansSize] = 0; // 初始化幂指数为0
while(n % prime[i] == 0){
ansNum[ansSize]++; // 不断除以素数,计算幂指数
n /= prime[i];
}
ansSize++; // 素因数个数加1
if(n == 1) break;
}
}
if(n != 1){
// 如果n不等于1,说明还有一个大于100000的素因数
ansPrime[ansSize] = n; // 添加素因数到数组
ansNum[ansSize] = 1; // 幂指数为1
ansSize++; // 素因数个数加1
}
int ans = 0;
// 计算所有素因数幂指数之和
for(int i = 0; i < ansSize; i++){
ans += ansNum[i];
}
// 输出结果
cout << ans << endl;
}
return 0;
}
#include <iostream>
using namespace std;
bool mark[100001];
int prime[100001];
int primeSize;
void init(){
for(int i = 0; i <= 100000; i++){
mark[i] = false;
}
primeSize = 0;
for(int i = 2; i <= 100000; i++){
if(!mark[i]){
prime[primeSize++] = i;
if(i >= 1000) continue;
for(int j = i * i; j <= 100000; j += i){
mark[j] = true;
}
}
}
}
int main(){
init();
int num, a;
cin >> num >> a;
int n = a;
int ansPrime[30];
int ansSize = 0;
int ansNum[30];
for(int i = 0; i < primeSize; i++){
if(n % prime[i] == 0){
// 素因数表中加上该素数
ansPrime[ansSize] = prime[i];
// 初始化幂指数为0
ansNum[ansSize] = 0;
while(n % prime[i] == 0){
ansNum[ansSize]++;
n /= prime[i];
}
// cout << prime[i] << "^" << ansNum[ansSize] << endl;
ansSize++;
if(n == 1) break;
}
}
if(n != 1){
ansPrime[ansSize] = n;
ansNum[ansSize] = 1;
ansSize++;
}
int nNum[30] ={0};
for(int i = 0; i < ansSize; i++){
for(int j = 2; j <= num; j++){
int tmp = j;
while(tmp % ansPrime[i] == 0){
nNum[i]++;
tmp /= ansPrime[i];
}
}
}
int maxNum = 0xFFFFFFF;
for(int i = 0; i < ansSize; i++){
if(nNum[i]/ansNum[i] < maxNum) maxNum = nNum[i]/ansNum[i];
}
cout << maxNum << endl;
return 0;
}
二分求幂
#include<iostream>
#include<math.h>
using namespace std;
int main(){
int a, b;
while(cin >> a >> b){
if(a == 0 && b == 0){
break; // 输入为0时结束循环
}
int cishu[50]; // 存储每一次b的二进制位数
int num_of_one = 0; // 1的个数
while(b != 0){
cishu[num_of_one++] = log2(b) + 1; // 计算b的二进制表示中1的个数
b = b - pow(2, (int)log2(b)); // 将b减去最高位的1
}
int res = 1; // 结果初始化为1
int now_ci = 1; // 当前幂次初始化为1
int tmp = a % 1000; // 临时变量,用于保存中间计算结果
for(int i = num_of_one - 1; i >= 0; i--){
while(now_ci < cishu[i]){
tmp = tmp * tmp % 1000; // 计算a的幂次方并取后三位
now_ci++;
}
res = res * tmp % 1000; // 计算最终结果并取后三位
}
cout << res << endl; // 输出结果
}
return 0;
}
#include<iostream>
#include<math.h>
using namespace std;
int main(){
int a, b;
while(cin >> a >> b){
if(a == 0 && b == 0){break;}
int ans = 1;
while(b != 0){
if(b % 2 == 1){
ans *= a;
ans %= 1000;
}
b /= 2;
a *= a;
a %= 1000;
}
cout << ans << endl;
}
return 0;
}
高精度整数
#include<iostream>
#include<string.h>
#include<iomanip>
using namespace std;
struct bigInteger{
int digit[1000];
int size;
void init(){
for(int i=0;i<1000;i++){
digit[i]=0;
}
size=0;
}
void set(char str[]){
init();
int L = strlen(str);
for(int i = L - 1, j = 0, t = 0, c = 1; i >= 0; i--){
// j是计数器
// c是数位权重
t += (str[i] - '0') * c;
j ++;
c *= 10;
if(j == 4 || i == 0){
digit[size++] = t;
t = 0;
j = 0;
c = 1;
}
}
}
void output(){
for(int i=size-1;i>=0;i--){
if(i != size - 1){
cout << setfill('0') << setw(4) << digit[i];
}
else{
cout << digit[i];
}
}
}
bigInteger operator + (const bigInteger &A) const{
bigInteger ret;
ret.init();
int carry = 0;
for(int i=0;i<size;i++){
int tmp = A.digit[i] + digit[i] + carry;
carry = tmp / 10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if(carry!= 0){
ret.digit[ret.size++] = carry;
}
return ret;
}
} a, b, c;
char str1[1002], str2[1002];
int main(int argc, char *argv[]) {
while(cin >> str1 >> str2){
a.set(str1);
b.set(str2);
c = a + b;
c.output();
cout << endl;
}
return 0;
}
搜索
递归
#include<iostream>
#include<string.h>
using namespace std;
int ans[22];
bool mark[22];
int n;
int prime[] = {2,3,5,7,11,13,17,19,23,29,31,37,41};
bool judge(int x){
for(int i = 0; i < sizeof(prime); i++){
if(prime[i] == x){return true;}
}
return false;
}
void check(){
if(judge(ans[n]+ans[1]) == false){
return;
}
for(int i = 1; i <= n; i++){
if(i!=1)cout << " ";
cout << ans[i];
}
cout << endl;
}
void DFS(int num){
if(num <= 0 || n == num){
check();
return;
}
for(int i = 1; i <= n; i++){
if(mark[i] == false && (judge(ans[num] + i) == true)){
mark[i] = true;
ans[num+1] = i;
DFS(num + 1);
mark[i] = false;
}
}
return;
}
int main(int argc, char *argv[]) {
int cas = 0;
while(cin >> n){
cas++;
for(int i = 0; i < sizeof(mark); i++){
mark[i] = false;
}
ans[1] = 1;
cout << "Case #" << cas << ": " << endl;
mark[1] = true;
DFS(1);
cout << endl;
}
return 0;
}
BFS
注意在set里插入自创的数据结构后要加bool operator<(const pos &p) const,应该是set内在插入时需要排序
#include<iostream>
#include<string.h>
#include<set>
using namespace std;
struct pos{
int x, y, z;
int time;
pos(int x, int y, int z, int time){
this->x = x;
this->y = y;
this->z = z;
this->time = time;
}
bool operator==(const pos &p) const
{
return (this->x == p.x) && (this->y == p.y) && (this->z == p.z);
}
bool operator<(const pos &p) const
{
if(this->x != p.x)
return (this->x < p.x);
else if(this->y!= p.y)
return (this->y < p.y);
else if(this->z!= p.z)
return (this->z < p.z);
else{
return this->time < p.time;
}
}
};
bool mark[50][50][50] = { 0 };
set<pos> list = {};
void forward(pos p0, int const a, int const b, int const c){
pos p1 = pos(p0.x + 1, p0.y, p0.z, p0.time + 1);
pos p2 = pos(p0.x, p0.y + 1, p0.z, p0.time + 1);
pos p3 = pos(p0.x - 1, p0.y, p0.z, p0.time + 1);
pos p4 = pos(p0.x, p0.y - 1, p0.z, p0.time + 1);
pos p5 = pos(p0.x, p0.y, p0.z + 1, p0.time + 1);
pos p6 = pos(p0.x, p0.y, p0.z - 1, p0.time + 1);
if(p1.x < a && !mark[p1.x][p1.y][p1.z]){
list.insert(p1);
mark[p1.x][p1.y][p1.z] = true;
}
if(p2.y < b && !mark[p2.x][p2.y][p2.z]){
list.insert(p2);
mark[p2.x][p2.y][p2.z] = 1;
}
if(p3.x > -1 && !mark[p3.x][p3.y][p3.z]){
list.insert(p3);
mark[p3.x][p3.y][p3.z] = true;
}
if(p4.y > -1 && !mark[p4.x][p4.y][p4.z]){
list.insert(p4);
mark[p4.x][p4.y][p4.z] = true;
}
if(p5.z < c && !mark[p5.x][p5.y][p5.z]){
list.insert(p5);
mark[p5.x][p5.y][p5.z] = true;
}
if(p6.z > -1 && !mark[p6.x][p6.y][p6.z]){
list.insert(p6);
mark[p6.x][p6.y][p6.z] = true;
}
if(list.find(p0) != list.end()){
list.erase(p0);
}
return;
}
int main(){
int n;
cin >> n;
while(n--){
int a, b, c, ddl;
cin >> a >> b >> c >> ddl;
int tmp;
for(int i=0; i<a; i++){
for(int j=0; j<b; j++){
for(int k=0; k<c; k++){
cin >> tmp;
mark[i][j][k] = (bool) tmp;
}
}
}
// 开始步进
pos p0 = pos(0, 0, 0, 0);
mark[p0.x][p0.y][p0.z] = 1;
list.insert(p0);
bool flag = 0;
int t = 0;
for(int i=0; i<=ddl; i++){
set<pos> tmpList;
copy(list.begin(), list.end(), inserter(tmpList, tmpList.begin()));
for(auto it : tmpList){
if(it.x == a - 1 && it.y == b - 1 && it.z == c - 1)
{
flag = 1;
break;
}
forward(it, a, b, c);
}
if(flag == 1){
t = i;
break;
}
}
if(flag){
cout << t << endl;
}
else{
cout << -1 << endl;
}
list.clear();
}
return 0;
}
1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0
11
可以认为是在(x,y,z)空间中以初始状态为(S,0,0)以互相倾倒为转换函数的寻找(S/2,0,S/2)或者(S/2,S/2,0)为结果的状态
动态规划
错排公式
错排问题,是组合数学中的问题之一。考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为D(n)。 研究一个排列错排个数的问题,叫做错排问题或称为更列问题。
最长公共子序列问题(考)
动态规划技巧
注意到任意选择一对物品,其累积的疲劳度为两个物品重量差的平方,在所有被选择的物品中任选两对,假设四个物品重量分别为a、b、c、d(a<=b<=c<=d),此时可能存在两种配对方案。
\(\begin{aligned} &(a-b)*(a-b)+(c-d)*(c-d) \\ &-(a-c)^*(a-c)+(b-d)^*(b-d) \\ &=2(ac+bd)-2(ab+cd) \\ &=2(a(c-b)+d(b-c)) \\ &=2(c-b)(a-d) \end{aligned}\)
因为c>=b而d>=a,所以,两式相减的差必为非正数。即,第一种方案中的疲劳度必不大于第二种配对方案中的疲劳度。由该分析可知,在选定的最优方案中,任选两对组合,其配对情况必为重量最大物品和重量次大物品为一对、重量最小物品和重量次小物品为一对,不存在交叉组合的情况。同时,当个两个物品的重量差越小时,其差的平方也越小,所以每一对组合的两个物品重量,必为原物品中重量相邻的两个物品。
综上所述,其状态转移方程为(设经过排序后第i件物品重量为list[i]):
\(dp[i][j]=\min\{dp[i][j-1],dp[i-1][j-2]+(list[j]-list[j-1])^2\}\)
本题大意:有一堆柑橘,重量为0到2000,总重量不大于2000。要求我们从中取出两堆放在扁担的两头且两头的重量相等,问符合条件的每堆重量最大为多少。没有符合条件的分堆方式则输出-1。
首先,我们只考虑柑橘重量为非0的情况。
因为本题要求解的是重量相等的两堆柑橘中每堆的最大重量,并且在堆放过程中,由于新的柑橘被加到第一堆或者第二堆,两堆之间的重量差会动态发生改变,所以我们设状态d[i][j]表示前i个柑橘被选择后(每个柑橘可能放到第一堆或者第二堆)后,第一堆比第二堆重j时(当j为负时表示第二堆比第一堆重),两堆的最大总重量和。
初始时,d[0][0]为0,即不往两堆中加任何柑橘时,两堆最大总重量为0; dp[0][j] (j不等于0)为负无穷,即其它状态都不存在。
根据每一个新加入的柑橘被加入到第一堆或者第二堆或者不加到任何一堆,设当前加入柑橘重量为list[i],这将造成第一堆与第二堆的重量差增大list[i]的或减小list[i]或者不变,我们在它们之中取最大值,其状态转移为:
\(\begin{aligned}&dp[i][j]=\max(dp[i-1][j-list[i]]+list[i],dp[i-1][j+list[i]]+list[i],dp[i-1][j]);\end{aligned}\)
当根据该状态转移方程求出所有的状态后,状态dp[n][0]/2即是所求。
我们再来考虑柑橘重量包含0的情况,当在不考虑柑橘重量为0,推得dp[n[0]为正数时,柑橘重量为0的柑橘将不对答案造成任何影响,固在这种情况时可直接排除重量为0的柑橘。当在不考虑柑橘重量为0,推得dp[n][0]为0时,即不存在任何非0的组合使两堆重量相等。此时,若存在重量为0的柑橘,则可组成两堆重量为0的柑橘(至少有一个柑橘重量为0),它们重量相等;否则,将不存在任何分堆方式,输出-1。
背包问题
0-1背包
\(dp[j]=\max\{dp[j-list[i].w]+\nu,dp[j]\};\)
多重背包
在该例中,对每个物品的总数量进行了限制,即多重背包问题。我们对每种物品进行拆分,使物品数量大大减少,同时通过拆分后的物品间的组合又可以组合出所有物品数量的情况。
其他技巧
滚动数组
初版
优化
滚动数组优化后
常用函数
strcmp
strcmp
函数是 C++ 标准库中的一个字符串比较函数,用于比较两个以 null 结尾的 C 字符串(也就是字符数组)是否相等,并返回比较结果。这个函数通常用于判断两个字符串是否相等,或者确定一个字符串在字典中的顺序。
int strcmp(const char* str1, const char* str2);
函数的返回值是一个整数,它表示了比较结果:
- 如果
str1
小于str2
,则返回一个负数(通常是 -1)。 - 如果
str1
等于str2
,则返回 0。 - 如果
str1
大于str2
,则返回一个正数(通常是 1)。
const char* str1
是一个指向 C 风格字符串的指针,而不是 C++ 标准库中的 std::string
类型。虽然你可以将一个 std::string
对象转换为 C 风格字符串,但它们是不同的数据类型。
如果你有一个 std::string
对象,你可以使用 c_str()
方法来获取一个指向 C 风格字符串的指针,然后将其传递给 strcmp
函数进行比较
std::string str1 = "hello";
const char* str2 = "world";
int result = std::strcmp(str1.c_str(), str2);
c_str()
c_str()
是 C++ 标准库中 std::string
类的一个成员函数,用于返回一个指向包含 std::string
内容的 null 终止 C 风格字符串(也称为字符数组)的指针。这个函数允许你将 std::string
对象中的字符串数据以 C 风格字符串的形式提取出来,以便与需要 C 风格字符串的函数进行交互。
const char* c_str() const;
atoi()
str.c_str()
:std::string
类的成员函数c_str()
返回一个指向以 null 结尾的 C 风格字符串(即字符数组)的指针,这个字符串包含了std::string
中的数据。这个指针通常用于与旧的 C 函数或需要 C 风格字符串的函数进行交互。atoi()
:是一个 C 标准库函数,它接受一个以 null 结尾的 C 风格字符串,并尝试将其解析为整数。如果字符串合法并包含整数文本,atoi()
函数将返回相应的整数值;如果无法解析或包含非法字符,它将返回 0。
include <stdlib.h>
atoi(str.c_str())
返回int类型值
sort()
include
sort
函数是 C++ 标准库中的一个用于排序容器中元素的函数。它可用于对数组、向量(std::vector
)、列表(std::list
)等容器类型的元素进行排序。排序的方式可以是升序(默认)或降序,取决于你提供的比较函数或运算符。
bool descending(int a, int b) {
return a > b;
}
int main() {
std::vector<int> numbers = {5, 2, 9, 1, 5, 6};
// 使用自定义的降序排序比较函数
std::sort(numbers.begin(), numbers.end(), descending);
}
也可以使用重载 的方式
to_string()
to_string()
函数是 C++ 标准库中的一个函数,它用于将各种基本数据类型(如整数、浮点数、长整数等)转换为对应的字符串表示形式。这个函数非常有用,因为它允许你将数值数据转换为字符串,以便进行字符串操作、输出到屏幕或者保存到文件等操作。
#include <string>
std::string to_string(int val);
std::string to_string(long val);
std::string to_string(long long val);
std::string to_string(unsigned val);
std::string to_string(unsigned long val);
std::string to_string(unsigned long long val);
std::string to_string(float val);
std::string to_string(double val);
std::string to_string(long double val);
reverse(res.begin(),res.end())
C++ 标准库中的 std::reverse
函数也可以用于反转容器中的元素,而且更加通用,可以用于多种容器类型(如向量、列表、字符串等)。
// 使用 std::reverse 函数反转向量
std::reverse(numbers.begin(), numbers.end());
setfill()和setw()
setfill()
是 C++ 中用于格式化输出的一部分,它是 <iomanip>
头文件中的一种输出控制符(omanipulators)。这个控制符用于设置填充字符,以确保输出的字段具有一定的宽度并在需要时用指定的字符填充。
std::setw()
是 C++ 中用于格式化输出的一种输出控制符(omanipulator)。它是 <iomanip>
头文件中的函数,用于设置输出流的字段宽度,以确保输出的数据在特定宽度的字段内对齐或填充。
运算符重载
bigInteger operator + (const bigInteger &A) const{
}
在C++中,这里的两个const
关键字是用于修饰成员函数的,它们有不同的含义:
- 第一个
const
位于成员函数参数列表的最后,如你的代码所示。
这个const
表明该成员函数是一个常量成员函数。在常量成员函数内部,你不能修改该类的成员变量。这通常用于表明这个成员函数不会对调用它的对象做任何修改,从而提供了更强的安全性和一致性。
- 第二个
const
位于参数A
前面:
const bigInteger &A
这个const
表示参数A
是一个常量引用。在函数内部,你不能修改参数A
所引用的值。这也是一种安全性和性能方面的考虑,因为它避免了不必要的拷贝操作,并确保参数A
在函数内部不会被修改。
所以,这两个const
结合在一起,表示这个成员函数是一个常量成员函数,它不会修改调用它的对象,并且接受一个常量引用作为参数,不会修改参数引用的对象。
fixed和setprecision()
std::fixed
来确保浮点数的小数点后保留指定精度(这里是 3 位),然后使用 std::setprecision(3)
来设置小数点后的精度为 3 位。
例如
cout << setw(6) << fixed << setprecision(3) << stu[i].score[j] << "\t";
strlen()
strlen()
函数是C和C++标准库中常用的字符串处理函数之一,用于计算一个以null结尾的字符串的长度,即字符串中字符的数量,不包括null终止符(\0
)。
size_t strlen(const char *str);
tolower()
tolower()
是C和C++标准库中的函数,用于将字符转换为小写字母。它是字符处理和文本处理中常用的函数之一。
erase()
erase()
函数是C++标准库中的 std::string
类的成员函数,用于从字符串中删除指定范围的字符。它的作用是修改调用它的字符串对象,使其不包含被删除的字符。以下是关于 erase()
函数的一些重要信息:
- 函数原型:
erase()
函数有多种重载形式,其中最常用的形式如下:
string& erase(size_t pos = 0, size_t count = npos);
pos
:要删除字符的起始位置(默认为0,即字符串的开头)。count
:要删除的字符数量(默认为npos
,表示删除从pos
开始到字符串末尾的所有字符)。
这是 erase()
函数的基本原型,还有其他重载形式,允许你指定不同的参数,例如删除单个字符、删除一个子字符串等。
- 返回值:
erase()
函数返回一个对修改后的字符串的引用,通常是调用函数的字符串对象。
find()
find()
函数是C++标准库中的 std::string
类的成员函数,用于在字符串中查找指定子字符串或字符的位置。它的作用是返回第一次出现指定子字符串或字符的位置索引。以下是关于 find()
函数的一些重要信息:
- 函数原型:
find()
函数有多种重载形式,其中最常用的形式如下:
size_t find(const string& str, size_t pos = 0) const;
str
:要查找的子字符串。pos
:从哪个位置开始查找(默认为0,即从字符串的开头开始)。
这是 find()
函数的基本原型,还有其他重载形式,允许你指定不同的参数,例如查找单个字符、查找多个字符等。
- 返回值:
find()
函数返回一个size_t
类型的值,表示查找到的子字符串或字符的位置索引。如果未找到匹配项,则返回一个特殊值string::npos
,通常是一个很大的无符号整数,表示未找到。
copy()
和inserter(tmpList, tmpList.begin())
copy(list.begin(), list.end(), inserter(tmpList, tmpList.begin()));
这行代码使用了 C++ 中的标准库函数 copy
,结合了 inserter
函数来复制一个列表(list
)的元素到另一个列表(tmpList
)中。这个操作通常用于将一个容器的内容复制到另一个容器中,特别是当目标容器的大小需要动态调整时,或者当你想要在目标容器中插入而不是覆盖元素时。
copy()
:这是 C++ 标准库中的一个算法函数,用于复制一个范围内的元素到另一个范围中。它接受三个参数:- 第一个参数是要复制的元素的开始迭代器。
- 第二个参数是要复制的元素的结束迭代器。
- 第三个参数是目标容器的起始位置的迭代器。
list.begin()
和list.end()
:这些是list
容器的成员函数,分别返回容器的起始和结束迭代器,表示复制操作的源范围。inserter(tmpList, tmpList.begin())
:inserter
函数是 C++ 标准库中的一个插入迭代器适配器,它用于在容器中插入元素,而不是覆盖它。这里我们将它用于tmpList
容器,并将tmpList.begin()
作为插入的起始位置。这意味着copy
函数会将list
中的元素复制到tmpList
的起始位置之前,而不会覆盖tmpList
中的任何现有元素。
所以,这行代码的作用是将 list
容器中的元素复制到 tmpList
容器中,同时保留了 tmpList
中已有的元素,如果有的话。这是一个常见的操作,用于将一个容器的内容合并到另一个容器中,而不丢失原有的数据。