C++(一)
前言
以前学习的C++忘得差不多了,因此重新学习一下并完善一下以前不理解的知识内容.大部分内容来自OI wiki,更完整内容可以前去观看链接.
以以下代码为例
#include <iostream> // 引用头文件
using namespace std;
// 引入命名空间(相关阅读 https://oi-wiki.org/lang/namespace/#using )
int main() { // 定义 main 函数
cout << "Hello, world!"; // 输出 Hello, world!
return 0; // 返回 0,结束 main 函数
}
#include
include
是一个预处理命令,include<>
尖括号里面为一个头文件,程序编译时将头文件内的内容链接到程序里编译(如cin
,cout
,printf
等)
using namespace std;
意为使用一个名为std的空间名.
std
为C++的命名空间,引入命名空间的目的是解决复杂项目中名字的冲突问题.例如:
假设自己定义了一个cin
变量,但是std库中也含有cin
,那么我们可以使用如下方式解决冲突
#include<iostream>
//此处无using namespace std;因为我们不希望使用std命名空间使得cin定义冲突
int main(){
定义cin
cin....//使用自己定义的cin
std::cin<<....//使用std中的cin
.....
return 0;
}
int main()
main是一个程序的入口.,程序执行或者调用时仅执行或调用main函数
高级数据结构
数组
定义:(int,char,long,bool,double,flat....) a[Num][Num]
.
如int a[100]
定义一个长度为100的整数数组(下标从0~99).
多维数组:char [100][100]
注意:过大数组尽量使用全局变量,局部变量会放在动态区(栈区)可能会造成溢出.
全局变量则会放在静态区未引用时仅使用空间.
结构体
定义:
struct Object{
int learn;
int point;
}MAP[100];
结构体的主要作用是将变量捆绑在一起.
值得注意的是,结构体在储存时可能存在实际大小比定义大小更大
原因如下:
为了访问内存的效率更高,编译器在处理结构中成员的实际存储情况时,可能会将成员对齐在一定的字节位置,也就意味着结构中有空余的地方。因此,该结构所占用的空间可能大于其中所有成员所占空间的总和。
指针
指针,即只想储存地址的特殊变量.用途极广(同时也很难).
指针变量的定义:
类型名后加*
.如int* a
;
要想访问指针变量地址所对应的空间(又称指针所 指向 的空间),需要对指针变量进行 解引用(dereference),使用 * 符号。
int main() {
int a = 123; // a: 123
int* pa = &a;
*pa = 321; // a: 321
}
对结构体变量也是类似。如果要访问指针指向的结构中的成员,需要先对指针进行解引用,再使用 . 成员关系运算符。不过,更推荐使用“箭头”运算符 -> 这一更简便的写法。
struct ThreeInt {
int a;
int b;
int c;
};
int main() {
ThreeInt x{1, 2, 3}, y{6, 7, 8};
ThreeInt* px = &x;
(*px) = y; // x: {6,7,8}
(*px).a = 4; // x: {4,7,8}
px->b = 5; // x: {4,5,8}
}
指针的偏移
指针变量也可以 和整数 进行加减操作。对于 int 型指针,每加 1(递增 1),其指向的地址偏移 32 位(即 4 个字节);若加 2,则指向的地址偏移 2 × 32 = 64 位。同理,对于 char 型指针,每次递增,其指向的地址偏移 8 位(即 1 个字节)。
使用指针偏移访问数组
我们前面说过,数组是一块连续的存储空间。而在 C/C++ 中,直接使用数组名,得到的是数组的起始地址。
int main() {
int a[3] = {1, 2, 3};
int* p = a; // p 指向 a[0]
*p = 4; // a: [4, 2, 3]
p = p + 1; // p 指向 a[1]
*p = 5; // a: [4, 5, 3]
p++; // p 指向 a[2]
*p = 6; // a: [4, 5, 6]
}
关于指针更进阶的应用可访问(OI Wiki)[https://oi-wiki.org/lang/pointer/]
本文的大部分内容均来自此网站.
文件操作
- freopen
FILE* freopen(const char* filename, const char* mode, FILE* stream);
- filename 要打开的文件名
- mode 文件打开方式(文件访问权限)
- stream 文件指针,通常使用标准文件流 (stdin/stdout) 或标准错误输出流 (stderr)
常用mode: - r:只读,文件必须存在
- w:只写,文件必须存在
- r+:读/写,文件必须存在
- w+:读/写,文件不存在则新建文件,否则清空后写入.
其他: - rb:只读打开二进制文件,文件必须存在
- wb:只写打开二进制文件,文件不存在则新建文件,否则清空后写入.
- rb+:读/写打开二进制文件,文件必须存在
- wb+:读/写打开二进制文件,文件不存在则新建文件,否则清空后写入.
- a:以附加方式打开只写文件,文件不存在将新建文件,写入数据将被附加在文件末尾(保留 EOF 符)
- a+:以附加方式打开只写文件,文件不存在将新建文件,写入数据将被附加在文件末尾(不保留 EOF 符)
- at+:以读写方式打开文本文件,写入数据将被附加在文件末尾
- ab+:以读写方式打开二进制文件,写入数据将被附加在文件末尾
例子:
#include <cstdio>
#include <iostream>
int main(void) {
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
/*
中间的代码不需要改变,直接使用 cin 和 cout 即可
*/
fclose(stdin);
fclose(stdout);
return 0;
}