Skip to content

Commit 5dc06cd

Browse files
committed
Created the Folder "code_in_book"
1 parent 63a351f commit 5dc06cd

36 files changed

+819
-74
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"cmake.configureOnOpen": true
3+
}

.vscode/tasks.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"tasks": [
3+
{
4+
"type": "cppbuild",
5+
"label": "C/C++: g++.exe build active file",
6+
"command": "D:\\msys64\\ucrt64\\bin\\g++.exe",
7+
"args": [
8+
"-fdiagnostics-color=always",
9+
"-g",
10+
"${file}",
11+
"-o",
12+
"${fileDirname}\\${fileBasenameNoExtension}.exe"
13+
],
14+
"options": {
15+
"cwd": "D:\\msys64\\ucrt64\\bin"
16+
},
17+
"problemMatcher": [
18+
"$gcc"
19+
],
20+
"group": {
21+
"kind": "build",
22+
"isDefault": true
23+
},
24+
"detail": "Task generated by Debugger."
25+
}
26+
],
27+
"version": "2.0.0"
28+
}

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
我为此规划了一个大致的编章结构,参见[Structure.md](https://github.com/cppHusky/cppHusky-cpp-Tutorial/blob/main/Structure.md)
1010

11-
正在疯狂赶进度,还要补充插图。现阶段争取保持每3天更新一章的速度。
11+
正在疯狂赶进度,还要补充插图。现阶段争取保持每4天更新一章的速度。
12+
13+
我正在考虑把书中每一份正式的示例代码打包并存至本项目中。现在尚在研究阶段。
1214

1315
如果发现内容有任何疏漏和错误,欢迎来作补充和提出修改意见!可以直接提交到[Issues](https://github.com/cppHusky/cppHusky-cpp-Tutorial/issues)当中。

code_in_book/1.1/Hello_World.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// 这是一个简单的C++程序,用于输出Hello World
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //使用std命名空间
4+
int main() { //主函数,程序执行始于此
5+
cout << "Hello World!";//输出Hello World
6+
return 0;
7+
}

code_in_book/1.2/calc.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// 这是一个简单的C++程序,用于简易的数值计算
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //使用std命名空间
4+
int main(){ //主函数,程序执行始于此
5+
double a {1.5}, b {0.3}, c {0.5}, d {4.5}; //定义并初始化
6+
cout << (a + b * c) / d; //输出(a+b*c)/d的值
7+
return 0;
8+
}

code_in_book/2.1/Integer_Limits.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// 这是一个简单的C++程序,用于输出一些整型数值的上/下限值
2+
#include <iostream> //标准输入输出头文件
3+
#include <limits> //标准算术类型属性头文件,numeric_limits定义于此
4+
using namespace std; //使用std命名空间
5+
int main(){ //主函数,程序执行始于此
6+
cout << numeric_limits<short>::lowest(); //输出short类型的下限值
7+
cout << endl; //输出换行,下同
8+
cout << numeric_limits<short>::max(); //输出short类型的上限值
9+
cout << endl;
10+
cout << numeric_limits<unsigned>::lowest(); //输出unsigned类型的下限值
11+
cout << endl;
12+
cout << numeric_limits<unsigned>::max(); //输出unsigned类型的上限值
13+
return 0;
14+
}

code_in_book/3.1/Input_to_ASCII.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// 这是一个简单的程序,用来将用户所有的输入转为ASCII码
2+
// 读者无需掌握本代码的全部细节,后续会讲到
3+
#include <iostream> //标准输入输出头文件
4+
using namespace std; //使用命名空间std
5+
int main() { //主函数,程序执行始于此
6+
char c; //定义一个char变量c用以接收输入
7+
while (cin.good()) { //while循环,当cin状态正常时继续循环
8+
c = cin.get(); //通过cin.get()接收输入,并存入c
9+
std::cout << static_cast<int>(c) << std::endl;
10+
//强制类型转换为int,故以ASCII码值形式显示输入内容
11+
}
12+
}

code_in_book/3.2/odd_or_even.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//这段代码可以判断输入的正整数是奇数还是偶数
2+
#include <iostream>
3+
using namespace std;
4+
int main() { //主函数,代码顺序执行
5+
int num; //也可以用unsigned
6+
cin >> num; //输入num变量
7+
const int mod {num % 2}; //num模除2的值;也可以不用const
8+
if (mod == 1) { //选择结构
9+
cout << "奇数";
10+
}
11+
else {
12+
cout << "偶数";
13+
}
14+
return 0;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//这是一个基于while循环的奇偶判断程序,当输入为字母时停止循环
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //命名空间使用
4+
int main() { //主函数
5+
int num; //定义num,可不初始化
6+
while (cin >> num) { //输入num并使用cin的返回值作为判断条件
7+
const int mod {num % 2}; //num模除2的值
8+
if (mod == 0) { //判断是否为偶数
9+
cout << "偶数" << endl;
10+
}
11+
else { //mod可能是1或-1,我们把它们都归入else中
12+
cout << "奇数" << endl;
13+
}
14+
}
15+
cout << "程序结束"; //输出一个提示语,告诉用户程序结束
16+
}

code_in_book/3.4/sum.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <iostream>
2+
using namespace std;
3+
void input_clear() {
4+
cin.clear(); //清除错误状态
5+
while (cin.get() != '\n') //清除本行输入
6+
continue;
7+
}
8+
int main() { //主函数
9+
int sum {0}, x {1}; //x初始化为1是为了防止误结束循环
10+
while (x != 0) { //当x为0时结束循环
11+
cin >> x; //输入x的值
12+
if (!cin) {
13+
input_clear(); //清除错误和错误输入
14+
x = 1; //x赋为1,否则可能导致循环误结束
15+
cout << "请输入数字!输入0结束计算" << endl;
16+
continue; //跳过sum+=x的操作
17+
}
18+
sum += x; //这是一个复合赋值运算符,等效于sum=sum+x
19+
}
20+
cout << "总数为:" << sum;
21+
return 0;
22+
}

code_in_book/3.5/简易计算器.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//这是一个简易计算器,可以支持简单的四则运算或模运算。不支持复杂表达式的计算
2+
#include <iostream>
3+
using namespace std;
4+
int main() {
5+
while (cin) { //如果cin状态正常,就继续循环
6+
double num1, num2, result; //定义两个操作数num及结果值result
7+
char op; //定义一个字符用来存储运算符输入
8+
cin >> num1 >> op >> num2; //依次输入左操作数、运算符和右操作数
9+
if (!cin) { //如果cin状态不正常,说明输入了非预期内容,退出循环
10+
break;
11+
}
12+
switch (op) { //判断op是什么
13+
case '+': //根据op的值,采取相应的操作
14+
result = num1 + num2; //通过赋值的方式存储结果
15+
break; //记得用break
16+
case '-':
17+
result = num1 - num2;
18+
break;
19+
case '*':
20+
result = num1 * num2;
21+
break;
22+
case '/':
23+
result = num1 / num2;
24+
break;
25+
case '%':
26+
result = static_cast<int>(num1) % static_cast<int>(num2);
27+
//显式类型转换,将double型的num1和num2转换为int,这样才能计算
28+
//末尾的break省略
29+
}
30+
cout << "=" << result << endl; //输出result的值
31+
}
32+
cout << "程序结束" << endl; //提示用户程序结束
33+
return 0;
34+
}

code_in_book/4.1/max3.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//这个程序可以接收三个输入整数,并给出它们的最大值
2+
#include <iostream> //标准输入输出头文件
3+
using namespace std; //使用命名空间std
4+
long long max3(long long, long long, long long); //声明
5+
int main() {
6+
long long a, b, c; //定义long long型变量a,b
7+
cin >> a >> b >> c; //输入a,b的值
8+
cout << max3(a, b, c); //输出a,b,c的最大值
9+
return 0;
10+
}
11+
long long max(long long a, long long b) {
12+
//接收两个long long参数,给出long long返回值
13+
if (a > b) { //当a>b时返回a
14+
return a;
15+
}
16+
else { //否则返回b
17+
return b;
18+
}
19+
}
20+
long long max3(long long a, long long b, long long c) {
21+
//接收三个long long参数,给出long long返回值
22+
const long long max_ab {max(a,b)};
23+
if (max_ab > c) { //如果a,b的最大值大于c,返回前者
24+
return max_ab;
25+
}
26+
else { 否则返回后者
27+
return c;
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//用递归方法实现阶乘函数
2+
#include <iostream>
3+
using namespace std;
4+
//如果fractorial的参数大于12,就会发生运算结果溢出。可以考虑用unsigned long long
5+
unsigned factorial(unsigned n) { //阶乘的参数和值都不是负数,所以定义成unsigned
6+
if (n == 0) { //终止条件,不可或缺
7+
return 1; //0!为1,直接返回
8+
}
9+
else { //如果没有到达终止条件,就调用factorial(n-1),离终止条件更近一步
10+
return n * factorial(n - 1); //递归,n!用n*(n-1)!表示
11+
}
12+
}
13+
int main() {
14+
cout << factorial(12); //计算并输出12!的值
15+
return 0;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//这是一个输入若干数求最大值的程序,用户可以输入最多100000个数据,输入q结束输入
2+
#include <iostream>
3+
using namespace std;
4+
//声明部分
5+
void input_clear(istream& = {cin}); //在声明中就给出默认参数,注意类型是引用
6+
template<typename T>
7+
T maximum(T[], int); //T[]写成T*也没问题,不过习惯上还是写成数组形式
8+
template<typename T> //注意:每次声明(定义)模版时必须写一个template
9+
unsigned input_arr(T[], const unsigned);
10+
//定义部分
11+
int main() { //主函数
12+
const int Maxsize {100000}; //用constexpr也可
13+
int arr[Maxsize];
14+
cout << maximum(arr, input_arr(arr, Maxsize));
15+
return 0;
16+
}
17+
void input_clear(istream &in) {
18+
in.clear();
19+
while (in.get() != '\n')
20+
continue;
21+
}
22+
template<typename T>
23+
T maximum(T arr[], int n) {
24+
T res {arr[0]}; //先假设最大值为arr[0]
25+
for (int i = 1; i < n; i++)
26+
if (arr[i] > res) //如果arr[i]>res,说明有更大的数
27+
res = arr[i]; //那么目前能找到的最大值就是arr[i]
28+
return res; //res就是返回值
29+
}
30+
template<typename T>
31+
unsigned input_arr(T arr[], const unsigned max_size) {
32+
unsigned real_size {0}; //记录数组中数据的实际个数
33+
while (real_size < 1000) { //防止数组下标越界
34+
cin >> arr[real_size]; //输入arr[real_size]
35+
++real_size; //然后real_size自增
36+
if (!cin) { //如果输入状态错误
37+
input_clear(); //先清理输入
38+
break; //再退出while循环
39+
}
40+
}
41+
return real_size;
42+
}

code_in_book/6.1/list.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include <iostream>
2+
using namespace std;
3+
struct Data {
4+
int num;
5+
Data *next;
6+
};
7+
void clear_list(Data *head) { //递归回收*head之后的所有动态内存
8+
if (head->next == nullptr) //如果*head之后没有动态内存
9+
return; //那就不需要回收什么了,直接return;结束本次调用
10+
clear_list(head->next); //先清理head->next之后的部分
11+
delete head->next; //再回收head.next
12+
head->next = nullptr;
13+
//现在head之后没有动态内存了,我们可以放心地把head->next置为nullptr
14+
}
15+
void insert_after(Data *head, int n) { //在*head下一位置插入n
16+
Data* p = { new Data{n,nullptr} }; // 分配动态内存,并初始化其num成员
17+
p->next = head->next; //插入数据的下一位指向当前的*head->next
18+
head->next = p; //head->next指向*p,注意顺序不要颠倒!
19+
}
20+
bool delete_after(Data *head) {
21+
//删除*head下一位置的数据,并返回true;若*head是末尾元素,删除失败,返回false
22+
if (head->next == nullptr) //说明*head就是末尾元素
23+
return false; //*head是末尾元素,无法再删除后面内容
24+
//这里应当用else块,不过也可以省掉
25+
//因为if块内会直接return,所以后面的代码肯定是在条件为false情况下运行的
26+
Data *p = head->next; //临时指针p指向*head->next
27+
head->next = p->next; //head->next指向更后一个元素
28+
delete p; //回收p指向的内存
29+
return true;
30+
}
31+
bool delete_after(Data *head, Data* tail) {
32+
//删除*head之后(不包含)直到*tail为止(包含)的单元。若删除失败,返回false
33+
if (head == tail) //说明没有任何数据需要清理
34+
return false; //删除失败
35+
if (tail == nullptr) { //说明我们需要删除*head之后的所有内容
36+
clear_list(head); //当然是用clear_list啦
37+
return true; //删除成功
38+
}
39+
Data tmp_head {*head}; //用*head来直接为tmp_head初始化
40+
head->next = tail->next; //绕过待删除段,直接指向*tail->next
41+
tail->next = nullptr; //tail指向nullptr,现在待删除片段就被剥离出来了
42+
clear_list(&tmp_head); //以tmp_head为头,清理这段链表
43+
return true; //删除成功
44+
}
45+
void transfer(Data *head, Data *tail, Data *dest) {
46+
//片段转移,把*head之后(不包含)直到*tail为止(包含)的单元移到*dest之后
47+
if (head == tail || dest == nullptr) //这两种情况下转移没有意义
48+
return;
49+
if (tail == nullptr) { //这种情况不方便我们处理,我们把tail改成指向末尾单元
50+
for (tail = head; tail->next != nullptr; tail = tail->next) {
51+
; //for循环的逻辑是,从head开始找,直到tail->next==nullptr为止
52+
}
53+
if (head == tail) //仍需当心head==tail的可能
54+
return;
55+
}
56+
swap(tail->next, dest->next); //swap函数需要utility或string_view库
57+
swap(head->next, dest->next); //是一种技巧,读者不必强求掌握
58+
}
59+
int main() {
60+
Data head; //链表头
61+
insert_after(&head, 10);
62+
insert_after(head.next, 20);
63+
delete_after(&head);
64+
std::cout << head.next->num; //将输出20
65+
clear_list(&head);
66+
return 0;
67+
}

code_in_book/7.1-7.3/Definition.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "Header.h" //它需要包含头文件Header.h
2+
void input_clear(istream& in) { //声明部分已经有默认参数cin,这里不应再写
3+
in.clear();
4+
while (in.get() != '\n')
5+
continue;
6+
}

code_in_book/7.1-7.3/Header.h

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
#include <iostream>
3+
using namespace std; //使用命名空间std
4+
void input_clear(istream& = {cin}); //在声明中就给出默认参数

code_in_book/7.1-7.3/Test.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include "Header.h"
2+
int main() {
3+
int n {1};
4+
while (n != 0) {
5+
cin >> n;
6+
if(!cin) //检测cin的状态
7+
input_clear(); //清理输入
8+
//...
9+
}
10+
return 0;
11+
}

0 commit comments

Comments
 (0)