【C语言学习笔记】二、流程控制与语言结构

(三)流程控制与语言结构

条件控制语句:if 语句、switch语句
循环控制语句:while语句、do...while 语句、for语句
跳转语句:break语句、continue语句、goto语句

1、if 语句

(1)最简单的if语句判断

  • if 后面的小括号()不能省,小括号里面是写表达式的,当判断这个表达式的返回值是真的时候,就执行if下面的语句块;当判断这个表达式的返回值是假的时候,就跳过if语句。所以,小括号里面的表达式,你也可以直接写1或0,就是真或假。
  • if 下面的花括号{}可以省,当花括号省略了,花括号里面的代码块也可以不用缩进。编译也是可以通过的,不会报语法错误。但是不建议省略。

(2)if...else...语句

(3)if...else if..else if...else...语句

这里把花括号给省略了,这里因为简单,省略了更清晰,所以也可以省略。

2、switch语句

注意,case 只是标志一个位置而已,所以当switch后面表达式等于某个case后面的表达式时,就跳到那个case,执行那个case后面的语句,所以,你一定要记得加break,执行完毕这个case后面的代码块后就跳出switch语句! 如果你不加break,就接着执行下面一个case语句中的打印,直到打印完毕default才跳出switch代码块!因为case只是一个标志,没有判断的逻辑!就是这里的case关键字没有判断逻辑,仅仅是一个标志。

3、分支结构的嵌套

(1)代码示例1:用户输入2个数字,程序判断这个2个数之间的大小关系。

  • scanf 函数
    格式化输入函数,就是从标准输入流中读取格式化字符串。和printf格式化输出函数正好相反。

(2)代码示例2:分支嵌套

  • getchar()函数
    getchar()函数是把空格回车等字符过滤掉,不然第二个scanf接受到的输入就是你输入第一个scanf的第二个字符,比如你在第一个scanf输入Y+回车时,程序立马就给变量isFree赋值Y,同时执行到第二个scanf,给第二个scanf赋值为回车,所以程序继续往下跑,就跑结束了。所以这里如果我们想输完第一个scanf,再继续输入第二个scanf,那两个输入之间要加一行代码:getchar(),意思就是你把第一次输入的内容中的空格回车等字符去掉。所以当你输入Y+回车时,getchar()就把后面的回车去掉了,程序执行到第二个scanf就得夯住,等待用户第二次输入。

getchar()是从标准输入流(stdin)中获取下一个字符,是一个一个获取的。相当于调用 getc(stdin) 函数。所以这个函数没有参数。
如果函数调用成功,返回值是获取的字符(用整型表示其 ASCII 码),就是返回一个char类型的值。
如果返回值是 EOF,表示该函数调用失败,或者是标准输入流位于处于结束的位置。
EOF是个宏定义,值为-1,是定义在stdio.h头文件里面的,所以我们可以直接用EOF。

  • 悬挂else问题
    c语言有一个原则就是,else始终以最接近它的if匹配,所以即使有缩进,也不一定是按照缩进表示的语句流来执行的:
    如果上面的代码第一个if后面没有花括号,else后面也没有花括号,那即使else是和第一个if对其,编译器也会把else匹配给第二个if,以为else是第二个if的else,就按照这个逻辑来执行语句流了。
    所以,也提醒我们在写if语句的时候最好不要省略{}花括号,不然逻辑出错,也不会有报错,debug的时候就很困难。

4、while语句
上面讲的都是分支结构,这里开始讲循环结构。
循环结构就是重复多次的执行同一段代码。C语言有很多方式来实现循环结构。

(1)代码示例:计算1+2+...+100的结果

(2)代码示例:统计从键盘上输入一行字符,自动计算字符的个数。

我们统计的是英文,因为一个英文字母就是一个字符,但中文就不是,一个汉字可能就是好几个ASCII编码。
只要用户不敲回车键,就一直统计,直到用户敲回车键,getchar函数获取的值就等于回车的ascll码,就跳出while循环,执行下面的打印语句。
\r \n区别是:\n是换行,英文是New line。\r是回车,英文是Carriage return。\r与\n合起来就是回车换行的意思,回车是将光标移到当前行的行首;换行是将光标移到当前行的下一行,但还是同一列,不会回到行首。

5、do...while 语句

代码示例:计算1+2+...+100的结果

do...while是先执行do下面的代码块,执行一次后,再执行while里面的条件,如果条件为真,继续再执行一次do里面的代码块,直到while条件为假,不再执行do,继续执行while下面的代码。

注意while语句后面一定不能忘记还有一个;号,表示语句结束。

6、for 语句
从上面的循环结构我们可以看到,一个循环结构至少要有:初始化计数器、循环条件、更新计数器 三个基本的操作。所以同理,for循环的语法是:

for (表达式1;表达式2;表达式3)
  循环体

三个表达式用分号隔开。表达式1是循环初始化表达式;表达式2是循环条件判断表达式;表示3是循环调整表达式。
三个表达式分别对应初始化计数器、循环条件、更新计数器 这三个基本操作。
三个表达式可以按照需要进行省略,但是分号不能省!!!比如,for(; ;)就表示while(1) 就是永远循环下去,就是一个死循环。

(1)一个最简单的for循环

(2)判断一个数是否为素数。
素数是只能被1和自身整除,无法被其他自然数整除的数字。
判断一个数字是否是素数的方法有很多,这里我们用比较暴力的方法:迭代测试从2到num/2看这些数是否能被num整除,如果没有出现能被整除的,就是素数。

布尔变量flat=1表示是素数,flag=0不是素数。
如果num是素数的话,每次循环,if里面的除法取余都不等于0,所以都不执行if代码块,flag还是等于1,就是素数。如果取余等于0,flag就重新赋值为0,num就不是素数。

(3)for语句的灵活使用: 省略表达式

for循环里面的第一个参数可以省,如果省了就按默认值0开始循环,但第一个分号不能省,否则报错。当然,第二个分号也不能省!分号都不能省!!!
for循环里面的第三个参数如果省了,i就不自增了,就是无限循环了。

(4)for语句的灵活使用: 用逗号隔开的多个表达式

(5)for语句的灵活使用: C99允许在for语句的表达式1中定义变量
要知道:C语言中的定义变量是要放在程序的最开头位置,不能写在中间的。但是后来c99规定for语句中可以定义变量,并且这个变量只在for语句中有效,而且编译的时候要加-std=c99
比如:for(int i =0; i<10; i++)

这种写法编译执行的时候要加参数-std=c99

(6)for循环表达式1里面定义的变量,只能在循环体内有效,出了循环体就不能使用了。

7、循环嵌套
就是循环里面套循环。执行的时候是先执行内层循环再执行外层循环。

代码示例:打印一个九九乘法表

8、break 语句
前面我们讲switch语句的时候,case后面的break就是表示跳出整个switch语句。
但是,如果break在循环语句中,当执行到break时,程序就会自动跳出当前的循环。
所以,如果是循环嵌套,那break只负责跳出它所在的那一层循环。

我们前面求素数的例子,如果用户输入了一个非常非常大的数,那我们循环这个数的一半次,是不是浪费啊,现在利用break把这个案例修改一下:

(1)把变量i和num都给出longlong型的,与之对应的printf里面的都改成%lld
(2)for循环里面的if语句,把花括号加上,不然程序逻辑就错了。就是不报错,但计算结果是错的。加上{}花括号的意思就是,if条件成立了,flag变成0了,我就跳出循环。如果不加花括号,循环一次就遇到break跳出了。
(3)我们想看看到底是不是循环的次数少了,我们可以在最好打印一下i就知道了。

9、continue 语句
continue是当满足某个条件的时候,跳出本轮循环。就是比如在for循环中的某轮循环中,满足了某个条件,那continue后面的代码就不用执行了,直接开始下轮循环。

这里是while循环,当用户只要不输入回车就执行while循环:把用户输入的打印出了。
while里面嵌套的if条件是:当用户输入了1或者2或者3时,就continue,就是跳过此轮循环,所以下面的putchar就不执行了,继续下轮while循环。所以意思就是当用户输入了123就自动不显示了。

10、零散知识点补充

(1)左值(lvalue)、右值(rvalue)
在赋值运算中,比如:int a=5; 其中,a就是rvalue, 5就是lvalue。a是不可改变的,就是变量名是不可改变的,变量值5是可以改变的,5是可以改变成其他数字的。

变量名不可改变的意思是:变量名是一个地址号,地址号怎么能改变呢,就是内存地址在机器出厂时就规定好编号了,这个变量名是哪个地址号就是这个地址号了,是一个地址常量。后面要学数组,数组名也是这个数组第一个元素的内存地址,所以数组名也不能被改变,也是一个地址常量。而左值是可以改变的,就是我在这个内存地址单元里写入什么数字,就是存储什么数据,我是可以想存啥就存啥的,就是可以改变的,现在我存个5,我不乐意了,我可以存成6,这就是左值。

lvalue要理解为locator value(特定位置的值),是用于识别或定位存储位置的标识符。而且左值同时还必须是可改变的。
rvalue 则应该理解是 value of an expression(表达式的值)。rvalue 的发明完全是为了搭配 lvalue,rvalue 你可以理解为 readable value,即任何可读取的值都被认为是右值(非左值)。

(2)复合的赋值运算符

(3)自增自减运算符
当我们需要对一个变量加一或者减一,并赋值给本身的时候,我们就可以使用自增自减运算符。

当变量只是自己自增或自减的时候,i++ 和++i 没有什么区别,变量i都自增了1。
但是如果用自增或自减的变量给其他变量赋值的时候,i++ 和++i就有区别了,下面代码示例其区别:

j=++i 是先把变量i的值加1,然后再把值赋值给变量j
j=i++ 是先把变量i的值赋值给变量j,然后再把变量i的值加1

(4)逗号运算符

上面就是把3个语句,用逗号运算符,给结合到一块儿,变成一个语句。
赋值符号比逗号运算符的优先级要高。所以上图下面的例子就是后面的两个表达式。

注意,不是所有的逗号都是逗号运算符,有的地方出现的逗号仅仅是作为分隔符的作用而已。

(5)条件运算符

所以,当我们简单的判断一下的时候,就用条件运算符就非常简洁。

(6)goto语句
语法: goto 标签
作用是直接跳转到指定的标签位置。所以标签要定位于某个语句的前面。

说明:实际开发中还是建议谨慎使用goto语句,或者直接不要用!因为频繁使用goto会破坏程序的逻辑性,代码原来的逻辑就不清晰了。只有在多层循环中,如果我们想从最里层跳出所有循环,一层层的跳很麻烦,用goto可以一步到位直接跳到最外层。除此之外,建议不要用goto

(7)注释
// 这是单行注释,后面的内容编译器不会理会
/* 这是多行注释,就是注释了多行 */

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值