Skip to content

Commit 21a283f

Browse files
committed
c++ 高级operator
1 parent 0268f95 commit 21a283f

File tree

22 files changed

+1228
-0
lines changed

22 files changed

+1228
-0
lines changed

000_1_10-文件和stream/main.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <fstream>
2+
#include <iostream>
3+
4+
using namespace std;
5+
6+
int main() {
7+
char data[100];
8+
9+
// 以写模式打开文件
10+
ofstream outfile;
11+
outfile.open("app.txt");
12+
13+
cout << "write to the file ..." << endl;
14+
cout << "Input your name:" << endl;
15+
cin.getline(data, 100); // 100-1
16+
17+
// 向文件写入用户输入的数据
18+
outfile << data << endl;
19+
20+
cout << "Input your age:" << endl;
21+
cin >> data;
22+
cin.ignore(); // 它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响
23+
// 再次向用户写入输入的数据
24+
outfile << data << endl;
25+
26+
// 关闭打开的文件
27+
outfile.close();
28+
29+
// 以读模式打开文件
30+
ifstream infile;
31+
infile.open("app.txt");
32+
33+
cout << "Reading from the file" << endl;
34+
infile >> data;
35+
cout << data << endl;
36+
37+
// 再次从文件读取数据,并显示
38+
infile >> data;
39+
cout << data << endl;
40+
41+
infile.close();
42+
43+
return 0;
44+
}

000_1_10-文件和stream/readme.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
[toc]
2+
3+
# 1: file & stream
4+
5+
- iostream 标准库,它提供了 cin 和 cout 方法分别用于从标准输入读取流和向标准输出写入流。
6+
- 本教程介绍如何从文件读取流和向文件写入流。这就需要用到 C++ 中另一个标准库 fstream
7+
- 标准库`fstream`;
8+
9+
| 数据类型 | describe |
10+
| :--------- | :--------------------------------------------------------------------------------------------- |
11+
| `ofstream` | 该类型表示输出文件流,用于创建文件并向文件写入信息 |
12+
| `ifstream` | 该类型表示输入文件流,用于从文件读取信息 |
13+
| `fstream` | 表示文件流,同时具有 ofstream 和 ifstream 的功能,可以创建文件,向文件写入信息,从文件读取信息 |
14+
15+
- 要在 C++中进行文件处理,必须在 C++源码中包含头文件`<iostream>``<fstream>`;
16+
17+
# 2: open file
18+
19+
- 在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream 和 fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象;
20+
- 下面是 open() 函数的标准语法,open() 函数是 fstream、ifstream 和 ofstream 对象的一个成员;
21+
22+
```cpp
23+
void open(const char* filename,ios::openmode mode);
24+
// 在这里,open() 成员函数的第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式
25+
```
26+
27+
| 模式标志 | 描述 | other |
28+
| :----------- | :------------------------------------------------------------------- | :---- |
29+
| `ios::app` | 追加模式,所有的写入都 append 到文件末尾 | |
30+
| `ios::ate` | 文件打开后定位到文件末尾 | |
31+
| `ios::in` | 打开文件用于读取 | |
32+
| `ios::out` | 打开文件用于写入 |
33+
| `ios::trunc` | 如果该文件已经存在,其内容将在打开文件之前被截断,即把文件长度设为 0 |
34+
35+
- 您可以把以上两种或两种以上的模式结合使用。那么您可以使用下面的语法:
36+
37+
```cpp
38+
ofstream outfile;
39+
outfile.open("file.dat", ios::out | ios::trunc ); // 如果您想要以写入模式打开文件,并希望截断文件,以防文件已存在
40+
41+
ifstream afile;
42+
afile.open("file.dat", ios::out | ios::in ); // 打开一个文件用于读写
43+
```
44+
45+
# 3: close file
46+
47+
- 当 C++ 程序终止时,它会自动关闭刷新所有流,释放所有分配的内存,并关闭所有打开的文件。但程序员应该养成一个好习惯,在程序终止前关闭所有打开的文件。
48+
49+
- 下面是 close() 函数的标准语法,close() 函数是 fstream、ifstream 和 ofstream 对象的一个成员 : `void close();`
50+
51+
# 4: write file
52+
53+
- 在 c++中,我们使用`流插入运算符(<<)`向文件写入信息;
54+
- `<<`就像输出到屏幕一样,不同的是使用的 ofstream 或者 fstream,而不是 cout 对象;
55+
56+
# 5: read file
57+
58+
- 在 c++中,我们使用`流提取运算符(>>)从文件读取信息`;
59+
- 就像使用该运算符从键盘输入信息一样。唯一不同的是,在这里您使用的是 ifstream 或 fstream 对象,而不是 cin 对象;
60+
61+
# 6:文件位置指针
62+
63+
- `istream``ostream`都提供了用于重新定义文件位置指针的成员函数,这些成员函数包括关于 istream 的`seekg` (seek get)和关于
64+
ostream 的`seekp` (seek put);
65+
- seekg 和 seekp 的参数通常都是一个长整型,第二个参数可以用于指定查找方向。
66+
- `ios::beg` : 从 stream 流的开头开始定位;
67+
- `ios::end` : 从流的末尾开始定位;
68+
- 文件位置指针是一个整数,制定了从文件起始位置到指针所在位置的字节数
69+
- 下面是关于定位 "get" 文件位置指针的实例:
70+
71+
```cpp
72+
// 定位到 fileObject 的第 n 个字节(假设是 ios::beg)
73+
fileObject.seekg( n );
74+
75+
// 把文件的读指针从 fileObject 当前位置向后移 n 个字节
76+
fileObject.seekg( n, ios::cur );
77+
78+
// 把文件的读指针从 fileObject 末尾往回移 n 个字节
79+
fileObject.seekg( n, ios::end );
80+
81+
// 定位到 fileObject 的末尾
82+
fileObject.seekg( 0, ios::end );
83+
```

000_1_11-异常处理/main.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <exception>
2+
#include <iostream>
3+
4+
using namespace std;
5+
6+
struct CustomException : public exception {
7+
const char* what() const throw() {
8+
return "C++ customException";
9+
};
10+
};
11+
12+
int main() {
13+
try {
14+
throw CustomException();
15+
16+
} catch (CustomException& e1) {
17+
cout << "CustomException caught ... " << endl;
18+
cout << "e1 : " << e1.what() << endl;
19+
} catch (const std::exception& e2) {
20+
std::cerr << "e2 : " << e2.what() << std::endl;
21+
}
22+
23+
return 0;
24+
}

000_1_11-异常处理/readme.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
[toc]
2+
3+
# 1: C++异常处理
4+
5+
- 异常提供了一种转移程序控制权的方式。C++ 异常处理涉及到三个关键字:`try``catch``throw`;
6+
7+
- **throw**: 当出现问题的时候,程序会抛出异常;
8+
- **try**: try 块中的代码标识将被激活的特定异常,它后面通常耕者一个或者多 catch 块;
9+
- **catch**: `catch`用于异常捕获,在你想要处理问题的地方,通过异常处理程序捕获异常;
10+
11+
- 如果有一个代码块抛出一个异常,捕获异常的方法会使用`try`,`catch`关键字。try 块中方式可能抛出异常的代码,try 块中的代码被称为保护代码;
12+
- 如果 try 块在不同的情境下会抛出不同的异常,这个时候可以尝试罗列多个 catch 语句,用于捕获不同类型的异常;
13+
14+
# 2: try/catch 语句
15+
16+
```cpp
17+
try{
18+
// 保护代码
19+
}catch(ExceptionName1 e1){
20+
// catch 块
21+
}catch(ExceptionName2 e2){
22+
// catch 块
23+
}
24+
```
25+
26+
# 3:throw 抛出异常
27+
28+
- 您可以使用`throw`语句在代码块的任何地方抛出异常;
29+
- throw 语句的操作可以是任意的表达式,表达式结果的类型决定了抛出的异常类型;
30+
31+
```cpp
32+
double division(int a,int b){
33+
if (b==0){
34+
throw "Division by zero condition!";
35+
}
36+
return (a/b);
37+
};
38+
```
39+
40+
# 4: try/catch 捕获异常
41+
42+
- catch 块跟在 try 块后面,用于捕获异常;
43+
- 您可以指定想要捕捉的异常类型,这是由 catch 关键字后的括号内的异常声明决定的;
44+
- 如果您想让 catch 块能够处理 try 块抛出的任何类型的异常,则必须在异常声明的括号内使用省略号 ...;
45+
46+
# 5: C++标准的异常
47+
48+
- C++提供了一系列标准的异常,定义在**<exception>**中,我们可以在程序中使用这些标准的异常,他们是以父类子类层次结构组织起来的;
49+
50+
- 如下所示:
51+
![](https://www.runoob.com/wp-content/uploads/2015/05/exceptions_in_cpp.png)
52+
53+
- 下表是对上面层次结构中出现的每个异常的说明:
54+
|**Exception 异常**|**Description**|**Other**|
55+
|:--|:--|:--|
56+
|std::exception |该异常是所有标准 C++ 异常的父类。||
57+
|std::bad_alloc |该异常可以通过 new 抛出。||
58+
|std::bad_cast |该异常可以通过 dynamic_cast 抛出。||
59+
|std::bad_exception |这在处理 C++ 程序中无法预期的异常时非常有用。||
60+
|std::bad_typeid |该异常可以通过 typeid 抛出。||
61+
|std::logic_error |理论上可以通过读取代码来检测到的异常。||
62+
|std::domain_error |当使用了一个无效的数学域时,会抛出该异常。||
63+
|std::invalid_argument |当使用了无效的参数时,会抛出该异常。||
64+
|std::length_error |当创建了太长的 std::string 时,会抛出该异常。||
65+
|std::out_of_range |该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator[]()。||
66+
|std::runtime_error |理论上不可以通过读取代码来检测到的异常。||
67+
|std::overflow_error |当发生数学上溢时,会抛出该异常。||
68+
|std::range_error |当尝试存储超出范围的值时,会抛出该异常。||
69+
|std::underflow_error |当发生数学下溢时,会抛出该异常。||
70+
71+
# 6: 定义新的异常
72+
73+
- 您可以通过继承和重载 exception 类来定义新的异常;
74+
- 下面的实例演示了如何使用 std::exception 类来实现自己的异常:

000_1_12-动态内存/main.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <iostream>
2+
using namespace std;
3+
4+
class Box {
5+
public:
6+
Box() {
7+
cout << "invoking box construct " << endl;
8+
};
9+
~Box() {
10+
cout << "invoking box destructor" << endl;
11+
};
12+
};
13+
14+
int main() {
15+
Box* myBoxArray = new Box[5]; //
16+
17+
delete[] myBoxArray; // 删除数组
18+
19+
return 0;
20+
}

000_1_12-动态内存/readme.md

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
[toc]
2+
3+
# C++动态内存
4+
5+
## 1:C++动态内存
6+
7+
- 了解动态内存在 C++中如何工作的是成为一名合格的 C++程序员必不可少的,C++程序中的动态内存分为 2 个部分:
8+
- **堆 heap:** 在程序运行时用于动态分配内存;
9+
- **栈 stack:** 在函数内部声明的变量都将用栈内存;
10+
- 很多时候,你无法提前与之需要多少内存来存储某个定义变量中的特定信息,所需内存大小需要在运行时才能确定;
11+
- 在 C++中,你可以使用特殊的运算符 **`new`** 为给定类型的变量在 runtime 时分配堆内存,这会返回分配的内存地址,即`new`运算符;
12+
- 如果你不再需要动态分配的内存空间,可以使用 **`delete`** 运算符,删除之前由`new`运算符分配的内存;
13+
14+
## 2: new 和 delete
15+
16+
### 2.1 new
17+
18+
```cpp
19+
double* pvalue = NULL; // 初始化为null指针
20+
pvalue = new double; // 为变量申请内存空间
21+
22+
// 如果自由存储区已被用完,可能无法成功分配内存;所以建议检查 new 是否返回null指针,并采取以下适当操作:
23+
double* pvalue =NULL;
24+
if (!(pvalue = new double)){
25+
cout<<"Error: out of memory!"<<endl;
26+
exit(1);
27+
}
28+
```
29+
30+
- **malloc()** 函数在 c 语言就出现了,在 C++中也存在,但建议不要使用`malloc()`函数;
31+
- **`new`****`malloc()`** 相比,优点是:**new 在分配内存的时候还创建了对象**;
32+
33+
### 2.2 delete
34+
35+
- 当你觉得某个已经分配了内存的变量不再需要使用的时候,你可以使用`delete`操作符释放它所占用的内存
36+
37+
```cpp
38+
delete pvalue; // 释放pvalue所指向的内存
39+
```
40+
41+
## 3: 动态内存分配示例
42+
43+
- https://www.runoob.com/cplusplus/cpp-dynamic-memory.html
44+
45+
### 3.1 double\*
46+
47+
```cpp
48+
int main() {
49+
double* pvalue = NULL; // 初始化为 null 的指针
50+
pvalue = new double; // 为变量请求内存
51+
52+
*pvalue = 100.568; // 在分配的地址存储值
53+
cout << "value of pvalue : " << *pvalue << endl;
54+
delete pvalue;
55+
56+
return 0;
57+
}
58+
59+
```
60+
61+
### 3.2 数组的动态内存分配
62+
63+
```cpp
64+
int main() {
65+
int** p; // 二维数组的指针
66+
int i, j; // p[4][8]
67+
//开始分配4行8列的二维数据
68+
p = new int*[4];
69+
for (i = 0; i < 4; i++) {
70+
p[i] = new int[8];
71+
}
72+
73+
for (i = 0; i < 4; i++) {
74+
for (j = 0; j < 8; j++) {
75+
p[i][j] = j * i;
76+
}
77+
}
78+
//打印数据
79+
for (i = 0; i < 4; i++) {
80+
for (j = 0; j < 8; j++) {
81+
if (j == 0)
82+
cout << endl;
83+
cout << p[i][j] << "\t";
84+
}
85+
}
86+
//开始释放申请的堆
87+
for (i = 0; i < 4; i++) {
88+
delete[] p[i];
89+
}
90+
delete[] p;
91+
return 0;
92+
}
93+
```
94+
95+
### 3.3 对象的动态内存分配
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <iostream>
2+
3+
using namespace std;
4+
5+
/* namespace first_space {
6+
void func() {
7+
cout << "inside first_space" << endl;
8+
}
9+
}; // namespace first_space
10+
11+
namespace seconds_space {
12+
void func() {
13+
cout << "inside seconds_space" << endl;
14+
}
15+
}; // namespace seconds_space
16+
17+
int main() {
18+
// 调用第一个namespace空间的函数
19+
first_space::func();
20+
21+
// 调用第二个namespace空间的函数
22+
seconds_space::func();
23+
return 0;
24+
} */
25+
26+
// 第一个命名空间
27+
namespace first_space {
28+
void func() {
29+
cout << "Inside first_space" << endl;
30+
}
31+
// 第二个命名空间
32+
namespace second_space {
33+
void func() {
34+
cout << "Inside second_space" << endl;
35+
}
36+
}; // namespace second_space
37+
}; // namespace first_space
38+
39+
using namespace first_space::second_space;
40+
int main() {
41+
// 调用第二个命名空间中的函数
42+
func();
43+
44+
return 0;
45+
}

0 commit comments

Comments
 (0)