当前位置: 首页 > news >正文

《明解C语言入门篇》读书笔记四

目录

第四章:程序的循环控制

第一节:do语句

do语句

复合语句(程序块)中的声明

读取一定范围内的值

逻辑非运算符 · 德摩根定律

德摩根定律

求多个整数的和及平均值

复合赋值运算符

后置递增运算符和后置递减运算符

练习4-1

练习4-2

第二节:while语句

while语句

用递减运算符简化程序代码

数据递增

限定次数的循环操作

字符常量和putchar()函数

do语句和while语句

前置递增运算符和前置递减运算符

do语句的显示

逆向显示整数值

练习4-3

练习4-4

练习4-5

练习4-6

练习4-7

练习4-8

练习4-9

练习4-10

练习4-11

练习4-12

第四章:程序的循环控制

第一节:do语句

📖读书笔记

  • do语句

C语言中提供了三种循环语句,分别是do语句、while语句、for语句,每种都有自己的使用场景,下面使用do语句编写一个程序,来判断输入的数字是奇数还是偶数。

//输入一个整数,判断是奇数还是偶数
//这个代码在书中的代码基础上做了一点点修改,比如使用更加熟悉的printf()函数来输出
#include <stdio.h>
int main()
{int retry = 1, no = 0;//将retry初始化为1,是为了不与循环条件retry == 0冲突do{printf("请输入一个整数\n");scanf("%d", &no);if (no % 2) //这里用来判断奇数还是偶数printf("这个数字是奇数\n");elseprintf("这个数字是偶数\n");printf("想要重来一次吗(Yes输入0,NO输入其他整数)?\n");scanf("%d", &retry);} while (retry == 0); //如果retry结果为0,表示继续循环,这里相当于判断条件return 0;
}

上面代码的运行结果如下:

那么do-while循环的执行过程是怎样的呢?输出结果首先就让我们“输入一个整数”,可见并不是先判断循环条件(因为最开始retry为1,判断的条件为假),这就是do-while语句的特点,即无论循环条件是否为真,都会先执行一次循环,这次循环执行结束之后,再判断循环条件,如果为真就继续循环,为假就跳出循环。

上面的程序我们可以再次修改一下,写成更加符合我们习惯的代码。

//程序修改
int main()
{int num = 0;do{printf("请输入一个整数\n");scanf("%d", &num);if (num % 2 == 1) //这里用来判断奇数还是偶数printf("这个数字是奇数\n");elseprintf("这个数字是偶数\n");printf("继续请输入1,退出请输入0\n");scanf("%d", &num);if (num == 0)break;} while (1); //将循环条件设置恒为真,此时需要搭配break语句跳出循环return 0;
}

  • 复合语句(程序块)中的声明

在上面的代码中,no变量只在循环内部使用,应尽量声明在循环内部,这就是复合语句中的声明,但如果在循环外部声明,也没有什么问题。

  • 读取一定范围内的值

下面代码应该是个“猜”拳游戏,只不过猜的不是谁赢,而是出了什么。

//“猜”拳游戏(有一定的更改)
//规定0代表石头,1代表剪刀,2代表布
int main()
{int hand = 0;do{printf("请出拳【0-石头、1-剪刀、2-布】\n");scanf("%d", &hand);} while (hand < 0 || hand > 2);//如果没有0、1、2这三个值其中之一,就继续循环//选择了正确的出拳//下面将书中的switch语句换成了if语句,原因是if语句更加清晰,而且使用频率也比switch高if (hand == 0)printf("石头\n");else if (hand == 1)printf("剪刀\n");else if (hand == 2)printf("布\n");return 0;
}

上面的程序中,通过do-while循环的循环条件,实现了读取[0, 2]范围内的整数值。

  • 逻辑非运算符 · 德摩根定律

通过逻辑非运算符(!),就可以实现真变假,假变真,比如上面程序中的“hand < 0 || hand > 2”就可以改成“!(hand >= 0 && hand <= 2)”。

在C语言中,0表示假,一切非0表示真,所以!a的含义是:如果a为0(假),那么!a就是非0(真);如果a为非0(真),那么!a就是0(假)。

  • 德摩根定律

下面两个表达式称为德摩根定律:

  1. (x && y) == !(!x || !y),即用x && y做判断条件,与!(!x || !y)做判断条件相同。
  2. (x || y) == !(!x && !y),这两个表达式就是通过逻辑非运算符联系在一起的。
  • 求多个整数的和及平均值

不停的输入整数,显示其和及其平均值,代码如下:

//不停的输入整数,显示其和及其平均值(稍加修改)
int main()
{int num = 0, sum = 0, count = 0;//num表示输入的整数,sum是和,count是数字个数float avg = 0.0;//avg是平均值do{printf("请输入一个整数\n");scanf("%d", &num);sum += num;//求和count++;//统计个数avg = (float)sum / count;//求平均值,由于sum是整形,所以要强转成浮点型之后计算printf("和为%d,平均值为%f\n", sum, avg);//%f用来输出浮点数printf("继续请输入1,退出请输入0\n");scanf("%d", &num);//这里借用了num变量来判断是否继续执行循环if (num == 0)break;} while (1);return 0;
}

  • 复合赋值运算符

复合赋值运算符有:+=(加等)、-=(减等)、*=(乘等)、/=(除等)、%=(取模等)、&=(按位与等)、|=(按位或等)、^=(按位异或等)、<<=(左移等)、>>=(右移等)。

这些运算符相当于简写,比如“a += b”和“a = a + b”是一样的,都是将a+b的值再赋给a。

  • 后置递增运算符和后置递减运算符

如果是++,表示递增运算符,--表示递减运算符。如果写在变量或表达式后面,就是后置递增或递减,写在前面就是前置递增或递减。

a++;//后置++
a--;//后置--
++a;//前置++
--a;//前置--

对于后置++或--,由于运算符在后面,所以运算顺序是先赋值,再++或--;如果是前置++或--,则恰好相反。当然,如果没有赋值这一操作,前置和后置++或--其实没什么区别。

a = (b++);//先把b的值给a,之后b的值加1,此时a的值是b,b的值是b+1
a = (--b);//先让b减1,之后把b-1的值给a,此时a的值是b-1,b的值也是b-1//这里需要注意的是,++和--运算符是能够改变b本身的值的,这与+和-运算符不同
a = b + 1;//a的值是b+1,b的值不变

📝课后习题

  • 练习4-1

将下面代码改成可以输入、显示任意次。

int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);if (num == 0)printf("该整数为0\n");else if (num > 0)printf("该整数为正数\n");elseprintf("该整数为负数\n");return 0;
}

✏️解答:

//练习4-1
int main()
{int num = 0;do{printf("请输入一个整数\n");scanf("%d", &num);if (num == 0)printf("该整数为0\n");else if (num > 0)printf("该整数为正数\n");elseprintf("该整数为负数\n");printf("继续请输入1,退出请输入0\n");scanf("%d", &num);if (num == 0)break;} while (1);return 0;
}

  • 练习4-2

编写一段程序,像下面一样读取两个数的值,然后计算出它们之间所有整数的和。

请输入两个整数

整数 a:37

整数 b:28

大于等于28,小于等于37的所有整数的和是325

✏️解答:

//练习4-2
#include <stdlib.h>
int main()
{do{//由于每一次循环,都需要将sum和count置为0,所以不如放在循环内部声明int a = 0, b = 0, sum = 0, count = 0;//sum求和,count记录a和b之间的个数printf("请输入两个整数\n");scanf("%d %d", &a, &b);//这样写的话,scanf()函数可以读取两个值,中间用空格分隔//由于不知道a和b的大小关系,所以使用到绝对值函数abs(),需要包含头文件<stdlib.h>count = abs(a - b) - 1;//计算a和b之间的数字个数(不包括a和b)//这里使用while循环求和do {sum += ((a < b ? a : b) + count);count--;} while (count > 0);sum += (a + b);//加上端点值//这样打印是考虑到a和b的大小关系printf("大于等于%d,小于等于%d的所有整数的和是%d\n", (a < b ? a : b), (a > b ? a : b), sum);printf("继续请输入1,退出请输入0\n");scanf("%d", &a);//借用a变量判断是否继续循环if (a == 0)break;//这里需要注意的是,借用的变量不能乱借,要借能够重新赋值的变量,不然会造成结果出错} while (1);return 0;
}

注意,上面的代码在计算count变量时,如果不想使用abs()函数,可以这样写:

count = ((a > b ? a : b) - (a < b ? a : b)) - 1;

第二节:while语句

  • while语句

while语句再循环结构中使用的频率很高,它几乎与do-while语句相同,只不过要先判断循环条件的真假,再进行循环,而do-while循环至少执行一次循环,其他地方二者都是一样的。

下面看一个程序,从输入的整数开始倒数到0。

//从输入的整数开始倒数到0(有修改)
int main()
{int num = 0;printf("请输入一个正整数\n");scanf("%d", &num);while (num >= 0)printf("%d ", num--);//先打印num的值,之后--return 0;
}

  • 用递减运算符简化程序代码

这个简化后的版本就是我上面写的代码,也就是用“printf("%d ", num--)”代替“printf("%d ", num)和num--”。

  • 数据递增

编写一个程序,使其从0开始递增(减)到输入的整数。

//从0开始递增(减)到输入的整数(有修改)
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);int i = num;if (num > 0){while (i >= 0)printf("%d ", num - (i--));}else if (num < 0){while (i <= 0)printf("%d ", num - (i++));}elseprintf("%d ", num);return 0;
}

  • 限定次数的循环操作

这个早就接触过了,也就像上面循环条件中的“i >= 0”这样,通过i的改变,导致循环次数的改变,比如i如果是10,该循环就执行11次。这个循环条件可以是变量、常量、表达式、函数调用等。

  • 字符常量和putchar()函数

用英文单引号括起来的字符称为字符常量(只能括一个字符),比如'a'、'?'、'&'等。用英文双引号括起来的称为字符串(无论个数多少),比如""(空字符串)、" "(空格字符串)、"abc"等。

putchar()函数是用来显示一个字符的,也可以使用printf()函数替换。

//putchar()函数
int main()
{char a = '@';putchar('?');putchar(a);printf("%c\n", '?');//%c用来打印字符printf("%c\n", a);return 0;
}

可以看出,putchar()函数也没有换行,个人认为printf()函数更好用一些。

  • do语句和while语句

关于两者的对比,上面已经说过了,这里不再重复了。

  • 前置递增运算符和前置递减运算符

上面讲后置的时候已经说过了。

  • do语句的显示

作者说do-while语句和while语句中都含有while,因此有时很难区分,其实当我们看见do的时候,找到它下面的花括号({}),之后花括号后面的第一个while就是do-while语句中的while。不好区分很大原因是代码写的凌乱(记住一点,do-while循环和while循环一样,如果循环内部只有一行代码,可以不写{},但是那样就不好区分,因此我都是无论do-while循环内部有多少代码,都写上{}加以区分)。

  • 逆向显示整数值

下面看这个程序,输入一个非负整数,进行逆向显示,比如输入1963,输出结果为3691。

//逆向显示整数值
int main()
{int num = 0;printf("请输入一个正整数\n");scanf("%d", &num);while (num > 0){printf("%d", num % 10);//通过模10操作,拿到num的最后一位num /= 10;//去掉num的最后一位}//模拟输出结果,假设输入1963//第一次循环:num == 1963, num % 10 == 3(此时输出3), num / 10 == 196//第二次循环:num == 196, num % 10 == 6(此时输出6), num / 10 == 19//第三次循环:num == 19, num % 10 == 9(此时输出9), num / 10 == 1//第四次循环:num == 1, num % 10 == 1(此时输出1), num / 10 == 0, 退出循环return 0;
}

我们可以通过模10再除等10的操作,拿到一个数字的每一位(从个位开始)。

📝课后习题

  • 练习4-3

对第二节while语句中第一个代码(从输入的整数开始倒数到0)进行修改,当输入的值为负数的时候不执行换行操作。

注意:由于我对代码进行了一些修改,所以当输入负数时,结果不进入循环,程序直接结束。因此不如将练习4-3改为输入负数时,从该负数开始输出到0。

✏️解答:

//练习4-3
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);if (num > 0){while (num >= 0)printf("%d ", num--);}else if (num < 0){while (num <= 0)printf("%d ", num++);}elseprintf("%d ", num);return 0;
}

  • 练习4-4

对练习4-3的代码进行修改,使其递(增)减到1。

✏️解答:

将while循环中的“num >= 0”和“num <= 0”改成“num >= 1”和“num <= 1”即可。

  • 练习4-5

对“从0开始递增(减)到输入的整数”的程序进行修改,使其从1(-1)开始递增(减)。

✏️解答:

//练习4-5
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);int i = num;if (num > 0){while (i > 0)printf("%d ", num - (i--) + 1);}else if (num < 0){while (i < 0)printf("%d ", num - (i++) - 1);}elseprintf("%d ", num);return 0;
}

  • 练习4-6

编写一个程序,像下面这样按照升序显示出小于输入值的所有正偶数。

请输入一个整数:19

2 4 6 8 10 12 14 16 18

✏️解答:

//练习4-6
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);int i = num;while (num > 1)printf("%d ", i - (num -= 2));return 0;
}

  • 练习4-7

编写一个程序,像下面这样显示出小于输入的整数的所有2的乘方。

请输入一个整数:19

2 4 8 16

✏️解答:

//练习4-7
int main()
{int num = 0, i = 1;printf("请输入一个整数\n");scanf("%d", &num);while (num - (i * 2) > 0)printf("%d ", i *= 2);return 0;
}

  • 练习4-8

编写一个程序,使得输入一个整数,连续显示出该整数个'*',之后输出换行符,当输入的值小于1时,不输出换行符。

✏️解答:

//练习4-8
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);if (num > 0){while (num--)printf("%c", '*');printf("\n");}return 0;
}

  • 练习4-9

编写一个程序,像下面这样交替显示+和-,总个数等于所输入的整数值。另外,当输入0以下的整数时,什么也不显示。

正整数:13

+-+-+-+-+-+-+

✏️解答:

//练习4-9
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);if (num % 2 == 1){printf("+");num -= 1;}while (num > 0){printf("-+");num -= 2;}return 0;
}

  • 练习4-10

编写一个程序,像下面这样连续显示*,总个数等于所输入的整数值,当输入0以下的整数时,什么也不显示。

正整数:3

*

*

*

✏️解答:

//练习4-10
int main()
{int num = 0;printf("请输入一个整数\n");scanf("%d", &num);while ((num--) > 0)printf("*\n");return 0;
}

  • 练习4-11

对上面逆向显示整数值的代码进行修改,使其像下面这样,在显示输出结果的同时,显示输入的整数值。

请输入一个正整数:1963

1963的逆向显示的结果是3691。

✏️解答:

只需要在上面代码的while循环的上一行加上“printf("%d逆向显示的结果是", num);”即可。

  • 练习4-12

编写一个程序,像下面这样,读取一个正整数,显示其位数。

请输入一个正整数:1963

1963的位数是4。

✏️解答:

注意到while循环的循环次数就是num的位数,所以只要再定义一个变量count用来记录循环次数即可。

//练习4-11
int main()
{int num = 0, count = 0;//count用来记录循环次数printf("请输入一个正整数\n");scanf("%d", &num);int i = num;//记录原来的数字while (num > 0){num /= 10;//由于不需要输出末位数,所以直接执行num/10即可count++;}printf("%d的位数是%d", i, count);return 0;
}

补充练习:

编写一个程序,输入一个整数,正向拿取到该整数的每一位,中间用空格分隔,比如:

请输入一个整数:1963。

输出结果:1 9 6 3。

✏️解答:

//补充练习
//由于没有学习数组和函数递归,因此采用下面的方法
#include <math.h>
int main()
{int num = 0, count = 0;//count记录循环次数,也就是num的位数printf("请输入一个正整数\n");scanf("%d", &num);int i = num;//统计num的位数while (i > 0){i /= 10;count++;}while (count)printf("%d ", (num / (int)pow(10, --count)) % 10);//pow(double x, double y)是C语言的库函数,用来计算x的y次幂,头文件为<math.h>//pow()函数的返回值是浮点型,所以强转为int类型//模拟输出结果:已知num == 1963, count == 4//第一次循环,pow() == 10^3,num / 1000 == 1,1 % 10 == 1,count变成3//第二次循环,pow() == 10^2,num / 100 == 19,19 % 10 == 9,count变成2//第三次循环,pow() == 10^1,num / 10 == 196,196 % 10 == 6,count变成1//第四次循环,pow() == 10^0,num / 1 == 1963,1963 % 10 == 3,count变成0,退出循环return 0;
}

相关文章:

  • pytorch写张量pt文件,libtorch读张量pt文件
  • log4cpp 使用指南
  • OpenCV 图形API(66)图像结构分析和形状描述符------将一条直线拟合到三维点集上函数fitLine3D()
  • linux用户管理
  • 什么是 HENGSHI SENSE?
  • 视觉导航中的回环检测技术解析
  • 基于STM32的便携式游戏机开发
  • 工控主板在船舶智能设备中的应用
  • 合理布局结构体,精打细算 cacheline
  • CONVOLUTION MEETS LORA(卷积遇到LORA)
  • 【大模型微调与应用开发实战指南】从理论到工业级部署
  • 【java】lambda表达式总结
  • SALOME源码分析:Geomtry模块
  • Vue响应式数据详解
  • Embedding入门概述
  • 制作一款打飞机游戏27:精灵编辑器UI
  • python文本合并脚本
  • G1(Garbage-First)垃圾回收器与JVM内存
  • 闭包与装饰器(python)
  • Go语言企业级项目使用dlv调试
  • 伊朗港口爆炸已致46人死亡
  • 当AI开始深度思考,人类如何守住自己的慢思考能力?
  • 马上评丨学生举报食堂饭菜有蛆,教育局应该护谁的犊子
  • 十大券商看后市|A股风险偏好有望边际改善,市场仍处黄金坑
  • 气温“过山车”现象未来或更频繁且更剧烈
  • 十四届全国人大常委会第十五次会议在京举行,审议民营经济促进法草案等