C程序设计2

您所在的位置:网站首页 html5循环语句 C程序设计2

C程序设计2

2023-03-18 21:37| 来源: 网络整理| 查看: 265

文章目录 一、引入(一)程序设计结构1 顺序结构2 选择结构3 循环结构 (二)语句1 表达式语句2 函数调用语句3 控制语句4 复合语句5 空语句 二、分支语句(一) if语句1 if 语句的语法结构代码块 2 悬空 else (二) switch语句1 break语句在分支语句的作用2 default子句 三、循环语句(一)循环结构概述1.什么是循环执行a.分析程序的执行结果b.分析数据的处理过程c.避免无限循环 2.循环结构的构成a.初始化部分b.判断部分c.循环部分d.迭代部分 (二)while循环1 基本用法2 while语句中的break和continuea.break介绍b.continue 介绍 3 从循环角度解释getchar和解决getchar的相关问题getchar()函数介绍 (三)for循环1 for循环语法及注意点2 for循环举例a试题1——判断代码循环次数b 试题2——计算阶乘c 试题3——计算 1!+2!+3!+……+10!c 试题4——实现顺序查找功能 (四)do...while循环1 基本框架2 do语句的特点 五.goto 语句1 goto语句的缺点2 goto语句的结构:3 goto语句的用法: 六.小结

一、引入 (一)程序设计结构

我们编写程序的目的是为了解决生活和生产中所遇到的问题,在大千世界中,解决问题的过程无非需要以下三种过程:

顺序过程选择过程循环过程

C语言是一种结构化的语言,在设计的时候就考虑了以下三种结构:

顺序结构选择结构循环结构 1 顺序结构

顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行,无特殊语句。 在这里插入图片描述

2 选择结构

选择结构用于判断给定的条件,根据判断的结果判断某些条件,根据判断的结果来控制程序的流程。其在C语言中由分支语句实现,主要有两种分支语句:

if语句switch语句

if语句的逻辑流程图——二选一 if语句的流程图 switch语句的逻辑流程图——多选一 switch语句流程图

3 循环结构

循环结构是结构化程序控制三种基本结构之一,使程序完成有规律的重复操作。在计算机中体现为某些语句被重复执行,这就是循环。循环结构可以用较少的语句解决复杂的运算,它是一种重要的、常用的程序设计方式。 循环结构特点为:在给定条件成立时,反复执行某程序段,直到条件不成立为止。 C语言提供了以下4钟循环结构:

用goto语句和if语句构成循环。用while语句。用do-while语句。用for语句。 由于用goto语句和if语句构成循环的方式可能会破坏程序的结构化,所以不常用。 (二)语句

以分号;结束的往往称为语句,而不是表达式,例如 3*4+5; 、a=c=d; 等 C语句可以分为以下五类

表达式语句函数调用语句控制语句复合语句空语句 1 表达式语句 int Add(int x, int y) { return x + y; } int main() { int n =0; n; /*变量表达式*/ 1000; /*常量表达式*/ a + 1; /*算术表达式*/ int m = 0; m = n; /*赋值表达式*/ m == n; /*关系表达式*/ n && m; /*逻辑表达式*/ n = Add(n, m); /*函数返回值为赋值表达式的操作数*/ return 0; } 2 函数调用语句

函数调用语句:由函数调用后添加分号构成,一般形式为 函数名(实际参数表);。执行函数调用语句,就是为函数传入实际参数,执行函数中的语句,并根据需要返回值的过程。函数调用语句的返回值也会被丢弃:

#include int Add(int x, int y) { return x + y; } int main() { int n = 1; int m = 2; /*调用自定义函数,未用返回值*/ Add(n, m); /*调用库函数*/ printf("n = %d, m = %d\n", n, m); return 0; } 3 控制语句

本文主要介绍的就是控制语句 控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选 择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。 可分成以下三类:

条件判断语句也叫分支语句:if语句、switch语句;循环执行语句:do while语句、while语句、for语句;转向语句:break语句、goto语句、continue语句、return语句。 4 复合语句

复合语句 复合语句(compound statement)简称为语句块,它使用大括号把许多语句和声明组合到一起,形成单条语句。 语句块与简单的语句不同,语句块不用分号当作结尾。当出现语法上某处需要一条语句,但程序却需要执行多条语句时,就可以用到语句块。例如,可以在 if 语句中使用语句块,或者当循环体需要执行多条语句时,也可以使用语句块:

{ double ret = 0.0, a = 0.0; // 声明 static long stu = 0; extern int lim; ++a; // 语句 if ( stu == 0 ) { // 新语句块 int i = 0; while ( stu == 0 && i /* ... */ } // 第三个语句块 }

如果语句块内需要有声明,通常会把声明放在语句块的头部,在其他语句之前。然而,C99 并不强制这么做,允许将声明放在语句块内的任何地方。 在语句块内声明的名称将具有语句块作用域。换句话说,这些名称只有自声明点开始,一直到语句块结尾之前有效。在这个作用域内,这种声明会把在语句块以外声明的同名称对象隐藏起来。 同样地,动态变量的存储周期也被限制在语句块中它们生成的地方。这意味着,如果一个变量没有被声明为 static 或 extern,那么该变量的存储空间会在语句块结束之后自动被释放。

5 空语句 int main() { int i = 0; for (; i if(表达式) { 语句列表1; } else { 语句列表2; } return 0; }

如果条件成立,要执行多条语句,怎应该使用代码块。

代码块

和上面提到的复合语句(语句块)其实是相同的概念,所谓代码块,就是由{ }包围起来的代码。代码块在C语言中随处可见,例如函数体、选择结构、循环结构等。 【注意】一般来说代码块花括号后不用加;,但结构体在定义时视为一条完整的语句,所以在花括号后加;

struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在学习小组 float score; //成绩 }; 2 悬空 else

我们看一段代码

#include int main() { int a = 0; int b = 2; if(a == 1) if(b == 2) printf("hehe\n"); else printf("haha\n"); return 0; }

这种对齐的方式很容易引起歧义,事实上,else的匹配原则式就近原则,即else是和它离的最近的if匹配的。代码改进如下。

//适当的使用{}可以使代码的逻辑更加清楚。 //代码风格很重要 #include int main() { int a = 0; int b = 2; if(a == 1) { if(b == 2) { printf("hehe\n"); } } else { printf("haha\n"); } return 0; }

另外,多加括号使得代码块结构分明,适合他人理解和自己复习。比如以下代码

//代码1 if (condition) { return x; } return y; //代码2 if(condition) { return x; } else { return y; } //代码3 int num = 1; if(num == 5) { printf("hehe\n"); } //代码4 int num = 1; if(5 == num) { printf("hehe\n"); }

以上四段代码都是对的,但2和4的可读性更高。 代码2较代码1而言结构更分明。 代码4保证了诸如新手典型错误 num =5 来作为判断条件的情况不发生,这样提高了容错性。

(二) switch语句

switch语句是一个多分支选择语句,并且可以支持嵌套。 switch语句的基本格式

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

switch语句通过将表达式的值与常量值进行比对,如果相等则执行后面的语句,如果不相等则跳到下一个case语句,当表达式和常量值相等,switch语句会将当前case语句以及后面所有的case语句全部输出。假如我们要实现用户输入一个数字来判断今天是星期几,那么就可以用下面的代码实现。

#include int main() { int day = 2; switch(day) { case 1: printf("星期一\n"); case 2: printf("星期二\n"); case 3: printf("星期三\n"); case 4: printf("星期四\n"); case 5: printf("星期五\n"); case 6: printf("星期六\n"); case 7: printf("星期天\n"); } return 0; }

运行结果如下图所示,可以看到当day=2时,switch语句将我2以及下面所有语句都执行,为了解决这个问题,我们引入了一个break语句。 在这里插入图片描述

1 break语句在分支语句的作用

当switch语句运行时遇到break关键字时会跳出,意思就是当语句运行到break时就不再运行了,接下来剩下的case语句也不会再执行,switch语句结束。

#include int main() { int day = 2; switch(day) { case 1: printf("星期一\n"); break; case 2: printf("星期二\n"); break; case 3: printf("星期三\n"); break; case 4: printf("星期四\n"); break; case 5: printf("星期五\n"); break; case 6: printf("星期六\n"); break; case 7: printf("星期天\n"); break; } return 0; }

在这里插入图片描述可以看到现在的情况,只输出一个星期二,这显然break语句已经生效,也达到了我想要的结果,还有一个值得注意的是,语句是可以为空语句的,那么我们将break和空语句结合起来就可以实现下面的代码。

int main() { int day = 2; scanf("%d", &day); switch (day)//整型表达式 { case 1: case 2: case 3: case 4: case 5: printf("工作日\n"); break; case 6: case 7: printf("休息日\n"); break; default: printf("输入错误\n"); break; } return 0; }

小提示:在分支语句中无法使用continue 编程习惯:在每个case或default子句后面都加上break,会减少编程错误概率。

2 default子句

default子句的作用是弥补如果表达式的值与所有case标签的值都不匹配的情况。 其实没有default也没什么,结果就是所有的语句都被跳过而已。程序并不会终止,也不会报错,因为这种情况在C中并不认为是个错误。但是,如果程序员并不想忽略不匹配所有标签的表达式的值时该怎么办呢?你可以在语句列表中增加一条default子句,把下面的标签default:写在任何一个case 标签可以出现的位置。 当 switch 表达式的值并不匹配所有case 标签的值时,这个default 子句后面的语句就会执行。 所以,每个switch语句中只能出现一条default子句。 但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。 在上面代码中,将day改为0就会输出错误提示。

每个switch后都加上default和break是一个较好的编程习惯

三、循环语句

循环结构是C语言的基本结构之一。在程序中有连续执行的操作可以用循环结构,简化函数,其特点是在给定条件成立时,反复执行每段程序,直到条件不成立为止(一次又一次的执行相同代码)。 C语言中有三种循环结构,for循环,while循环,do-while循环,其中for循环最常用。

(一)循环结构概述 1.什么是循环执行

循环执行是循环结构的核心,表现为反复执行一个或一组操作。在编程中,如果想要从数据处理中发现循环执行,就要分析程序的执行结果与数据的处理过程。

a.分析程序的执行结果

大部分程序在处理数据后,都有明确的执行结果。从程序的执行结果的表现形式和数量构成,往往可以找到重复执行的“痕迹”。

b.分析数据的处理过程

部分程序处理数据后没有明确的结果,或者结果非常简单,无法对其进行分析。这个时候,可以分析数据的处理过程,从中发现重复操作的规律。

c.避免无限循环

对于循环执行,一定要注意循环操作的终止条件,避免出现无意义的无限循环,也就是死循环,终止条件用于限制循环操作的无限执行,规定什么时候结束循环操作,如果没有会导致程序出现问题。

一般我们使用一个变量或多个变量来控制循环,避免无限循环的关键就是保证每次循环都使得其控制变量的范围缩小

2.循环结构的构成

一个完整的循环包括四个部分:

初始化部分判断部分循环部分迭代部分 a.初始化部分

初始化部分用来描述循环操作前的基本情况。在程序中,初始化部分一般由各种初始条件和额外的计数器组成。

b.判断部分

判断部分又称终止部分,用来在每次进行循环操作之前或者之后判断是否完成目标任务。

c.循环部分

循环部分是指反复执行的操作部分,其中可能是极其简单的操作,也可能是复杂的。

d.迭代部分

迭代部分是指用于修改关键状态,而该状态参与判断部分的处理。如果确实这个部分,就有可能陷入死循环。

(二)while循环 1 基本用法

while语句和if语句有相同之处,我们首先来回顾以下if语句

if(条件) { 语句; }

当条件满足的情况下,if语句后面的语句执行,否则不执行。但是这个语句只会执行一次。 如果实际问题要求反复执行,我们就需要引入while语句来实现循环。

//while 的语法结构,expr表示判断条件,stmt表示循环代码 while(expr) stmt;

其执行的语法流程如下图: while执行流程 根据流程图,进入while语句的时候,我们首先判断while(expr)中的条件expr是否成立,如果成立进入循环代码stmt,在stmt部分要实现迭代功能,执行完循环代码后继续回到条件判断;如果expr不成立则退出循环,执行while后的语句。

使用例子:用while循环实现打印1-10的整数

void test1() { int i = 1; while (i int i = 1; while (i break; } } }

执行结果如下 break 当循环执行到i==3时,打印3,然后i变为4,符合if判断,执行break退出循环,所以在屏幕上打印了1 2 3就停止了。 总结

break在while循环中的作用:其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。所以:while中的break是用于永久终止循环的。

b.continue 介绍

continue在C语言循环语句中的作用是跳出当前循环。跳出当前循环指的是跳出本次循环语句,并尝试再次进入循环语句。其功能示意图大致如下 continue示意图 我们通过一段代码来演示continue的作用

void test_continue1() { int i = 1; while (i continue; } printf("%d ", i);//循环部分 i++;//迭代部分 } }

在这里插入图片描述 程序似乎陷入了一种死循环,其原因是当i==4时直接跳出了当次循环,但是i并没有改变,所以应当修改程序,这就第一次体现了迭代部分的重要性。

//修改后的while代码 void test_continue2() { int i = 0; while (i continue; } printf("%d ", i);//循环部分 } }

在这里插入图片描述 总结:

continue在while循环中的作用就是:continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。

3 从循环角度解释getchar和解决getchar的相关问题 getchar()函数介绍

在 cplusplus.com上 查到了getchar()的相关信息如下 getchar 也就是说我们用一个int类型的变量接受从键盘处输入的一个字符。 我们来看一段代码:

//代码1 #include int main() { int ch = 0; while ((ch = getchar()) != EOF) putchar(ch); return 0; }

在这里插入图片描述 可以看到,getchar()函数忠诚的接受了每一个字符,包括换行,其原理如下图所示:

在这里插入图片描述 操作系统在内存中开辟了一个输入缓冲区,以匹配键盘速度和cpu处理速度不平衡的问题,也就是说,我们在键盘上输入的所有字符都会进入缓冲区,我们输入一个字符通常会输入回车提醒电脑输入完毕,但回车转化成为的换行’\n’也会在某些情况对我们的程序造成干扰,我们再来看一个例子。

int main() { char password[20] = { 0 }; printf("请输入密码:>"); scanf("%s", password); printf("请确认密码(Y/N):"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }

在这里插入图片描述 可以看到,我们并没有输入Y/N,自动识别为确认失败,在这种情况下,我们需要使用while来消除输入的回车

int main() { char password[20] = { 0 }; printf("请输入密码:>"); scanf("%s", password); //清理\n while (getchar() != '\n') { ; } printf("请确认密码(Y/N):"); int ch = getchar(); if (ch == 'Y') { printf("确认成功\n"); } else { printf("确认失败\n"); } return 0; }

在这里插入图片描述 通过while去掉了缓冲区中多余的换行符,这样就可以解决一部分getchar()所遇到的问题。

(三)for循环 1 for循环语法及注意点

我们已经知道了while循环,但是C语言中最常用,最严格,功能最强的循环语句其实是for循环。 首先看一下for循环的语法定义:

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

表达式1:表达式1为初始化部分,用于初始化循环变量的。 表达式2:表达式2为条件判断部分,用于判断循环时候终止。 表达式3:表达式3为调整部分,用于循环条件的调整。 C语言for循环流程图如下 在这里插入图片描述 看一段代码

int i = 0; //实现相同的功能,使用while i=1;//初始化部分 while(i printf("hehe\n"); }

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

tips 1.for循环中的循环变量尽量使用左闭右开的形式,这样方便显示循环次数 2.尽量不在for 循环体内修改循环变量,防止 for 循环失去控制。 3.for循环的初始化、条件判断、更新表达式三个方面都可以省略,但省略有时会造成bug,一般不要省,其实条件判断省略会进入死循环,更新表达式可以放在循环体内,初始化可以放在for语句之前 break和continue在for循环中和while循环中类似,但由于更新表达式在循环体之外,不用担心上文中涉及的continue死循环的问题

2 for循环举例 a试题1——判断代码循环次数 //请问循环要循环多少次? #include int main() { int i = 0; int k = 0; for(i =0,k=0; k=0; i++,k++) k++; return 0; }

答案是0次,因为判断语句是赋值语句,其真值为所赋予的值,判断恒为0,故不会进入循环。

b 试题2——计算阶乘 #define _CRT_SECURE_NO_WARNINGS #include //实现求解n! double fact(int n) { int i = 0; double ret = 1; for (i = 1; i double ret = fact(3); printf("%.0lf\n", ret); ret = fact(4); printf("%.0lf\n", ret); ret = fact(5); printf("%.0lf\n", ret); return 0; }

在这里插入图片描述

c 试题3——计算 1!+2!+3!+……+10! double SumFact(int n) { int fact1 = 1; int sum = 0; int i = 0; for (i = 1; i int i = 0; for (i = 0; i int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int len = (sizeof(arr) / sizeof(int));//数组的长度 int val = 0; while((scanf("%d",&val) != EOF)) { int order = linear_search(arr, len, val); if (order != -1) printf("%d在第%d个位置\n", val, order); else printf("未查到%d\n", val); } }

在这里插入图片描述 时间复杂度为O(n)

(四)do…while循环 1 基本框架 表达式1; do { 语句; } while(表达式2);

执行流程图入下 在这里插入图片描述

2 do语句的特点

特点:循环至少执行一次。 do while语句的使用的场景有限,所以不是经常使用。

do while 适合于循环代码至少执行一次的场景 其使用continue和break的规则和逻辑与while一致 要注意条件控制变量的改变,使用continue的过程中也许会造成死循环

五.goto 语句

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。

1 goto语句的缺点

它有一个致命的缺点:一旦滥用goto语句将会导致逻辑混乱,导致系统崩溃等问题。

2 goto语句的结构: again: 语句; goto again;//again可以替换成其他的,这里不要求一定是again 3 goto语句的用法: for(...) for(...) { for(...) { if(disaster) goto error; } } … error: if(disaster) // 处理错误情况

某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过 程。比如结束多层嵌套的使用。

六.小结

充分利用顺序结构、选择结构和循环结构可以将生活中的问题代码化,从而使得部分问题可以利用编程妥善解决。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3