c语言流程控制的三种基本结构,c语言程序流程控制的三个常用结构

  c语言流程控制的三种基本结构,c语言程序流程控制的三个常用结构

  C语言系列:3、过程控制文章目录C语言系列:3、流程控制1。语句和块2。if-else语句3。else-if语句4。转换语句5。while循环和for循环6。do-while循环7。中断语句和继续语句8。转到语句和标签1。语句和块添加分号(;),他们成为

  声明。例如:

  x=0;

  我;

  printf(.);在C语言中,分号是一个语句的结束,而Pascal等语言使用分号作为语句之间的分隔符。

  一组声明和语句用一对大括号“{”和“}”括起来,形成一个复合语句(也称为

  程序块),复合语句在语法上等同于单个语句。函数体中用花括号括起来的语句就是一个明显的例子。

  If、else、while和for后面用花括号括起来的几个语句都是类似的例子。右花括号用于结束代码块,其后不需要分号。

  2.if-else语句if-else语句用于条件判断,其语法如下:

  如果{表情}

  1项声明

  其他

  2语句,其中else部分是可选的。语句执行时,先计算表达式的值,如果其值为真(即表达式的值不为0),则执行语句1;如果其值为false(即表达式的值为0),并且语句包含else部分,则执行语句2。

  因为if语句只是一个简单的测试表达式,所以可以简化一些代码的编写。最明显的例子写如下

  If(表达式)代替

  如果(表情!0)在某些情况下,这种形式自然是清楚的,但在另一些情况下,意思可能就不清楚了。

  因为if-else语句的else部分是可选的,所以在嵌套的if语句中省略它的else部分会导致歧义。解决方案是,如果没有else对,则将else与最近的前一个匹配。

  例如,在下面的语句中:

  如果(n ^ 0)

  如果(a b)

  z=a;

  其他

  z=b;else部分匹配内层的if,从程序的缩进结构也能看出来。如果这不符合我们的意图,我们必须使用花括号来强制正确的匹配关系:

  if (n 0) {

  如果(a b)

  z=a;

  }

  其他

  z=b;在以下情况下,模糊尤其有害:

  如果(n ^ 0)

  for(I=0;I n;我)

  if (s[i] 0) {

  printf( . ));

  返回I;

  }

  else /*错误*/

  printf(error - n为负\ n );程序的缩进结构清楚地表明了设计意图,但编译器无法获得这些信息,它会将else部分与内层的if配对。这种错误很难发现,所以我们建议在有嵌套if语句的情况下使用花括号。

  顺便提醒读者,在声明中

  如果(a b)

  z=a;

  其他

  z=b;z=a后面是分号。这是因为,从语法上讲,if后面应该跟一个类似“z=a;这个类的表达式语句总是以分号结尾。

  3.else-if语句在C语言中,我们经常使用以下结构:

  If(表达式)

  句子

  Else if(表达式)

  句子

  Else if(表达式)

  句子

  Else if(表达式)

  句子

  Else,这里就单独解释一下吧。这种if语句序列是编写多路径决策最常用的方法。将依次计算的表达式。一旦表达式的结果为真,相关的语句将被执行,整个语句序列的执行将被终止。类似地,每个语句可以是单个语句,也可以是用花括号括起来的复合语句。

  最后一个else部分用来处理“以上条件都不成立”的情况或者默认情况,即以上条件都不满足的情况。有时,没有必要对默认值执行显式操作。在这种情况下,您可以将

  Else部分省略;这个部分也可以用来检查错误,以捕捉“不可能”的情况。

  这里,用一个二分搜索法函数来说明三向判断程序的用法。这个函数用于确定一个特定的值x是否存在于排序后的数组v中。数组v的元素必须按升序排列。如果x包含在v中,函数返回x在v中的位置(0到n-1之间的整数);否则,该函数返回-1。

  对半查找时,首先将输入值X与数组v的中间元素进行比较,如果X小于中间元素的值,则在数组的前半部分查找;否则,在数组的后半部分寻找。在这两种情况下,下一步是将X与所选零件的中间元素进行比较。这个过程一直持续到找到指定的值或者搜索范围为空。

  /* binsearch:在v[0]=v[1]=中查找x.=v[n-1] */

  int binsearch(int x,int v[],int n)

  {

  int低、高、中;

  低=0;

  高=n-1;

  while(低=高){

  mid=(低高)/2;

  if (x v[mid])

  高=中1;

  else if (x v[mid])

  低=中1;

  else /*找到匹配项*/

  返回mid

  }

  return-1;/*不匹配*/

  }这个函数的基本判断是:在每一步判断x是否小于、大于或等于中间元素v[mid]。使用

  else-if结构做出这个决定是很自然的。

  4.switch语句switch语句是一个多通道的判断语句,测试表达式是否匹配某个常量整数值的某个值,并执行相应的分支动作(常量整数值使switch呈现鸡肋,这一块在Go中进行了优化)。

  开关(表达式){

  Case表达式:语句序列

  Case表达式:语句序列

  默认值:语句序列

  }每个分支由一个或多个整数值常量或常量表达式标记。如果一个分支匹配表达式的值,它将从该分支执行。分支表达式必须互不相同。如果没有分支可以匹配表达式,则执行标记为默认的分支。默认分支是可选的。如果没有默认分支,也没有其他分支与表达式的值匹配,则switch语句不执行任何操作。每个分支和默认分支的顺序是任意的。

  我们使用if…else if…else结构编写了一个程序来计算每个数字、空格和所有其他字符的出现次数。让我们用switch语句重写程序,如下所示:

  #包含stdio.h

  main() /*计数位数、空格、其他*/

  {

  int c,I,nwhite,nother,ndigit[10];

  n white=nother=0;

  for(I=0;i 10我)

  ndigit[I]=0;

  while ((c=getchar())!=EOF) {

  开关(c) {

  大小写“0”:大小写“1”:大小写“2”:大小写“3”:大小写“4”:

  大小写“5”:大小写“6”:大小写“7”:大小写“8”:大小写“9”:

  ndigit[c- 0 ];

  打破;

  案例“”:

  大小写 \n :

  大小写 \t :

  n白色;

  打破;

  默认值:

  其他;

  打破;

  }

  }

  printf( digits=);

  for(I=0;i 10我)

  printf( %d ,ndigit[I]);

  printf(,空白=%d,其他=%d\n ,nwhite,nother);

  返回0;

  }break语句将导致程序的执行立即从switch语句中退出。在switch语句中,case

  的作用只是一个标签。因此,一个分支中的代码执行完之后,程序会在下一个分支中继续执行,除非在程序中显式跳转。跳出switch语句最常见的方法是使用break语句和return语句。break语句还可以强制控制立即退出while、for和do循环语句,我们将在后面进一步介绍。

  依次执行每个分支的做法有利也有弊。从好的方面来说,它可以组合几个分支来完成一项任务,比如上面例子中对数字的处理。但是,在正常情况下,为了防止直接执行下一个分支,每个分支都必须以break语句结束。从一个分支到下一个分支并不完美,修改程序时很容易出错。除了计算需要多个标签的情况之外,应该尽量减少直接从一个分支到下一个分支,并且在必须使用时应该添加适当的程序注释。

  作为一种好的编程风格,在switch语句的最后一个分支(默认分支)之后

  还要添加一个break语句。这在逻辑上是不必要的,但当我们需要在switch语句后添加其他分支时,这种预防措施会降低出错的可能性。

  5.while循环语句中的while循环和for循环

  While(表达式),先求表达式的值。如果其值不为0,则执行该语句并再次计算表达式。这个循环过程一直持续到表达式的值为0,然后继续执行语句的后面部分。

  For循环语句:

  For(表达式1;表情2;3)它等效于下面的while语句:

  表情1;

  While(表达式2) {

  句子

  表情3;

  }但当while或for循环语句包含continue语句时,上述两个语句不一定等价。

  从语法的角度来看,for循环语句的三个组成部分是表达式。最常见的是,表达式1和3是赋值表达式或函数调用,表达式2是关系表达式。这三个部分中的任何一个都可以省略,但是分号必须保留。如果在for语句中省略了表达式1和3,它就会退化为while循环语句。如果测试条件(表达式2)被省略,它的值总是被认为是真值。因此,下面的for循环语句:

  for(;) {

  .

  }是一个“无限”循环语句,需要其他手段(如break语句或return语句)来终止其执行。

  设计程序时,选择while循环语句还是for循环语句,主要取决于程序员的个人喜好。例如,在下面的语句中:

  while((c=getchar())== c== \ n c= \ t )

  ;/*跳过空格字符*/因为里面没有初始化或重新初始化,所以使用whi1e loop语句更自然。

  如果语句中需要简单的初始化和变量增量,使用for语句更合适,它将循环控制语句集中在循环的开始,使结构更加紧凑清晰。这可以从下面的声明中清楚地看出:

  for(I=0;I n;我)

  .这是C语言处理数组前N个元素的习惯用法。它类似于Fortran语言中的DO循环或Pascal语言中的for循环。但这种类比并不完全准确,因为在C语言中,for循环语句的循环变量和上限可以在循环体中修改,循环变量I的值在循环因故终止后仍然保留。因为for语句的每个组成部分可以是任何表达式,所以for语句不限于通过算术级数进行循环控制。但把一些无关紧要的计算放在for语句的初始化和变量增量部分,是不良的编程风格,更适合循环控制操作。

  举个大例子,让我们重写函数atoi,将字符串转换成相应的数值。

  以下是程序的结构,从中可以看出输入的格式:

  如果有空白字符,跳过它。

  如果有符号,请阅读符号。

  取整数部分,并执行转换。转换的每一步都会相应地处理输入数据,并为下一步做准备。当遇到第一个不能转换成数字的字符时,整个过程终止。

  #包含ctype.h

  /* atoi:将s转换为整数;版本2 */

  int atoi(char s[])

  {

  int i,n,sign

  for(I=0;is space(s[I]);i ) /*跳过空白*/

  ;

  sign=(s[i]==-)?-1 : 1;

  if (s[i]== s[i]==-) /*跳过符号*/

  我;

  for(n=0;is digit(s[I]);我)

  n=10 * n(s[I]- 0 );

  回车符* n;

  }标准库中提供了更完善的函数strtol,将字符串转换为长整数。有关strtol函数的详细信息,请参见附录B.5。

  对于多个嵌套循环,将循环控制部分集中在一起具有更明显的优势。下面的函数是一个Shell排序算法,用于对整数数组进行排序。Shell排序算法是由D. L. Shell于1959年发明的。它的基本思想是:先比较较远的元素,而不是像简单的交换排序算法那样先比较相邻的元素。这样可以快速减少大量无序的情况,从而缓解后续工作。被比较元素之间的距离逐渐减小,直到减小到1,此时排序就变成了相邻元素的交换。

  /* shellsort: sort v[0].v[n-1]按升序排列*/

  void shellsort(int v[],int n)

  {

  int gap,I,j,temp

  for(gap=n/2;差距0;间隙/=2)

  for(I=gap;I n;我)

  for(j=I-gap;j=0v[j]v[j gap];j-=间隙){

  temp=v[j];

  v[j]=v[j gap];

  v[j gap]=temp;

  }

  }此函数包含一个三重嵌套的for循环语句。最外层的for语句控制两个比较元素之间的距离,从n/2开始,逐渐对折,直到距离为0。中间层的for循环语句用于在元素之间移动位置。最里面的for语句用于比较由间隔位置分隔的元素对,当两个元素顺序相反时,它们会互换。由于gap的值最终将减少到1,所有元素最终都将处于正确的排序位置。注意,即使最外层for循环的控制变量不是等差数列,for语句的书写形式也保持不变,可见for语句具有很强的通用性。

  逗号“,”也是C语言中优先级最低的运算符,常用于for语句中。被戏弄

  由#分隔的一对表达式将从左到右求值,表达式右边的操作数的类型和值就是其结果的类型和值。这样,在一个for循环语句中,可以在每个语句组件中放置多个表达式,例如,可以同时处理两个循环控制模糊。我们可以以下面的函数reverse(s)为例。这个函数用于反转字符串s中每个字符的位置。

  #包含字符串. h

  /* reverse:原地反转字符串*/

  作废冲销(字符s[])

  {

  int c,I,j;

  for (i=0,j=strlen(s)-1;I j;我,j - ) {

  c=s[I];

  s[I]=s[j];

  s[j]=c;

  }

  }有些情况下逗号不是逗号运算符,比如逗号分隔函数参数,逗号分隔声明中的变量等。这些逗号并不保证表达式是从左向右计算的。

  逗号运算符应该谨慎使用。逗号运算符最适合于紧密相关的结构,比如上面reverse函数中的for语句,也适合于单个表达式中需要多步计算的宏。逗号表达式也适用于反向函数中的元素交换,这样元素交换就可以看作是单步操作。

  for (i=0,j=strlen(s)-1;I j;我,j -)

  c=s[i],s[i]=s[j],s[j]=c;6.do-while循环while和for这两个循环在执行循环体之前测试终止条件。相反,C语言中的第三个循环——do-while循环在执行完循环体后测试终止条件,使循环体至少执行一次。

  do-while循环的语法如下:

  做

  句子

  While(表情);在这种结构中,首先执行循环体中的语句部分,然后计算表达式的值。如果表达式的值为true,则再次执行该语句,依此类推。当表达式的值变为false时,循环终止。除了条件测试的语义不同,do-while循环等价于Pascal中的repeat-until语句。

  经验表明,do-while循环比while循环和for循环使用得少得多。尽管如此,做一会儿

  陈述有时是有用的。让我们用函数itoa来说明这一点。Itoa函数是atoi函数的反函数,将数字转换成字符串。这项工作比原先想象的更复杂。如果根据atoi函数中生成数字的方法将数字转换为字符串,则生成的字符串的顺序正好相反。因此,我们应该首先以相反的顺序生成字符串,然后反转字符串。

  /* itoa:将n转换为s中的字符*/

  void itoa(int n,char s[])

  {

  int i,sign

  if ((sign=n) 0) /*记录sign */

  n=-n;/*使n为正*/

  I=0;

  是否{ /*以逆序生成数字*/

  s[I]=n % 10“0”;/*获取下一个数字*/

  } while((n/=10)0);/*删除它*/

  如果(符号0)

  s[I]=-;

  s[I]= \ 0 ;

  反转;

  }这里有必要用do-while语句,至少用do-while语句会更方便,因为即使n的

  值为0时,数组s中至少要放一个字符,其中,do-while语句体中只有一个语句。尽管这是不必要的,我们仍然用花括号将语句括起来,这可以防止草率的读者将while部分误认为另一个while循环的开始。

  7.有时,break语句和continue语句不通过循环头或循环尾的条件测试就跳出循环是很方便的。Break语句可用于提前退出for、while和do-while等循环,就像提前退出switch语句一样。Break语句可以使程序立即跳出switch语句或最里面的循环。

  下面的函数trim用于删除字符串末尾的空格字符、制表符和换行符。当发现最右边的字符是非空格、非制表符和非换行符时,使用break语句退出循环。

  /* trim:删除尾随空格、制表符、换行符*/

  int trim(char s[])

  {

  int n;

  for(n=strlen(s)-1;n=0;n -)

  if (s[n]!= s[n]!=\t s[n]!=\n )

  打破;

  s[n 1]= \ 0 ;

  返回n;

  }strlen函数返回字符串的长度。for循环从字符串的末尾开始,以相反的方向扫描,查找第一个不是空格字符、制表符或换行符的字符。当找到满足条件的第一个字符时,或者当循环控制变量n变为负数时(即扫描整个字符串时),循环终止执行。读者可以验证这个函数是正确的,即使字符串是空的或者只包含空白字符。

  continue语句与break语句相关联,但不如break语句常见。继续语言

  句子用来使for、while或do-while语句开始下一个循环的执行。While和do-while

  语句,continue语句的执行意味着测试部分被立即执行;在for循环中,意味着控制转移到增量循环变量部分。continue语句仅用于循环语句,不用于switch语句。循环中包含的switch语句中的continue语句将导致下一个循环。

  例如,下面的程序用于处理数组a中的非负元素。如果元素的值为负,则跳过处理。

  for(I=0;I n;我)

  if (a[i] 0) /*跳过负元素*/

  继续;

  ./* do positive elements */当循环的后半部分比较复杂时,经常使用continue语句。在这种情况下,如果不使用continue语句,可能需要反向测试或者缩进另一层循环,这样会使程序的嵌套更深。

  8.goto语句和标签C语言提供了可以随意滥用的goto语句和标记跳转位置的标签。从理论上讲,goto语句是不必要的,在实践中,不使用goto语句也很容易编写代码。

  但是,在某些情况下,goto语句仍然有用。最常见的用法是在一些深度嵌套的结构中终止程序的处理,比如一次跳出两个或多个循环。在这种情况下,break语句无法实现目标。它只能从最里面的循环退出到下一个更高级别的循环(其他一些语言使用名称空间来处理这种情况)。以下是使用goto语句的示例:

  对于(.)

  对于(.) {

  .

  如果(灾难)

  goto错误;

  }

  .

  错误:

  /*收拾残局*/在这个例子中,如果错误处理代码很重要,错误可能出现在多个地方,那么使用goto语句会更方便。

  标签的名称与变量的名称相同,后跟一个冒号。该标签可以位于函数中相应goto语句所在的任何语句之前。标签的范围是整个函数。

  让我们看另一个例子。考虑确定两个数组A和B是否具有相同元素的问题。一个可能的解决方案是:

  for(I=0;I n;我)

  for(j=0;j m;j)

  if (a[i]==b[j])

  找到goto

  /*找不到任何公共元素*/

  .

  找到:

  /*得到一个:a[i]==b[j] */

  .所有使用goto语句的程序代码都可以重新编写成没有goto语句的程序,但可能会添加一些额外的重复测试或变量。例如,上述确定是否具有相同数组元素的程序段可以重写为以下形式:

  发现=0;

  for(I=0;我在!找到了;我)

  for(j=0;j . m!找到了;j)

  if (a[i]==b[j])

  发现=1;

  如果(找到)

  /*得到一个:a[i-1]==b[j-1] */

  .

  其他

  /*找不到任何公共元素*/

  .在大多数情况下,使用goto语句的程序段比不使用goto语句的程序段更难理解和维护,除了少数情况,比如我们前面提到的例子。虽然问题不太严重,但我们还是建议尽量少用goto语句。

  否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • c语言调用退出函数 c语言退出整个程序怎么写
  • c语言中怎么给函数初始化 c语言的初始化语句
  • c语言编写函数计算平均值 c语言求平均函数
  • 详解c语言中的字符串数组是什么,详解c语言中的字符串数组结构,详解C语言中的字符串数组
  • 表达式求值c++实现,c语言实现表达式求值
  • 看懂c语言基本语法,C语言详解,C语言的基本语法详解
  • 用c语言实现快速排序算法,排序算法设计与实现快速排序C语言,C语言实现快速排序算法实例
  • 深入解析c语言中函数指针的定义与使用方法,深入解析c语言中函数指针的定义与使用情况,深入解析C语言中函数指针的定义与使用
  • 描述E-R图,E-R图举例,关于C语言中E-R图的详解
  • 折半查找法C语言,折半查找算法(算法设计题)
  • 折半查找法C语言,c语言折半法查找数据,C语言实现折半查找法(二分法)
  • 扫雷小游戏c++代码设计,c语言扫雷游戏源代码,C语言实现扫雷小游戏详细代码
  • 怎样统计程序代码行数,C语言统计行数,C#程序员统计自己的代码行数
  • 基于c语言的贪吃蛇游戏程序设计,用c语言编写贪吃蛇游戏程序,C语言实现简单的贪吃蛇游戏
  • 图的两种遍历算法,图的遍历算法代码c语言,Python算法之图的遍历
  • 留言与评论(共有 条评论)
       
    验证码: