心之所向,素履以往

阔论Cpp

2024-09-17

鉴于大一糟糕的C语言体验和学校老师堪忧的教学质量,故本学期下定决心恶补C/Cpp相关知识(

此博客持续更新,旨在记录一些重点、易错点、遗忘点以及二次元美图


基操勿6

stdIO

整数输入输出:

1
2
3
int a, b;
cin >> a >> b;
cout << a + b << endl;

字符串:

1
2
3
string str;
cin >> str;
cout << str;

cout << “woof” << endl;cout << “woof\n”; 等同。

格式化输出 - 小数/科学计数法/字符串の限位:

1
2
3
cout << format( “{:.2f} {:.3e} {:.4s}\n", 3.14159, 12345.678, "abcdef") << endl;

// 输出:3.14 1.235e+04 abcd

输出地址:

1
2
3
4
char c = 'a';
cout << (void*)&c << endl;

// output: 0x971c1ff99f

string的比较:

>, <, >=, <=, ==, !=

传参:

1)按值(x)main()外部调用main()内部参数时,参数改动不影响其真实值。
2)按引用(&x):外部调用内部参数时,参数值同步改变。

数组:

1
*a == a[] == a[LENGTH];

多维数组形参除第一维外,其余必须指定。

1
2
3
4
5
6
7
8
// 访问数组元素的不同方法

int arr[5] = {1,2,3,4,5};
int *ptr = arr;
// 三者等同:
cout << arr[3];
cout << *(ptr+3);
cout << ptr[3];

条件运算符?:

condition ? consequent : alternative
condition 表达式的计算结果必须为 true 或 false。 若 condition 的计算结果为 true,将计算 consequent,其结果成为运算结果;若 condition 的计算结果为 false,将计算 alternative,其结果成为运算结果。


类与结构体:

类:

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
#include<iostream>
using namespace std;

class Person {

private:
int age, height;
double money;
string books[100];
public:
string name;

Person(string _name, int _age) {
name = _name;
age = _age;
money = 1000;
}

Person(string _name, int _age, double _money) : name(_name), age(_age), money(_money) {}

void say() {
cout << "I'm " << name << endl;
}

void add_money(double x) {
money += x;
}

void set_age(int x) {
age = x;
}
};

int main() {
class Person c("yxc", 18, 10086);
c.name = "qbt";
c.set_age(18);
c.add_money(10000);
c.say();
return 0;
}

// output:
// I'm qbt

结构体:

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
#include<iostream>
using namespace std;

struct Person {

int age, height;
double money;
string books[100];
string name;

Person(string _name, int _age) {
name = _name;
age = _age;
money = 1000;
}

Person(string _name, int _age, double _money) : name(_name), age(_age), money(_money) {}

void say() {
cout << "I'm " << name << endl;
}

void add_money(double x) {
money += x;
}

void set_age(int x) {
age = x;
}
};

int main() {
class Person c("yxc", 18, 10086);
c.name = "qbt";
c.set_age(18);
c.add_money(10000);
c.say();
return 0;
}

// output:
// I'm qbt

class默认变量私有struct默认公有
两者构造差不多,上述示例做参考。

数据结构重点!

链表

1
2
3
4
5
6
7
8
9
// define
struct Node {
int val; Node* next;
}

int main() {
Node *node = new Node(1); // 正确,此处传引用
Node *node = Node(1); // 错误,此处指Node型变量,传值
}

堆/栈

1
2
3
4
5
6
7
8
9
10
11
12
13
                    RAM Space
·-----------------·
Stacks | | func() call; |
(Downwards) | | local val…… |
| | |
↓ | |
| |
|`````````````````|
Heaps ↑ | global val…… |
(Upwards) | | |
| | |
| | |
·-----------------·

STL

#include <vector>

vector是变长数组,支持随机访问,不支持在任意位置 O(1) 插入。为了保证效率,元素的增删一般应该在末尾进行。

size函数返回vector的实际长度(包含的元素个数),empty函数返回一个bool类型,表明vector是否为空。二者的时间复杂度都是***O(1)***。
所有的STL容器都支持这两个方法,含义也相同,之后我们就不再重复给出。

clear函数会清空vector容器。

迭代器就像STL容器的“指针”,可以用星号*操作符解除引用。
一个保存intvector的迭代器声明方法为:

1
vector<int>::iterator it;

若想直接访问迭代器的值,需要在变量前* 例如*i

vector的迭代器是“随机访问迭代器”,可以把vector的迭代器与一个整数相加减,其行为和指针的移动类似。可以把vector的两个迭代器相减,其结果也和指针相减类似,得到两个迭代器对应下标之间的距离。

begin函数返回指向vector中第一个元素的迭代器。例如a是一个非空的vector,则*a.begin()a[0]的作用相同。

所有的容器都可以视作一个“前闭后开”的结构,end函数返回vector的尾部,即第n个元素再往后的“边界”。*a.end()a[n]都是越界访问,其中n = a.size()

下面两份代码都遍历了vector<int> a,并输出它的所有元素。

1
2
3
4
5
for (int i = 0; i < a.size(); i ++)
cout << a[i] << endl;

for (vector<int>::iterator it = a.begin(); it != a.end(); it ++)
cout << *it << endl;

front函数返回vector的第一个元素,等价于*a.begin()a[0]
back函数返回vector的最后一个元素,等价于*--a.end()a[a.size() – 1]

a.push_back(x)把元素x插入到vector a的尾部。
b.pop_back()删除vector a的最后一个元素。

来源https://www.acwing.com/file_system/file/content/whole/index/content/3598249/

技巧

好题共赏

动物

给定你三个葡萄牙语单词,这些词将根据下表从左到右定义一个动物。
OI
请你确定并输出这个动物的名称。

输入格式
根据上表,输入包含三个单词,每行一个,用以识别动物,单词由小写字母构成。

输出格式
输出识别出的动物的名称。

题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

int main() {
string s[3]; string sF;
for(int i=0; i<3; i++) {
cin>> s[i]; sF+= s[i][0];
}

if(sF=="vac") cout<< "aguia";
if(sF=="vao") cout<< "pomba";
if(sF=="vmo") cout<< "homem";
if(sF=="vmh") cout<< "vaca";
if(sF=="iih") {
if(s[2] == "hematofago") cout<< "pulga";
else cout<< "lagarta";
}
if(sF=="iah") cout<< "sanguessuga";
if(sF=="iao") cout<< "minhoca";
}

点的坐标

给定两个保留一位小数的浮点数X,Y,用来表示一个点的横纵坐标。
请你判断该点在坐标系中的位置。

输入格式
共一行,包含两个浮点数X,Y,表示点的横纵坐标。

输出格式
如果点在第一象限,则输出 Q1,在第二象限,则输出 Q2,以此类推。
如果点在原点处,则输出 Origem。
否则,如果点在x坐标上,则输出 Eixo X,在y坐标上,则输出 Eixo Y。

数据范围
-10.0≤X,Y≤10.0

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>

using namespace std;

int main() {
double x, y;
cin >> x >> y;
if (x == 0 && y == 0) cout << "Origem";
else if (x * y == 0) cout << (x == 0 ? "Eixo X" : "Eixo Y");
else if (x > 0) cout << (y > 0 ? "Q1" : "Q4");
else cout << (y > 0 ? "Q2" : "Q3");

return 0;
}

C++,危险又优雅~
cum!