> 文章列表 > 【跟着陈七一起学C语言】今天总结:C语言的if选择结构和循环结构

【跟着陈七一起学C语言】今天总结:C语言的if选择结构和循环结构

【跟着陈七一起学C语言】今天总结:C语言的if选择结构和循环结构

友情链接:专栏地址

知识总结顺序参考C Primer Plus(第六版)和谭浩强老师的C程序设计(第五版)等,内容以书中为标准,同时参考其它各类书籍以及优质文章,以至减少知识点上的错误,同时方便本人的基础复习,也希望能帮助到大家
 
最好的好人,都是犯过错误的过来人;一个人往往因为有一点小小的缺点,将来会变得更好。如有错漏之处,敬请指正,有更好的方法,也希望不吝提出。最好的生活方式就是和努力的大家,一起奔跑在路上


文章目录

  • 【思维导图】
  • 🚀选择结构设计
    • ⛳一、if语句
      • 🎈(一)if语句的三种形态
      • 🎈(二)if语句的嵌套
    • ⛳二、switch语句循环结构设计
    • ⛳三、switch和if else的选择
    • ⛳四、拓展:goto语句
  • 🚀循环结构设计
    • ⛳一、三种基本循环
      • 🎈(一)while语句实现循环
      • 🎈(二)for语句实现循环
      • 🎈(三)do...while语句实现循环
    • ⛳二、while和do...while循环的比较
    • ⛳三、循环中的特殊控制:continue 与 break
    • ⛳四、循环嵌套
    • ⛳五、如何选择循环

【思维导图】

在这里插入图片描述

我的总结方式一般是先搞一段程序过来,然后再逐行的学习相关的知识点

 

🚀选择结构设计

⛳一、if语句

if ( expression ) statement

expression称为测试条件,if 和 if else 语句使用测试条件来判断执行哪些语句。所有非零值都被视为 true,零被视为false。测试通常涉及关系表达式(比较两个值)、逻辑表达式(用逻辑运算符组合或更改其他表达式)

如果对expression求值为真(非0),则执行statement;否则,跳过 statement,statement可以是一条简单语句或复合语句。通常,expression 是关系表达式,例如:

if(x>=0)printf("%d",x);

拓展:

1.C并不要求一定要缩进,但这是标准风格。缩进让根据测试条 件的求值结果来判断执行哪部分语句一目了然。

2.要记住一个通用原则,如果要测试两个条件,应该使用逻辑运算符把两个完整的测试表达式组合起来。例如:

if (a < x < z) // 错误,没有使用逻辑运算符 …if (ch != 'q' && != 'Q') // 错误,缺少完整的测试表达式 … //正确的方式:用逻辑运算符连接两个关系表达式
if (a < x && x < z) // 使用&&组合两个表达式 … if (ch != 'q' && ch != 'Q') // 使用&&组合两个表达式 …

🎈(一)if语句的三种形态

简单形式的if语句可以让程序选择执行一条语句,或者跳过这条语句。 C还提供了if else形式,可以在两条语句之间作选择。但是如果要在if和else之间执行多条语句,必须用花括号把这些语句括起来成为一个块。

if ( expression )statement1 
else statement2

1.如果…那么

#include <stdio.h>int main(void) {int salary;printf("你月薪是多少");scanf("%d",&salary);if (salary < 20000) {printf("你是一个好人, 我还不想谈恋爱\\n");}return 0;
}

2.如果…那么…否则

#include <stdio.h>int main(void) {int salary;printf("你月薪是多少");scanf("%d",&salary);if (salary < 20000) {printf("你是一个好人, 我还不想谈恋爱\\n");} else {printf("我没有什么要求, 只要你对我好就行\\n");}return 0;
}

3.如果…那么…,或者…那么…,否则…

#include <stdio.h>int main(void)
{int salary;char houseRet[8]; //是否有房char carRet[8]; //是否有车printf("你月薪是多少");scanf("%d",&salary);printf("你有房吗");scanf("%s",carRet);printf("你有车吗");scanf("%s",carRet);if (salary < 20000) {printf("你是一个好人, 我还不想谈恋爱\\n");} else if (houseRet == "有") {printf("我其实没有什么要求,只要你对我好\\n");} else if (carRet == "有") {printf("我还不错哦, 以后再联系\\n");} else {printf("有缘再见\\n");}return 0;
}

🎈(二)if语句的嵌套

实例: 求 3 个数的最大值

#include <stdio.h>int main(void) {int x, y, z; printf("请输入 3 个整数:\\n"); scanf("%d%d%d",&x,&y,&z);if (x > y) {if (x > z) {printf("最大值是:%d\\n",x);} else {printf("最大值是:%d\\n",z);}} else {if (y > z) {printf("最大值是:%d\\n",y);} else {printf("最大值是:%d\\n",z);}}return 0;
}

嵌套的常见错误(配对错误),else与前面最近的,而且还没有配对的 if匹配,错误避免方法:

  1. 严格使用 { }
  2. 先写{}再写里面的内容
  3. 保持良好的“缩进
     

⛳二、switch语句循环结构设计

使用条件运算符和 if else 语句很容易编写二选一的程序。然而,有时程序需要在多个选项中进行选择。可以用if else if…else来完成。但是,大多数情况下使用switch语句更方便。

switch语句的作用是根据表达式的值,使流程跳转到不同的语句。switch语句的一般形式如下:

switch(表达式)
{case 常量表达式1:语句1case 常量表达式2:语句2case 常量表达式3:语句3default 表达式1:语句1
}

例如:

# include <stdio.h>
int main( ){char grade;scanf(" %c", &grade);printf(" Your score:" );switch(grade){case 'A': printf("85~ 100\\n") ;break;case 'B': printf("70~ 84\\n"); break;case 'C': printf("60~69\\n"); break;case 'D': printf("< 60\\n") ; break;default: printf("enter data error!\\n" );}
return 0;
}

在这里插入图片描述

  1. 程序分析:等级grade定义为字符变量,从键盘输人一个大写字母,赋给变量grade,switch得到grade的值并把它和各case中给定的值(‘A’,‘B’,‘C’,‘D’之一)相比较,如果和其中之一相同(称为匹配),则执行该case后面的语句(即printf语句)。输出相应的信息。如果输入的字符与’A’,‘B’,‘C’,‘D’ 都不相同,就执行default 后面的语句,输出“输入有错”的信息

  2. 可以没有default标号,此时如果没有与switch表达式相匹配的case常量,则不执行任何语句,流程转到switch语句的下一个语句。

  3. 各个case标号出现次序不影响执行结果。例如可以先出现default标号,再出现“case ‘D’: …”,然后是“case ‘B’: …”

  4. switch在圆括号中的测试表达式的值应该是一个整数值(包括char类型)。case标签必须是整数类型(包括char类型)的常量或整型常量表达式 (即,表达式中只包含整型常量)。不能用变量作为case标签。

  5. case标号只起标记的作用。在执行switch语句时,根据switch表达式的值找到匹配的入口标号,并不在此进行条件检查,在执行完一个case标号后面的语句后,就从此标号开始执行下去,不再进行判断。例如在例4.6中,如果在各case子句中没有break 语句,将
    连续输出:

    Your score:85~ 100
    70~ 84
    60~ 69
    60
    enter data error !
    
  6. break语句在其中起什么作用?它让程序离开switch语句,跳至switch 句后面的下一条语句。如果没有break语句,就会从匹配标签开 始执行到switch末尾,如第4点中的情况。一般情况下,在执行一个case子句后,应当用break语句使流程跳出switch结构,即终止switch语句的执行。最后一个case子句(今为default 子句)中可不必加break语句,因为流程已到了switch结构的结束处。

  7. 在case子句中虽然包含了一个以上执行语句,但可以不必用花括号括起来,会自动顺序执行本case标号后面所有的语句。当然加上花括号也可以。

  8. 多个case标号可以共用一组执行语句,例如:当grade 的值为’A’,‘B’ ,'C’时都执行同一组语句,输出“≥60”。然后换行。

    case
    ' A':
    case
    'B' :
    case
    'C' : printf("> 60\\n" ) ; break;
    

拓展:

1.以下错误,在 vs/vc 中有提示,但是仍可以通过编译。 在 gcc 编译器中,不能通过编译

switch(c) {
case 1:int x = 0; //错误!printf("c=1");break;
case 2:.......//应修改为
case 1:
{int x = 0; printf("c=1");
}
break;
case 2:......

2.continue语句:
 
break语句可用于循环和switch语句中,但是continue只能用于循环中。尽管如此,如果switch语句在一个循环中,continue便可作为 switch语句的一部分。
 
这种情况下,就像在其他循环中一样,continue让程序跳出循环的剩余部分,包括switch语句的其他部分。

 

⛳三、switch和if else的选择

何时使用switch?何时使用if else?经常会别无选择

如果是根据浮点类型的变量或表达式来选择,就无法使用 switch。如果根据变量在某范围内决定程序流的去向,使用 switch 就很麻烦,这种情况用if就很方便:

if (integer < 1000 && integer > 2)

使用switch要涵盖以上范围,需要为每个整数(3~999)设置case标签。但是,如果使用switch,程序通常运行快一些,生成的代码少一些。

 

⛳四、拓展:goto语句

早期版本的BASIC和FORTRAN所依赖的goto语句,在C中仍然可用。但是C和其他两种语言不同,没有goto语句C程序也能运行良好。Kernighan和 Ritchie提到goto语句“易被滥用”,并建议“谨慎使用,或者根本不用”

goto语句有两部分:goto和标签名。标签的命名遵循变量命名规则,如下所示:

goto part2

要让这条语句正常工作,函数还必须包含另一条标为part2的语句,该 语句以标签名后紧跟一个冒号开始:

part2: printf("Refined analysis:\\n");

避免使用goto

程序中使用其他形式比使用goto的条理更清晰。当多种情况混在一起时,这种差异更加明显。过度地使用 goto 语句,会让程序错综复杂。如果不熟悉goto 语句,就不要使用它
 

🚀循环结构设计

⛳一、三种基本循环

🎈(一)while语句实现循环

while循环的通用形式如下:

while ( expression ) statement
  1. statement部分可以是以分号结尾的简单语句,也可以是用花括号括起来的复合语句。
  2. expression部分是循环条件。执行循环体的次数是由循环条件控制的,它也称为循环条件表达式。当此表达式的值为“真”(以非0值表示)时,就执行循环体语句;为“假”(以0表示)时,就不执行循环体语句。

在这里插入图片描述

拓展:

1.伪代码

把sum初始化为0
提示用户输入数据
读取用户输入的数据
当输入的数据为整数时,
输入添加给sum,
提示用户进行输入,
然后读取下一个输入
输入完成后,打印sum的值

伪代码(pseudocode),是一种用简单的句子表示程序思路的方法,它与计算机语言的形式相对应。伪代码有助于设计程序的逻辑。确定程序的逻辑无误之后,再把伪代码翻译成实际的编程代码。使用伪代码的好处之一是,可以把注意力集中在程序的组织和逻辑上,不用在设计程序时还要分心如何用编程语言来表达自己的想法。例如,可以用缩进来代表一块代码,不用考虑C的语法要用花括号把这部分代码括起来。
 
2.C风格读取循环

status = scanf("%ld", &num);
while (status == 1)
{
/* 循环行为 */
status = scanf("%ld", &num);
}

可以用以下代码替换

while (scanf("%ld", &num) == 1)
{
/*循环行为*/
}

第二种形式同时使用scanf()的两种不同的特性。首先,如果函数调用成功,scanf()会把一个值存入num。然后,利用scanf()的返回值(0或1,不是 num的值)控制while循环,因为每次迭代都会判断循环的条件,所以每次迭代都要调用scanf()读取新的num值来做判断

死循环:当循环判断条件永远为真的时候即是一个死循环

while(1) {语句
}

🎈(二)for语句实现循环

while循环是不确定循环(indefinite loop)。所谓不确定循环,指 在测试表达式为假之前,预先不知道要执行多少次循环。另外,还有一类是计数循环(counting loop)。这类循环在执行循环之前就知道要重复执行多少次,即for循环

for语句的一般形式为

for(表达式1;表达式2;表达式3)语句
  • 表达式1:设置初始条件,只执行一次。可以为零个、一个或多个变量设置初值(如i=1)。
  • 表达式2:是循环条件表达式,用来判定是否继续循环。在每次执行循环体前先执行此表达式,决定是否继续执行循环。
  • 表达式3:作为循环的调整,例如使循环变量增值,它是在执行完循环体后才进行的。

在这里插入图片描述

拓展:

1.表达式 1、表达式 2、表达式 3, 这 3 个表达式的任意一个或多个,都可以省略! 但是其中的“;”不可以省略!

for (; ; ) {循环体
}
//相当于:
while (1) {循环体
}for ( ; test ; ) {循环体
}
//相当于:
while ( test ) {循环体
}

2.在 C89 标准中,表达式 1 不能定义变量,在 C99 标准和 C++中,表达式 1 可以定义变量 表达式 1 中定义的变量仅在 for 循环中有效。

3.若省略表达式2且在循环体中没有设置循环结束条件,那么该循环将成为一个死循环

🎈(三)do…while语句实现循环

前面讲的while和for循环也叫入口条件循环,除了while语句以外,C语言还提供了do…while语句来实现循环结构,它是一种出口条件循环。

do…while语句的一般形式为

do语句
while (表达式) ;

其中的“语句”就是循环体。它的执行过程可以用图5.4表示。请注意do…while循环用N-S流程图的表示形式(图5.4(b))。先执行一次指定的循环体语句,后判别表达式,当表达式的值为非零(“真”)时,返回重新执行循环体语句,如此反复,直到表达式的值等于0(“假”)为止时循环结束

在这里插入图片描述

在这里插入图片描述

拓展:

特殊用法:

do { // 循环体 
} while(0)

 

⛳二、while和do…while循环的比较

1.用while循环:

# include < stdio. h>int main( )
{int i,sum=0;printf(" please enter i,i=?");scannf("%d",&i);while(i<= 10){sum= sum+i;i++;}printf("sum=%d\\n",sum);return 0;
}

运行结果(两次):

please enter i,i=?1
sum = 55please enter i,i=?11
sum = 0

2.用do…while循环:

# include < stdio. h>
int main( )
{int i,sum= 0;printf(' please enter i,i=?");scanf("%d" ,&i);do{sum = sum+i;i++;}while(i< = 10);printf("sum=%d\\n",sum);return 0; 
}

运行结果(两次):

please enter i,i=?1
sum = 55please enter i,i=?11
sum = 11

可以看到,当输入i的值小于或等于10时,二者得到的结果相同;而当i>10时,二者结果就不同了。这是因为此时对while循环来说,一次也不执行循环体(表达式“i<=10”的值为假),而对d…while循环语句来说则至少要执行一次循环体。可以得到结论:当while后面的表达式的第1次的值为“真”时,两种循环得到的结果相同;否则,二者结果不相同(指二者具有相同的循环体的情况)。
 

⛳三、循环中的特殊控制:continue 与 break

break :结束本层循环。

continue :结束本次循环,进入下一次循环

for 语句中的 continue

在这里插入图片描述

while 语句中的 continue

在这里插入图片描述
 

⛳四、循环嵌套

要点: 把内层的循环,看成一个完整的“大语句”

#include <stdio.h>// 一天想我几次?
// 24 小时,每秒一次
int main(void) {int count = 0;for (int i=0; i < 24; i++) {for (int j=0; j<60; j++) {for (int k=0; k<60; k++) {count++; printf("%d:%d:%d想你第%d次\\n",i,j,k,count);Sleep(1000);}}}printf("一天想你%d次\\n",count);return 0;
}

 

⛳五、如何选择循环

  1. 首先,确定是需要入口条件循环还是出口条件循环。通常,入口条件循环用得比较多,有几个原因。其一,一般原则是在执行循环之前测试条件比较好。其二,测试放在循环的开头,程序的可读性更高。另外,在许多应用中,要求在一开始不满足测试条件时就直接跳过整个循环。
  2. 一般而言,当循环涉及初始化和更新变量时,用for循环比较合适,而在其他情况下用while循环更好。
  3. 对于涉及索引计数的循环,用for循环更适合

行文至此,落笔为终。文末搁笔,思绪驳杂。只道谢不道别。早晚复相逢,且祝诸君平安喜乐,万事顺意。