2022年暑假ACM集训周记 - 第一周

First Post:

Last Update:

Word Count:
2.6k

Read Time:
11 min

0x01 第一天

学习内容

  • C++基础循环:for & while
C++ 共 22 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream> // C++标准输入输出流头文件
#include <cstdio> // C++中C语言标准输入输出头文件
#include <bits/stdc++.h> // Linux gnu gcc上万能头文件,不是所有的OJ都适用
using namespace std; // C++的标准库因为有命名空间,所以要加这行
int main(int argc, const char* argv[]) {
int a,b;
char c[20];
/** 多组样例输入数据的循环方法 */
while (scanf("%d %d", &a, &b) != EOF) {}
while (scanf("%d %d", &a, &b) == 2) {}
while (scanf("%d %d", &a, &b) != -1) {}
while (~scanf("%d %d", &a, &n)) {} // 结果取反法,推荐使用
while (cin >> a >> b) {}// C++ std::cin多样例输入使用方法
while (gets(c)) {} // 采用gets整行读入,不过gets有缓存溢出漏洞,不推荐使用
// fgets(字符串变量, 要读入的最大字符串大小, 从中读取字符的流);
// 标准输入流(键盘)为stdin,标准输出流(屏幕)为stdout,错误输出流(屏幕)为stderr
while (fgets(c, 20, stdin)) {} // 采用更安全的fgets替换gets读入整行
/** 标准for循环 */
// for(参数定义; 循环条件; 参数更新) {}
for (int i = 0; i < 10; i++) {}
return 0;
}
  • 标准输入输出流重定向
C++ 共 11 行
展开
1
2
3
4
5
6
7
8
9
10
11
#define DEBUG
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]) {
#ifdef DEBUG
freopen("data.in", "r", stdin); // 将data.in的内容仅读入并重定向到stdin,实现模拟键盘输入
freopen("data.out", "w", stdout); // 将stdout输出的内容重定向写入到文件data.out中
#endif
// 程序代码
return 0;
}
  • 文件读写
C++ 共 16 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]) {
FILE *fin, *fout; // 定义两个文件指针,一个输入一个输出
int x;
fin = fopen("data.in", "rb"); // 以二进制读入的方式打开文件,并将文件指针传给fin
fout = fopen("data.out", "wb"); // 以二进制写入的方式打开文件,并将文件指针传给fout
// 如果要从标准输入输出流读写,就将标准输入输出流地址传给文件指针
fin = stdin;
fout = stdout;
fscanf(fin,"%d",&x); // 从文件中进行格式化读取
fprintf(fout,"%d\n",x); // 将变量内容格式化输出到文件中
fclose(fin); // 关闭文件流,解除文件占用,当使用stdin和stdout时不用fclose
fclose(fout);
return 0;
}
  • C++基础输入输出
C++ 共 14 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <fstream> // 文件流头文件
using namespace std;
int main(int argc, const char* argv[]) {
int x, y;
cin >> x >> y; // 基础输入,std::cin
cout << x << y << endl; // 基础输出std::cout 和换行+清空缓冲区std::endl
// std::endl 相当于 '\n' 和 std::flush(刷新缓冲区)的结合体
ifstream in("data.in"); // 创建输入文件流对象
ofstream out("data.out"); // 创建输出文件流对象
in >> x >> y; // 将文件流内容读入到变量
out << x << y << endl; // 将变量内容写入到文件流
return 0;
}
  • 64位整数类型
C++ 共 13 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]) {
long long x; // 长整型 long long,也称64位整型
// 以下两种变量同理,可能有的编译器无法通过编译
int64_t y;
__int64 z;
scanf("%lld",&x); // 使用scanf读入长整型时采用%lld
cin >> x; // cin读入时无需特别处理
printf("%lld",x); // printf输出时也是使用%lld
cout << x << endl; // cout输出无需特别处理
return 0;
}
  • 浮点数按精度比较
C++ 共 8 行
展开
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]) {
for (double i = 0; i != 10; i += 0.1) {} // 由于精度问题,i永远不可能等于10,所以会陷入无限循环
for (double i = 0; i <= 10; i += 0.1) {} // 当 i > 10.0时就会停止运行,可行
for (double i = 0; fabs(10 - i) > 1e-5; i += 0.1) {} // 采用绝对值进行精度比较,更加精确
return 0;
}
  • 编码规范
C++ 共 9 行
展开
1
2
3
4
5
6
7
8
9
// K&R方式编码
#include <iostream>
using namespace std;
int main(int argc, const char* argv[]) { // 大括号与函数同行,而不是另起一行
for (int i = 0; i < 10; i++) {} // 变量定义在离使用最近的地方,如只在for循环里使用的变量就在for处定义
// 定义常量采用const修饰变量,而不是采用define进行宏定义
const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
return 0;
}

0x02 第二天

学习内容

  • 数组
C++ 共 19 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstring> // memset和memcpy在C语言的string.h中

using namespace std;

int x[16384]; // 过大的数组不能定义在函数内部,要定义在函数外部,避免爆栈

int main(int argc, const char* argv[]) {
int y[64]; // 数组定义时可以仅指定大小不初始化
int m[64] = {0}; // 也可以定义大小的同时将整个数组进行初始化
int z[] = {1,2,3,4,5}; // 也可以不定义大小,直接输入数据创建指定大小和数据的数组
// C语言的内存初始化函数,将指定数组的指定位数初始化为指定值.
// memset(要初始化的数组, 初始化的值, 初始化的大小);
memset(y, 0, 64);
// 数组复制函数,将z数组中指定的前5个值复制到y数组
// memcpy(目标数组,源数组,复制值的数量);
memcpy(y, z, sizeof(int) * 5);
return 0;
}
  • 字符串
C++ 共 70 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <sstream> // 字符串流
#include <cstring> // C的字符串处理库
#include <string> // C++ string类
#include <cctype> // C的类型库

using namespace std;

int main(int argc, const char* argv[]) {
char a[] = "Hello World"; // 字符串,即字符数组,可以采用赋值字符串确定数组大小。
char b[20] = {'H','E','L','L','O','\0'}; // 以数组方式初始化字符串
char c[20]; // 不赋值创建字符串变量
string d; // C++字符串初始化
string e = "function"; // C++字符串带赋值的初始化
/** C语言字符串应用 */
printf("%s",a); // 直接输出字符串
memset(a,0,strlen(a)); // 清空字符串
// strcpy(存储复制内容的字符数组, 要复制的字符串);
strcpy(c, "hello c"); // 将字符串内容存入c变量
// strcat(存储追加内容的字符数组, 要追加的字符串);
strcat(c, "have fun"); // 将字符串内容追加到c变量后面
// strncpy(存储复制内容的字符数组, 要复制的字符串, 复制的字符数);
strncpy(c, a, 2); // 将a字符串中前两个字符复制到c变量,覆盖原本内容
// strcmp(参与比较的字符串1, 参与比较的字符串2)
if (strcmp(a, b) == 0) {} // a字符串和b字符串相等
if (strcmp(a, b) > 0) {} // a字符串大于b字符串
if (strcmp(a, b) < 0) {} // a字符串小于b字符串
int l = strlen(c); // 获取字符串长度
sscanf(c,"%c",&c); // 从字符串中按格式读入变量
sprintf(c,"%d",1); // 将格式化输出内容存入字符串
if (strchr(c,'h') != NULL) {} // 查找字符串中首次出现某个字符的位置

/** C++字符串应用 */
cin >> d; // 标准输入流输入字符串
cout << d; // 标准输出流输出字符串
printf("%s",e.c_str()); // 将字符串转成C样式以采用printf输出
// 求字符串长度,size和length同样效果
int x = d.size();
x = d.length();
d.clear(); // 清空字符串
d.at(0); // 访问字符串中指定位置的字符
d[0]; // 访问字符串中指定位置的字符
d += "a"; // 类似strcat的效果
if (d == e) {} // 类似strcmp的效果
d = "hello world"; // 替换字符串内容为新串
getline(cin, e); // 一次性读入一整行字符串,不会因为空格停下
int pos = d.find('h'); // 查找字符串中出现指定字符的首个位置

/** 字符读取 */
char cc = fgetc(stdin); // 从文件流中读取字符
char ch = getchar(); // 从标准输入流中读取字符

/** 字符类型判断和转换 */
bool dight = isdigit(ch); // 判断是不是数字
bool alpha = isalpha(ch); // 判断是不是英文字母
bool upper = isupper(ch); // 判断是不是大写英文字母
bool lower = islower(ch); // 判断是不是小写英文字母
bool print = isprint(ch); // 判断是否是可打印字符
toupper(ch); // 英文小写转大写
tolower(ch); // 英文大写转小写

/** 字符串流 */
stringstream ss; // 创建字符串流
ss << e; // 将字符串输入流
e >> ss; // 将流输入变量
sscanf(ss,"%d",&c); // 将流内容进行格式化读入
sprintf(ss,"%d",1); // 将变量内容格式化输出到流
return 0;
}
  • 函数重载和运算符重载
C++ 共 27 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
using namespace std;
/** 函数重载 */
int sum(int a, int b) {
return a + b;
} // 第一个重载,只能两个变量相加

int sum(int a[], int size) {
for (int i = 1; i < size; i++) {
a[0] += a[i];
}
return a[0];
} // 第二个重载,可以实现数组求和

class stu {
public:
stu operator+(const stu& a) {
stu st;
st.id = this -> id + a.id;
st.name = this -> name + a.name;
return st;
}
private:
int id;
string name;
}; // C++运算符重载,代表是string的运算符处理

函数重载可以实现同名同返回值函数不同处理逻辑,简化调用过程。

运算符重载主要用在自定义变量的代码可读性提升

  • 内存申请和释放
C++ 共 18 行
展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

int main(int argc, const char* argv[]) {
int *a = (int*)malloc(sizeof(int) * 10); //C语言申请一段连续的内存空间,相当于定义数组
int *b = (int*)malloc(sizeof(int)); // C语言申请一个变量
free(a); // 释放数组
free(b); // 释放变量

int *c = new int; // 创建变量
int *d = new int(10); // 创建变量并赋值10
int *e = new int[10]; // 创建该变量类型的数组
delete c; // 释放变量空间
delete d; // 释放变量空间
delete[] e; // 释放数组空间
return 0;
}