学习笔记

6.1 if语句

c601

华为内部开发规范就是这样,我也要改成这样.

还有一个就是if ; for; while这样的语句块要和()中间各一个空格.

6.2 逻辑表达式

|| ,逻辑OR运算符 第一个表达式为True则短路,==第一个为真则不去判断第二个表达式==

&& ,逻辑AND运算符 第一个表达式为False则短路,==第一个为假则不去判断第二个表达式==

c602

转移字符’\a’是

\a 响铃(BEL) 007

image-20241103200625112

反正每次遇到这种很多组合在一起的时候,不要急着立马一眼翻译出对应的汉语可以表达的逻辑关系

image-20241108211412541

image-20241108211428150

你就慢慢来把每一个表达式的情况都拆解出来.n个expr就对应2的n次方种情况.你就每一个表达式都罗列出来,然后最后判断整体的结果是true还是false.(不要偷懒,自以为是的一眼真或者一眼假,这样一定会吃亏)

[!NOTE]

我记得这里自己之前是写了

1
2
3
4
true && true
true && false
false && false
false && true

这四种情况,也就是按照我上面的想法,n个expr就对应2的n次方种情况,这样子来分析的.

但是我后来又发现可以直接按照面向过程的思路来记忆,按程序6.5来做例子,就是看看在输入的过程中可能碰到的情况,然后分别要怎么处理,,具体如下

1
2
3
4
输入这个数之后,这个数不是负数 同时 没有满足六个,那么继续输入
输入这个数之后,这个数不是负数 同时 有满足六个,那么停止输入
输入这个数之后,这个数是负数 同时 没有满足六个,那么停止输入
输入这个数之后,这个数是负数 同时 有满足六个,那么停止输入

这样就很自然的理解了&& 的意思,

同理对于一个if也是的,例如

1
if(expr) do something;

你从逻辑上来看可能是expr为真,然后do something;expr为假,就做后面的.

但是你从这个程序具体对应的例子上来看,从过程中分析: 可能是输入这个数之后,没有满足十个,那么就继续输入.当你输入的数满足了十个,就做后面的.

因此我们这两种都要掌握.尤其是第二种,对解读代码有更好的记忆效果.而且对于短路原则,第二种可以和实际效果联系得上.例如

1
2
3
4
5
6
int i = 0;
if (i不超出数组范围 && array[i] < 10)
{
cout <<i<<endl;
i ++;
}

先从个人解读代码的角度上,用第二种方法:

如果用第一种方式就对着感到一丝丝困惑,还要自己搞四种情况,一个一个来判断,就算判断出来了也不知道这里面的过程是怎么样的.

但是用第二种方式,你首先知道初始的时候i = 0,然后从实际的作用上来理解, 就是i在自增的过程中,起初是不超出数组范围的,所以就是筛选小于10的元素,一直自增到i超出范围就停止了.

总的来说,就是第一种方式是从离散数学的逻辑判断的角度上出来,严谨但是理解速度慢.第二种方式就是从是实际出来,理解速度快同时面向过程思考.而且从实际的角度出来能理解短路原则的好处就是:

我们先从实际的角度,面向过程的来分析下面的例子

一开始i = 0, 就是i在自增的过程中,

起初是不超出数组范围的,所以就是筛选小于10的元素,#1

一直自增到i超出范围就停止了.#2

———————————————分割线

你可以看到#1这句话对应离散数学的第一种方法就是

1
2
i不超出数组范围 同时 array[i]小于10,那么输出i,然后i++
i不超出数组范围 同时 array[i]不满足小于10,那么被筛选掉了,不执行花括号里面 的语句

你看到#2这句话对应离散数学的第一种方法就是

1
2
3

i超出数组范围 同时 array[i]小于10,那么停止
i超出数组范围 同时 array[i]不满足小于10,那么停止

也就是#2自然而然的在我们面向过程的对实际情况的分析中,很自然的只判断了表达式1为false,我们大脑也自然的不去执行和判断表达式2,因为表达式2无论是true还是false 都不影响这个表达式为false.

这就是面向过程的对着实际分析和短路原则两者不谋而合的地方,或者来说,这个&&之所以存在短路原则就是参照人脑的想法,人脑看到表达式1为false的时候就本能的不去管表达式2了.所以&&有一个短路原则来和人脑对应.至于后面短路原则刚好规避了表达式2执行起来不合法的巧合,,个人认为这是先有短路原则,然后人们发现存在表达式2执行起来不合法的情况.所以调整表达式1和表达式2的位置,来刚好让短路原则,在模拟人脑的本能在表达式1为false的时候不去管表达式2这种行为下,能将不去管表达式2这个行为 即达到了模拟人脑偷懒的想法,又 达到了对执行表达式2的规避(也就是保护表达式2不被执行)

总结就是:本来短路原则是模拟人脑的偷懒行为 的,但是通过拜访表达式1和表达式2 的位置,能够一箭双雕,一石二鸟.让短路原则即达到了模拟人脑的偷懒行为的效果,又达到了不执行表达式2(也就是规避表达式2 的执行,也就是保护表达式2不被执行)

.

如果表达式1为false 的情况下,表达式2的判断过程中有不合法的阶段(如同下面的例子,在i超出数组范围的时候,表达式2不能取值,一定是不合法的,因此在表达式1为false的时候,我们不希望表达式2被执行.)因此那么就把表达式1放在表达式2的左边,通过&&连接起来.这样在表达式1为false的时候,就可以保护表达式2不被执行.最经典要记忆的例子就是下面这种写法

1
2
3
4
5
6
int i = 0;
if (i不超出数组范围 && array[i] < 10)
{
cout <<i<<endl;
i ++;
}

最后注意一个别人积累出来的规避错误的技巧:

在最后一次判断刚好超出范围的i的时候,取array[i]是不合法的,但刚好把判断i是否超出数组范围的语句写到前面,就能保护后面的语句不被执行.这是一种习惯,记住就行.

接着如果有可以优化的判断,或者是短路原则之类 的,你再去判断.这样一步一步的理解就不会有让自己有怀疑的点了.

第一次看程序6.5的时候自己有些迟疑,怀疑是自己没咋见过这种的,自己还不够熟练.自己现在不看给出的答案,自己写一遍

image-20241108211859900

程序清单6.5

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
#include <iostream>
#include <cstring>
using namespace std;
const int ArSize = 6;
int main(void)
{
// 由于两种不同 的因素来结束循环
// 一个是数组满了.
// 另一个是

double arr[ArSize];
double temp;

int i = 0;
cout << "First value: ";
cin >> temp;
while (i < ArSize && temp >= 0) // 两个退出条件
{
arr[i] = temp;
i++;
if (i < ArSize) // room left in the array数组里面还有空间的时候才能为下一个输入的数做Next value的铺垫
{
cout << "Next value: ";
cin >> temp;
}
}
if (i == 0)
cout << "No data -- bye" << endl;
else
{
// i最后的值就是成功被写入arr数组里面的 数字的个数.
printf("Enter your NAAQ:");
double ave;
cin >> ave;

int count = 0;
for (int j = 0; j < i; j++)
{
if (arr[j] > ave)
count++;
}
cout << count << endl;
cout << "of your neighbor have greater awareness of the New Age than you do . " << endl;
}
return 0;
}

注意:在按照我的面向过程的想法看待这个输入的数据的过程的时候,总是不自觉地假定第一个输入的数字是符合要求的,从第二个开始往后输入的数字才是因为expr1或者expr2为false而不符合要求的,从这个过程中让自己了解各种情况.但是往往陷入一个思维误区,就是第一个输入的数字也完全可能是不符合要求的,从而一次while循环都没有进入过.具体到我这里的题意就是 第一个输入的数字是负数,因此arr数组里面一个数都没有,所以加一个特判

1
2
if (i == 0)
cout << "No data -- bye" << endl;

很多时候自己写才发现自己会忘记很多东西,看代码的时候想当然,自己写的时候啥都不确定.

一句话送给自己:不要眼高手低,可能有难题,但绝对没有简单题目

6.2.3 用&&来设置取值范围

这里复习一下

image-20241226210149602

程序清单 6.6 more_and.cpp

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
#include <iostream>
#include <cstring>
using namespace std;
const char *qualify[5] = {
"Perfect", "Great", "Good", "Just so so", "failed"};
int main(void)
{
int score;
int index;
cout << "Enter your score:";
cin >> score;
if (score >= 90 && score <= 100)
index = 0;
else if (score >= 80 && score < 90)
index = 1;
else if (score >= 70 && score < 80)
index = 2;

else if (score >= 60 && score < 70)
index = 3;
else
index = 4;

cout << qualify[index] << endl;
return 0;
}

程序清单6.7 not.cpp

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 <climits>
using namespace std;
bool is_int(double x);
int main(void)
{
double number; // 通过定义成double类型,让number获得一个更广的取值范围
cout << "Enter an integer value:";
cin >> number;

while (!is_int(number))
{
cout << "out of range , please enter again:";
cin >> number;
}

int value = int(number);
cout << "You have entered an integer: " << value << endl;
return 0;
}
bool is_int(double x)
{
if (x <= INT_MAX && x >= INT_MIN)
return true;
else
return false;
}

不要眼高手低,还是每一个都敲一遍,不知不觉就有感觉和记忆.’

程序清单6.7 cctype.cpp

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
#include <iostream>
#include <cctype>
using namespace std;
int main(void)
{
int whitespace = 0; // 这是记录标准空白字符,不是空格
// 标准空白字符是 whitespace
// 空格是 blankspace
// 上面是我猜测的,但是不论真假,能拿来记忆就是好的
int digits = 0;
int chars = 0;
int punct = 0;
int others = 0;

char ch;
cout << "Enter text for analysis, and type @ to terminate the input. " << endl;
cin.get(ch);
while (ch != '@')
{
if (isspace(ch)) // 这是判断标准空白字符,不是空格
whitespace++;
else if (isdigit(ch))
digits++;
else if (isalpha(ch))
chars++;
else if (ispunct(ch))
punct++;
else
others++;
cin.get(ch);
}
printf("%d letters\n", chars);
printf("%d whitespaces\n", whitespace);
printf("%d digits\n", digits);
printf("%d punctuations\n", punct);
printf("%d others\n", others);
}

程序清单6.9 condit.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cctype>
using namespace std;
int main(void)
{
int a, b;
cout << "Enter two integers:";
cin >> a >> b;

int max = a > b ? a : b;
cout << "the larger is " << max << endl;
}

程序清单6.10 switch.cpp

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
#include <iostream>
#include <cctype>
using namespace std;
void showmenu(void);
void report(void);
void comfort(void);
int main(void)
{
char choice;

showmenu();
cin >> choice;

while (choice != 'Q' && choice != 'q')
{
switch (choice)
{
case 'a':
case 'A':
cout << "Warning!!!" << endl;
break;

case 'r':
case 'R':
report();
break;

case 'l':
case 'L':
cout << " The boss was in all day" << endl;
break;

case 'c':
case 'C':
comfort();
break;
default:
cout << "That is not a choice" << endl;
break;
}

showmenu();
cin >> choice;
}
return 0;
}

void showmenu(void)
{
cout << "Please enter 1, 2 , 3, 4, 5 as your choice:" << endl;
cout << "a) alarm r) report" << endl;
cout << "l) alibi c) comfort" << endl;
cout << "q) quit" << endl;
}
void report(void)
{
cout << "Sales are up 120%, Expenses are down 35%." << endl;
}
void comfort(void)
{
cout << " You are the best CEO !" << endl;
}

程序清单6.11 enum.cpp

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

enum
{
red,
orange,
yellow,
green,
blue,
violet,
indigo
};
int main(void)
{
int code;

cout << "Enter color code(0~6): ";
cin >> code;

while (code >= red && code <= indigo)
{
switch (code)
{
case red:
cout << "You choose red!" << endl;
break;
case orange:
cout << "You choose orange!" << endl;
break;
case yellow:
cout << "You choose yellow!" << endl;
break;
case green:
cout << "You choose green!" << endl;
break;
case blue:
cout << "You choose blue!" << endl;
break;
case violet:
cout << "You choose violet!" << endl;
break;
case indigo:
cout << "You choose indigo!" << endl;
break;
}

cout << "Enter color code(0~6): ";
cin >> code;
}

cout << "bye1" << endl;
return 0;
}

程序清单6.12 jump.cpp

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
#include <iostream>
#include <cstring>
using namespace std;
const int ArSize = 80;

int main(void)
{
char line[ArSize];

cout << "Enter a line of text: ";
cin.get(line, ArSize);

int blankspaceCount = 0;
for (int i = 0; i < strlen(line); i++)
{
cout << line[i];
if (line[i] == '.')
break;
if (line[i] == ' ')
blankspaceCount++;
}

cout << endl;
cout << "blankspaceCount is " << blankspaceCount << endl;

cout << "Complete line :" << line << endl;
return 0;
}

老师讲的简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cstring>
using namespace std;
// const int ArSize = 80;

int main(void)
{
int num1, num2;
cout << "First number: ";
cin >> num1;

cin.clear(); // reset cin or reset input让cin功能继续使用
// 清空缓冲区的内容
while (cin.get() != '\n') // get rid of bad input
;
cout << "Last number: ";
cin >> num2;
cout << "num1 = " << num1 << ", num2 = " << num2 << endl;

return 0;
}

程序清单6.13 cinfish.cpp

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
#include <iostream>
#include <cstring>
using namespace std;
const int Max = 5;

int main(void)
{
double fish[Max];
cout << "Please enter the weight of your fish: " << endl;
cout << "You may enter up to " << Max << " fish <q> to terminate. " << endl;

cout << "fish #1:"; // cin >>fish[i] 捕获失败的话 ,,会返回一个false
int i = 0;
while (i < Max && cin >> fish[i])
{
i++;
if (i < Max) // room left;下一条鱼没超出范围就提示您 请输入 的信息
cout << "fish #" << i + 1 << ":";
}

double ave;
double sum = 0;
for (int j = 0; j < i; j++)
sum += fish[j];

cout << "total :" << sum << endl;
// 看到除法,不自觉就写一个if (除数 == 0)的特别判断
if (i == 0)
cout << "No fish" << endl;
else
{
ave = sum / i;
cout << "Average weight of " << i << " fish is " << ave << endl;
}

// 有可能第一次输入的值就是错误的,,也就是一条鱼的信息都没有录入

return 0;
}

程序清单6.14 cingolf.cpp

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
#include <iostream>
#include <cstring>
using namespace std;
const int Max = 5;

int main(void)
{
int golf[Max];
cout << "Please enter your golf scores." << endl;
cout << "You must enter " << Max << " rounds. " << endl;
int i;
for (i = 0; i < Max; i++)
{
cout << "Round #" << i + 1 << ": " << endl;
while (!(cin >> golf[i]))
{
cin.clear();
while (cin.get() != '\n')
;
cout << "Error: bad input , please enter your golf scroe again!" << endl;
}
}

double total = 0;
// cout << "the result is \n";
for (int i = 0; i < Max; i++)
total += golf[i];

cout << "Average score is " << total / Max << endl;
return 0;
}

6.8 简单文件输入/输出

发现可以在VScode的终端里面按照ubuntu一样的用命令行来编译运行,就可以在同一路径下放多个有main函数的cpp文件了.(缺点是windows下的路径的符号是反斜杠也就是\ ,不想Ubuntu下的是斜杠,也就是除号/,也叫做正斜杠.反正你没事按下tab就能自动补全,甚至能帮你修改一些微小的格式错误.).

用快捷键Ctrl + alt + n肯定是把当前目录下的所有cpp文件都一起编译链接了,所以出了问题有多个main函数作为程序的入口

程序清单6.15 outfile.cpp

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
#include <iostream> //键盘和屏幕的输入输出用了iostream
// istream->cin和ostream->cout
#include <fstream>
#include <cstring>
using namespace std;
const int Max = 5;
// using namespace std;
int main(void)
{

char automobile[50];
int year;
double a_price;
double d_price;

ofstream outFile;
outFile.open("hsuwindow.txt");
cout << "Enter the make and model of automobile:";
cin.getline(automobile, 50);
cout << "Enter the model year: ";
cin >> year;
cout << "Enter the original asking price:";
cin >> a_price;
d_price = a_price * 0.913;

// set precision
cout << fixed;
cout.precision(2);
cout.setf(ios_base ::showpoint);
cout << "Make and model: " << automobile << endl;
cout << "Year: " << year << endl;
cout << "Was asking: " << a_price << endl;
cout << "Now asking: " << d_price << endl;

outFile << fixed;
outFile.precision(2);
outFile.setf(ios_base ::showpoint);

outFile << "Make and model: " << automobile << endl;
outFile << "Year: " << year << endl;
outFile << "Was asking: " << a_price << endl;
outFile << "Now asking: " << d_price << endl;

// 想到open就想到close,就和new 和 delete永远联想到一起是一样的
outFile.close();
return 0;
}

程序清单6.16 sumafile.cpp

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
#include <iostream> //键盘和屏幕的输入输出用了iostream
// istream->cin和ostream->cout
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 100;
int main(void)
{
char filename[SIZE];
ifstream inFile;

// char arr[] =
cout << "Enter name of data file: ";
cin.getline(filename, SIZE);

inFile.open(filename);

if (!inFile.is_open())
{
cout << "Could not open the file " << filename << endl;
cout << "Program terminating." << endl;
exit(EXIT_FAILURE);
}
cout << "Success open the txt file." << endl;

double value; // 读取的内容是什么
double sum = 0.0; // 感觉是和cin 的一样的,一个是从键盘读入,一个是从文本读入
int count = 0;

// cin>> value;
inFile >> value;
while (inFile.good())
{
count++;
sum += value;
inFile >> value;
}
// inFile.good()为假只有两种可能,一是文本都读完了,
// 二是读着读着有数据不合格,不属于能被存到double类型的数据的
// 这一段是检查while循环是因为什么原因退出的
if (inFile.eof())
{
cout << "End of file reached." << endl;
}
else if (inFile.fail())
{
cout << "Input terminated by data mismatched. " << endl;
}
else // 未知原因退出的
cout << "Input terminated by unknown reason " << endl;

if (count == 0)
{
cout << "No data processed." << endl;
}
else

{
cout << "Items read: " << count << endl;

cout << "Sum: " << sum << endl;
cout << "Average: " << sum / count << endl;
}

inFile.close(); // 有open就要有close,成对出现,狠狠背诵
return 0;
}

复习题解析

1.第一种格式不论什么情况,两个if语句都会被执行一次,第二种格式在ch 为空格的时候,不会执行else if里面的语句,所以第二种格式第一种格式好的地方

2.ch + 1的结果是int类型,cout之后结果是整形数

++ch是ASCII码值向后或者向前挪一位,因此他在运算完毕之后,他仍然还是一个char类型,因此他cout之后结果仍然是字符

H$i$!$

$S$e$n$d$ $ct1 = 9, ct2 = 9

weight >= 100 && weight < 125

ch == ‘q’ || ch == ‘Q’

x % 2 == 0 && x != 26

x % 2 == 0 && x % 26 != 0

(donation >= 1000 && donation <= 2000) || (1 == guest)

(ch >= ‘a’ && ch <= ‘z’) || (ch >= ‘A’ && ch <= ‘Z’)

如果是x是bool类型,那么!!x和x是一样的

如果说x是char或者int类型,!x变成变成bool类型的 false,!!x就是true,那么!!x和x肯定就不一样 了

(x > 0) ? x : -x;

switch(ch){

case: ‘A’:

a_grade++;

break;

case: ‘B’:

a_grade++;

break;

case: ‘C’:

a_grade++;

break;

case: ‘D’:

a_grade++;

break;

default :

f_grade++;

break;

}

image-20241231214449951

image-20241231214512678

image-20241231214550568

这里书上可能是编译器的问题,反正跟b站视频的结果和我自己测试的结果有出入

我把我的测试代码贴在下面

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
#include <iostream>
using namespace std;
void showMenu(void);

int main(void)
{
int choice;
showMenu();
cin >> choice;

while (choice != 5)
{
switch (choice)
{
case 0:
cout << "kankan choice is or not 0\n";
break;
case 1:
cout << "you enter 1\n";
// system("pause");
break;
case 2:
cout << "you enter 2\n";
// system("pause");
break;
case 3:
cout << "you enter 3\n";
// system("pause");
break;
case 4:
cout << "you enter 4\n";
// system("pause");
break;

default:
cout << "That is not a choice\n";
// system("pause");
break;
}
showMenu();
cout << choice << endl;
cin >> choice;
}

cout << "Bye!\n";
return 0;
}
void showMenu(void)
{
cout << "Please enter 1, 2, 3, 4, or 5:\n";
cout << "1) alarm 2) report\n";
cout << "3) alibi 4) comfort\n";
cout << "5) quit\n";
}

本题的答案应该是

修改成 char类型之后,无论你输入的是数字还是26个英文字符,程序运行起来都没有问题.

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

int main(void)
{
int line = 0;
char ch;
while (cin.get(ch) && ch != 'Q')
{
if (ch == '\n')
line++;
}
return 0;
}

编程练习ing

💡 有关C++PrimerPlus上的问题,欢迎您在底部评论区留言,一起交流~