C语言进阶教程之循环语句缺陷详析

目录
  • 前言
  • 1 循环语句的三要素
  • 2 使用不同循环语句实现六种排列组合
    • 2.1 第一种排列(ABC)
    • 2.2 第二种排列(ACB)
    • 2.3 第三种排列(BCA)
    • 2.4 第四种排列(CBA)
    • 2.5 第五种排列(BAC)
    • 2.6 第六种排列(CAB)
  • 3 什么时候用for循环语句
  • 4 什么时候用while循环语句
  • 5 什么时候用do-while循环语句
  • 6 其他情况
  • 7 总结

前言

你是否也有过下面的体会?

为什么刚开始学习C语言时很喜欢用for循环语句,但逐渐发现有经验的工程师都在用while和do-while循环(看过内核代码的小伙伴应该也注意到这点了)?

在刚开始写循环语句时总分不清什么时候用for,什么时候用while,什么时候又该使用do-while;刚把这些问题搞清楚了,觉得已经熟练掌握了所有循环语句的使用,但又时不时遇到一个新的问题——总得在循环语句中,甚至是循环语句前和循环语句后添加代码,调整语句顺序,否则最终的逻辑就不正确,甚至是出现指针的解引用错误。

当遇到这些问题时,你是否怀疑过C语言的循环语句是自带缺陷的?下面就让我们一起找出困扰我们编程的幕后黑手吧~~

1 循环语句的三要素

实现一个循环语句的三要素是:

  • A. 判断:判断退出条件是否满足,如果满足则退出循环;如果不满足则循环继续。
  • B. 执行:执行需要循环的内容;内容中一般都会引用循环变量,否则循环就是无差别的。
  • C. 移动:移动循环变量,否则退出条件永远无法满足,循环就演变成了死循环,这也是初学者很容易落的。

根据上述三个要素的执行顺序,可以得到下述6种排列组合。

编号 顺序
1 A -> B -> C
2 A -> C -> B
3 B -> C -> A
4 C -> B -> A
5 B -> A -> C
6 C -> A -> B

你所编写的程序中都逃不出以上这六种排列组合,下面我们对其一一进行剖析。

2 使用不同循环语句实现六种排列组合

2.1 第一种排列(ABC)

这种顺序是我们最最熟悉的,也是最常见的。实现起来并不复杂,也是C语言循环语句最擅长处理的情况。

使用for语句实现

/* 使用for语句实现ABC */
for (; A; C) {
    B;
}

使用while语句实现

/* 使用while语句实现ABC */
while (A) {
    B;
    C;
}

2.2 第二种排列(ACB)

这种顺序我们就不是经常见到了,所以,for语句对它的支持就不是那么友好了,但是while语句没有受到任何影响。

使用for语句实现

/* 使用for语句实现ACB */
for (; A; ;) {
    C;
    B;
}

使用while语句实现

/* 使用while语句实现ACB */
while (A) {
    C;
    B;
}

2.3 第三种排列(BCA)

对于这种排列,for语句彻底没脾气了,while语句也蔫儿了,do-while语句可以大显身手了。

使用for语句实现

/* 使用for语句实现BCA */
for (B, C; A; C;) { /*可读性变得很差,也有很多重复代码*/
    B;
}

使用while语句实现

/* 使用while语句实现BCA */
B; /*已经需要在while语句外额外加重复代码了*/
C;
while (A) {
    B;
    C;
}

使用do-while语句实现

/* 使用do-while语句实现BCA */
do {
    B;
    C;
}while (A); /*do-while就是为此而生啊(看来设计该语句的老前辈已经仔细考虑过该排列了)*/

2.4 第四种排列(CBA)

这种排列跟上一种类似。不过对for语句就更不友好了。

使用for语句实现

/* 使用for语句实现CBA */
for (C, B; A; C,B;) /*这种形式看似一行就处理结束了,但是真实情况是B的内容会很多*/

使用while语句实现

/* 使用while语句实现CBA */
C; /*重复代码*/
B;
while (A) {
    C;
    B;
}

使用do-while语句实现

/* 使用do-while语句实现CBA */
do {
    C;
    B;
}while (A); /*do-while语句默默地说:“这里才是我的战场”。*/

2.5 第五种排列(BAC)

对于这种排列,C语言的循环语句们心里都在想,这是什么鬼地方,没见过啊~~

使用for语句实现

/* 使用for语句实现BAC */
for (B; A; ;) { /*有重复代码*/
    C;
    B;
}

使用while语句实现

/* 使用while语句实现BAC */
B; /*有重复代码*/
while(A) {
    C;
    B;
}

使用do-while语句实现

它说它不在家,让我们去找break。

使用while-break语句实现

/* 使用while-break语句实现 */
while (1) {
 B;
 if (!A)
     break;
 C;
}

2.6 第六种排列(CAB)

这种排列和第五种类似,不使用break仍然无法解决代码重复问题。

使用for语句实现

/* 使用for语句实现CAB */
for (C; A; C) {
    B;
}

使用while语句实现

/* 使用while语句实现CAB */
C;
while (A) {
    B;
    C;
}

使用while-break语句实现

/* 使用while-break语句实现CAB */
while (1) {
    C;
    if (!A)
        break;
    B;
}

3 什么时候用for循环语句

通过上面的实验和摸索,我们发现for语句最适合的场景就是第一种排列(ABC)的场景。在应用与其他场景时要么就退化为while,要么就束手无策了。

这就是for语句的缺陷之所在。

所以,你去看Linux内核或者其他大型项目,其中的for语句都是比较少的,你所见到的基本都长成下面这两种样子。

/* for循环的第一种应用范式 */
#define MAX 100
int i;
for (i = 0; i < MAX; ++i) {
    /* do somthing you like. */
}

我是分割线。。。

/* for循环的第二种应用范式 */
for (;;) {
    /* do somthing you like. */
}

第二种应用范式一般都是用在线程死循环中,当然死循环使用while(1)也可以,只能说是大家都这么用习惯了而已,你可以选择自己喜欢的方式。

4 什么时候用while循环语句

while语句适用于第一种排列(ABC)和第二种排列(ACB)场景。

这种场景的特点是——A在最开始执行。

5 什么时候用do-while循环语句

do-while语句适用于第三种排列(BCA)和第四种排列(CBA)场景。

这种场景的特点是——A在最后执行 。

6 其他情况

其他情况包括第五种排列(BAC)和第六种排列(CAB)场景,以及其他更复杂的场景。

这种场景的特点是——A在中间执行。

这种情景一般就采用whie-break语句来cover了。其实,该语句可以cover住所有场景。

爱刨根问题的同学可能会问,怎么会有这种场景呢?真的有需求么?

那我在此给出一个CABC真实场景的小例子吧,起到抛砖引玉的作用。

/* 重点关注外层循环;关注pstr指针变量 */
while(1){
    pstr = find_cmd(format_str, pstr); /*C[移动]:这一步会移动pstr指针*/
    if (NULL != pstr) /*A[判断]:在使用前需要先判断;看指针是否合法,非法则退出循环*/
    {
        /* B[执行]:执行开始(读取字符串内容并打印)*/
        printf("----------------------------------------------------------------------------\n");
        printf("|| name    \t| %s \n",pstr->name);
        printf("|| brief   \t| %s \n",pstr->brief);
        for (i = 0; i < pstr->argc; i++)
        {
            if (pstr->argv[i])
                printf("|| @ para%d\t| @ %s \n", i, pstr->argv[i]);
        }
        printf("----------------------------------------------------------------------------\n");
  /* B[执行]:执行结束 */

        pstr++; /*C[移动]:这一步还是移动,属于复杂场景,是六种排列的延伸。。。*/
    } else {
        break;
    }
}

7 总结

文章已经很长了,最后不废话,直接上表格。

编号 顺序 合适的循环语句
1 A -> B -> C for/while
2 A -> C -> B while
3 B -> C -> A do-while
4 C -> B -> A do-while
5 B -> A -> C while-break
6 C -> A -> B while-break
x 复合场景 while-break

到此这篇关于C语言进阶教程之循环语句缺陷的文章就介绍到这了,更多相关C语言循环语句缺陷内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中传值与传指针的介绍与区别

    前言 我们可能听过C语言中的传值和传指针,在其他语言中,也有传引用一说,那么他们到底有什么区别呢?如果你还不能准确地分辨,就该好好了解一下了. 传值 我们在初学C语言的时候就被老师教过,下面的方式是无法交换a和b的值的: #include<stdio.h> void swap(int a,int b) { int temp = a; a = b; b = temp; printf("swap a = %d,b = %d\n",a,b); } int main(void) {

  • 关于C语言中参数的传值问题

    1. 考题一:程序代码如下: 复制代码 代码如下: void Exchg1(int x, int y) { int tmp; tmp=x; x=y; y=tmp; printf("x=%d,y=%d/n",x,y) } void main() { int a=4,b=6; Exchg1 (a,b) ; printf("a=%d,b=%d/n",a,b) } 输出的结果: x=____, y=____ a=____, b=____ 问下划线的部分应是什么,请完成. 2

  • 基于C语言利用哈夫曼树实现文件压缩的问题

    一.哈夫曼树 具有n个权值的n个叶子结点,构造出一个二叉树,使得该树的带权路径长度(WPL)最小,则称此二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree). 注意:哈夫曼树是带权路径长度最短的树,且权值越大的叶子结点离根结点越近. 二.哈夫曼编码         哈夫曼编码是一种编码方式,又称"霍夫曼编码",其是可变字长的编码(VCL)的一种,是由霍夫曼于1952年提出的一种编码方式,有时被称为最佳编码,一般称为Huffman编码. 那么我们为什么要使用哈夫曼编码进行压缩?

  • C语言版的三子棋游戏

    本文实例为大家分享了C语言版三子棋游戏的具体代码,供大家参考,具体内容如下 一.游戏说明 三子棋相信大家都不陌生,小时候经常在纸上画出九宫格就可以直接和小伙伴一起玩,规则就是谁先在九宫格中下出同一行三个一样,或者同一列三个一样,又或者对角线的三个一样的棋子,谁就获胜:其实在编程中,代码也能实现人机版的三子棋小游戏,让我们一起来看看如何实现的吧! 二.游戏设计步骤 将三子棋游戏的实现逻辑分为以下步骤: 1.创建菜单(选择玩游戏或者退出游戏) 2.创建和初始化游戏棋盘(本质上为一个二维数组) 3.打

  • C语言:传值与传址交换整数

    目录 传值调用 传址调用 总结 传值调用 要想交换两个整数的值,我们可以自定义一个函数,来实现这个过程.具体代码如下: #include <stdio.h> void Swap1(int x, int y) { int z = 0; z = x; x = y; y = z; } int main() { int a = 10; int b = 20; pirntf("交换前:a=%d b=%d", a, b); Swap1(a, b); pirntf("交换前:a

  • C语言进阶教程之循环语句缺陷详析

    目录 前言 1 循环语句的三要素 2 使用不同循环语句实现六种排列组合 2.1 第一种排列(ABC) 2.2 第二种排列(ACB) 2.3 第三种排列(BCA) 2.4 第四种排列(CBA) 2.5 第五种排列(BAC) 2.6 第六种排列(CAB) 3 什么时候用for循环语句 4 什么时候用while循环语句 5 什么时候用do-while循环语句 6 其他情况 7 总结 前言 你是否也有过下面的体会? 为什么刚开始学习C语言时很喜欢用for循环语句,但逐渐发现有经验的工程师都在用while

  • C语言进阶教程之函数指针详解

    目录 一.函数指针 1.概念 1.2函数指针的使用方法 1.3练习巩固 1.4小结一下 二.阅读两段有趣的代码 1.( *(void( *)( ))0 )( ) 2.void (* signal(int,void( * )( int ) ) )(int) 附:函数指针的应用——函数回调 总结 一.函数指针 1.概念 函数指针:首先它是一个指针,一个指向函数的指针,在内存空间中存放的是函数的地址: 请看示例: int main(){ int a = 10; int*pa = &a; char ch

  • Python趣味入门教程之循环语句while

    前言 任何语言都有循环语句,在Python里循环更是变化无穷,有基本的循环,有循环else语句,引伸出来的还有迭代器.推导式,咱们先学习最简单的一种. While循环  while 条件判断语句: 子代码1 子代码2 子代码3 - 子代码N 主代码1 while语句的格式与if类似,子代码必须进行缩进4个空格,作用却是大不相同.当它执行第一次循环时,判断条件是否成立,如果条件成立,就从子代码1开始执行到子代码N,然后程序会回到while语句再次判断条件是否成立,如果成立就继续从子代码1开始执行,

  • Python基础教程之循环语句(for、while和嵌套循环)

    循环可以用来重复执行某条语句,直到某个条件得到满足或遍历所有元素. 1 for循环 是for循环,可以把集合数据类型list.tuple.dict.set的元素遍历出来. (1)对list进行循环 city_list = ['广州','深圳','东莞','佛山'] city_list = ['广州','深圳','东莞','佛山'] for city in city_list: print("当前地市为:{0}".format(city)) 当前地市为:广州 当前地市为:深圳 当前地市为

  • C语言进阶教程之字符串&内存函数

    目录 前言: 一.求字符串长度 strlen strlen函数的模拟实现 二.长度不受限制的字符串函数 strcpy strcpy函数的模拟实现 strcat strcat函数的模拟实现 strcmp strcmp函数的模拟实现 三.长度受限制的字符串函数 strncpy strncpy函数的模拟实现 strncat strncat函数的模拟实现 strncmp strncmp函数的模拟实现 四.字符串查找 strstr strstr函数的模拟实现 strtok strtok函数的模拟实现 五.

  • C语言进阶教程之字符函数&字符串函数

    目录 1.strlen 1.1.三种模拟实现 2.长度不受限制的字符串函数 2.1.strcpy 2.1.1.模拟实现 2.2.strcat 2.2.1.模拟实现 2.3.strcmp 2.3.1.模拟实现 3.长度受限制的字符串函数 3.1.strncpy 3.1.1.模拟实现 3.2.strncat 3.2.1.模拟实现 3.3.strncmp 3.3.1.模拟实现 4.字符串查找 4.1.strstr 4.1.1.模拟实现 4.2.strtok 5.错误信息报告 5.1.strerror

  • Go语言学习之循环语句使用详解

    目录 1.for循环 2.for-each语法 3.break的使用 4.continue的使用 5.goto的使用 1.for循环 写法基本和其他语言一致,只是没有了while循环,用for代替while. 样例代码如下 // for循环 func loop1() { sum := 0 for i := 0; i < 100; i++ { sum += i } fmt.Printf("sum = %d\n", sum) // 和while循环一样 sum1 := 3 for s

  • C语言实例讲解四大循环语句的使用

    目录 一.do…while()循环 1. 图示流程 2. 代码流程 3. 示例代码1到100求和) 二.while()循环 1. 图示流程 2. 代码流程 3. 示例代码(1到100求和) 三.for()循环 1. 图示流程 2. 代码流程 3. 示例代码(1到100求和) 四.goto循环 1. 代码流程 2. 示例代码-1(1到100求和) 3. 示例代码-2 一.do…while()循环 1. 图示流程 从上面图示 do…while() 语句流程中可以看出,do…while() 语句会先进

  • C语言示例讲解while循环语句的用法

    目录 1.while语句结构 2.代码示例 在学习和回顾该知识前,已经掌握了if语句的结构和用法. if (条件)    语句; 当条件满足的情况下,if结构中的语句执行,且只执行一次:条件不满足则不执行.但是生活中常常需要将一件事情完成很多次,这时候就要用到while语句来实现循环了. 1.while语句结构 while (表达式)    循环语句; 例子:利用循环结构打印1-10 #include <stdio.h> int main() { int i = 0; while(i <

  • Verilog语言的循环语句示例详解

    目录 关键词:while, for, repeat, forever while 循环 for 循环 repeat 循环 forever 循环 关键词:while, for, repeat, forever Verilog 循环语句有 4 种类型,分别是 while,for,repeat,和 forever 循环.循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式. while 循环 while 循环语法格式如下: while (condition) begin -

随机推荐