C控制语句:循环

一,深入while循环

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/3 17:07
    * @description: 根据用户键入的整数求和
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        long num;
        long sum = 0L;
        int status;
    
        printf("Please enter an integer to be summed ");
        printf("(q to quit):\n");
        status = scanf("%ld",&num);
        while (status == 1)
        {
            sum = sum + num;
            printf("Please enter next integer (q to quit):");
            status = scanf("%ld",&num);
        }
        printf("Those integers sum to %ld.\n",sum);
    
        return 0;
    }
    
    
    

1,程序注释

  • status == 1

    • ==运算符是C的相等运算符,该表达式判断status是否等于1
  • scanf()

    • scanf()返回成功读取项的数量。如果scanf()成功读取一个整数,就把该数存入num并返回1,随后返回值将被赋给status。如果用户输入的不是数字,scanf()会读取失败并返回0.此时,status的值就是0,循环结束。
    • 如果scanf()在转换之前出了问题(如:检测到文件结尾或遇到硬件问题),会返回一个特殊值EOF(其值通常被定义为**-1**)。这个值也会引起循环终止。
  • 伪代码

    • 伪代码(pseudocode),是一种用简单的句子表示程序思路的方法,它与计算机语言的形式相对应。伪代码有助于设计程序的逻辑。确定程序的逻辑无误之后,再把伪代码翻译成实际的编程代码:如下伪代码

      • 把sum初始化为0
        提示用户输入数据
        读取用户输入的数据
        当输入的数据为整数时,输入添加给sum,
        提示用户进行输入,
        然后读取下一个输入
        输入完成后,打印sum的值
        
  • 每次循环都被称为一次迭代iteration

2,观察下面程序输出并分析

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/3 19:35
    * @description: 
    ********************************************************************************/
    #include <stdio.h>
    int main(void) {
        int n = 0;
        while (n++ < 3)
            printf("n is %d\n",n);
            printf("That's all this program does.\n");
    
        return 0;
    }
    /***
    * output
    * n is 1
    * n is 2
    * n is 3
    * That's all this program does.
    */
    
  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/3 19:35
    * @description: 
    ********************************************************************************/
    #include <stdio.h>
    int main(void) {
        int n = 0;
        while (n++ < 3);
            printf("n is %d\n",n);
            printf("That's all this program does.\n");
    
        return 0;
    }
    /***
    * output
    * n is 4
    * That's all this program does.
    */
    
  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/3 19:35
    * @description: 
    ********************************************************************************/
    #include <stdio.h>
    int main(void) {
        int n = 0;
        while (n++ < 3)
        {
            printf("n is %d\n", n);
            printf("That's all this program does.\n");
        }
        return 0;
    }
    /***
    * output
    * n is 1
    * That's all this program does.
    * n is 2
    * That's all this program does.
    * n is 3
    * That's all this program does.
    */
    
  • while语句本身使用复合语句,在语句构成上,它也是一条单独的语句。该语句从while开始执行,到第1个分号结束。在使用了复合语句的情况下,到右花括号结束。

二,用关系运算符和表达式比较大小

  • while循环经常依赖测试表达式作比较,这样的表达式被称为关系表达式relational expression),出现在关系表达式中间的运算符叫做关系运算符relational operator)。C语言中的所有关系运算符如下:

    • 运算符含义
      < < <小于
      < = <= <=小于或等于
      = = == ==等于
      > = >= >=大于或等于
      > > >大于
      ! = != !=不等于
  • 虽然关系运算符可用来比较浮点数,但是要注意:比较浮点数时,尽量只使用**<>**。因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。

  • 使用fabs()函数(声明在math.h头文件中)可以方便地比较浮点数,该函数返回一个浮点值的绝对值。

    • /********************************************************************************
      * @author: Mr.Y
      * @date: 2022/2/4 14:53
      * @description: 浮点数大小比较
      ********************************************************************************/
      #include <stdio.h>
      #include <math.h>
      int main(void)
      {
          const double ANSWER = 3.14159;
          double response;
          printf("What is the value of pi?\n");
          scanf("%lf",&response);
          while (fabs(response - ANSWER) > 0.0001)
          {
              printf("Try again!\n");
              scanf("%lf",&response);
          }
          printf("Close enough!\n");
      
          return 0;
      }
      
      /***
       * output
       * What is the value of pi?
       * 1
       * Try again!
       * 2.3
       * Try again!
       * 3.1415
       * Close enough!
       * 
       * /
      

1,什么是真

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/4 15:03
    * @description: 真假的表示
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        int true_val,false_val;
        
        true_val = (10 > 2);		//关系为真的值
        false_val = (10 == 2);		//关系为假的值
        printf("true = %d; false = %d",true_val,false_val);
        
        return 0;
    }
    
    /***
     * output
     * true = 1; false = 0
     * 对于C而言,表达式为真的值是1,表达式为假的值是0。
    */
    
  • 一些C程序使用下面的循环结构,由于1为真,所以循环会一直进行。

    • while(1)
      {
      ......
      }
      
  • 一般而言,所有的非零值都视为真,只有0被视为。只要测试条件的值为非零,就会执行while循环。

2,_Bool类型

  • C99新增了**_Bool类型,表示真或假的变量被称为布尔变量**(Boolean variable)。

  • _Bool类型的变量只能存储1)或0)。如果把其他非零数值赋给布尔类型的变量,该变量会被设置为1

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/4 16:00
    * @description: 使用布尔类型改造上面示例
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        long num;
        long sum = 0L;
        _Bool input_is_good;
    
        printf("Please enter an integer to be summed ");
        printf("(q to quit):");
        input_is_good = (scanf("%ld",&num) == 1);
    
        while (input_is_good)
        {
            sum = sum +num;
            printf("Please enter next integer (q to quit):");
            input_is_good = (scanf("%ld",&num) == 1);
        }
        printf("Those integers sum to %ld.\n", sum);
    
        return 0;
    }
      /***
     * output
     * Please enter an integer to be summed (q to quit):12
     * Please enter next integer (q to quit):23
     * Please enter next integer (q to quit):q
     * Those integers sum to 35.
      */
    
    • C99提供了stdbool.h头文件,该头文件让bool成为**_Bool的别名,而且把truefalse分别定义为10**的符号常量。包含该头文件后,写出的代码可以与C++兼容。
    • 如果系统不支持布尔类型,导致无法运行该程序,可以把布尔替换成int即可。

3,优先级和关系运算符

  • 关系运算符的优先级比算术运算符(包括+和-)低,比赋值运算符高。

  • 关系运算符之间有两种不同的优先级

    • 高优先级组:<<= >>=
    • 低优先级组: == !=
  • 运算符优先级

    • 运算符(优先级从高至低)结合律
      ( )从左往右
      - + ++ – sizeof从右往左
      * / %从左往右
      + -从左往右
      < > <= >=从左往右
      == !=从左往右
      =从右往左

三,不确定循环和计数循环

  • 不确定循环indefinite loop),指在测试表达式为假之前,预先不知道要执行多少次循环。如前面用户输入数字计算示例,不知用户何时结束。
  • 计数循环counting loop),这类循环在执行循环之前就知道要重复执行多少次。

四,for循环

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/4 22:35
    * @description: for循环示例
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const int NUMBER = 22;
        int count;
        for (count = 0; count <= NUMBER ; count++)
            printf("Be my Valentine! count = %d\n",count);
    
    
        return 0;
    }
     /***
      * output
      * Be my Valentine! count = 0
      * Be my Valentine! count = 1
      * Be my Valentine! count = 2
      * ......
      * Be my Valentine! count = 21
      * Be my Valentine! count = 22
      */
    
    • 关键字for后面的括号中有3个表达式,分别用两个分号隔开。
      • 第一个表达式是初始化,只会在for循环开始时执行一次。
      • 第二个表达式是测试条件,在执行循环之前对表达式求值。如果表达式为假,循环结束。
      • 第三个表达式执行更新,在每次循环结束时求值。
    • 完整的for语句还包括后面的简单语句或复合语句。for圆括号中的表达式也叫控制表达式,他们都是完整表达式。

五,逗号运算符

  • 逗号运算符扩展了for循环的灵活性,以便在循环头中包含更多的表达式。

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/5 15:12
    * @description: 逗号运算符
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const int FIRST_OZ = 46;
        const int NEXT_OZ = 20;
        int ounces,cost;
    
        printf("ounces cost\n");
        for (ounces = 1,cost = FIRST_OZ;ounces<=16;ounces++,cost+=NEXT_OZ)
            printf("%5d  $%4.2f\n",ounces,cost / 100.0);
    
        return 0;
    }
        /***
         * output
         * ounces cost
         * 1  $0.46
         * 2  $0.66
         * 3  $0.86
         * 4  $1.06
         * ......
         * 15  $3.26
         * 16  $3.46
         */
    
  • 其次,逗号也可用作分隔符。在下面语句中的逗号都是分隔符,不是逗号运算符。

    • char ch,date;
      printf("%d %d\n",chimps, chumps);
      

六,出口条件循环:do while

  • 出口条件循环exit-condition loop),即在循环的每次迭代之后检查测试条件,保证了至少执行循环体中的内容一次。

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/5 15:54
    * @description: 出口条件循环
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const int secret_code = 13;
        int code_entered;
    
        do
        {
            printf("To enter the triskaidekaphobia therapy club,\n");
            printf("please enter the secret code number: ");
            scanf("%d",&code_entered);
        }while (code_entered!=secret_code);         //当输入的值是13退出。
        printf("Congratulations! You are cured!\n");
    
        return 0;
    }
    

1,do while格式

  • do
    	statement
    while (expression);
    
    • statement可以是一条简单语句或复合语句。
    • do while循环在执行完循环体后才执行测试条件,所以至少执行循环体一次;而forwhile循环都是在执行循环体之前先执行测试条件。do while循环适用于那些至少要迭代一次的循环。

七,如何选择循环

  • 首先确定需要入口条件循环还是出口条件循环。一般而言入口条件循环用得比较多。

  • 当循环涉及初始化和更新变量时,用for循环比较合适,而在其他情况下用while循环更好。例如:

    • while (scanf("%ld", &num) == 1)
      
  • 对于涉及索引计数的循环,用for循环更适合。例如:

    • for (count = 1; count <= 100; count++)
      

八,嵌套循环

  • 嵌套循环nested loop)指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据。

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/5 17:11
    * @description: 
    ********************************************************************************/
    #include <stdio.h>
    #define ROWS 6
    #define CHARS 10
    int main(void)
    {
        int row;
        char ch;
        for (row = 0; row < ROWS; row++) 					//外层循环
        {
            for (ch = 'A'; ch < ('A' + CHARS); ch++) 		//内层循环
                printf("%c", ch);
                printf("\n");
        }
        return 0;
    }
    
        /***
         * OutPut
         * ABCDEFGHIJ
         * ABCDEFGHIJ
         * ABCDEFGHIJ
         * ABCDEFGHIJ
         * ABCDEFGHIJ
         * ABCDEFGHIJ
         */
    
  • 嵌套循环中的内层循环在每次外层循环迭代时都执行完所有的循环。

九,数组

  • 数组可以作为一种存储多个相关项的便利方式。

  • 数组array)是按照顺序存储的一系列类型相同的值,整个数组有一个数组名,通过整数下标访问数组中单独的项或元素element)。如,以下声明:

    • float debts[20];
      //声明debts是一个内含20个元素的数组,每个元素都可以存储float类型的值。数组的第一个元素是debts[0],第二个元素是debts[1],以此类推,直到debts[19]。注意数组的编号是从0开始。
      
  • 考虑到影响执行的速度,C编译器不会检查数组的下标是否正确。下面的代码,都不正确。

    • debts[20] = 88.32;				//该数组元素不存在
      debts[33] = 828.12;				//该数组元素不存在
      
    • 编译器不会查找这样的错误。当运行程序时,这会导致被放置在已被其他数据占用的地方,可能会破坏程序的结果甚至导致程序异常中断。

  • 数组的类型可以是任意数据类型。

  • 如果char类型的数组末尾包含一个表示字符串末尾的空字符**\0**,则该数组中的内容就构成了一个字符串。

    在这里插入图片描述

  • 用于识别数组元素的数字被称为下标subscript),索引index)或偏移量offset)。下标必须是整数,而且要从0开始计数。数组的元素被依次存储在内存中相邻的位置。

    在这里插入图片描述

1,在for循环中使用数组

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/5 19:52
    * @description: 使用循环处理数组
    ********************************************************************************/
    #include <stdio.h>
    #define SIZE 10
    #define PAR 72
    
    int main(void)
    {
        int index,score[SIZE];
        int sum = 0;
        float average;
    
        printf("Enter %d golf scores:\n",SIZE);
        for (index = 0;index<SIZE;index++)
            scanf("%d",&score[index]);
        printf("The scores read in are as follows:\n");
        for (index = 0;index < SIZE;index++)
            printf("%5d",score[index]);
        printf("\n");
        for (index = 0; index < SIZE;index++)
            sum += score[index];
        average = (float) sum / SIZE;
        printf("Sum of scores = %d, average = %.2f\n",sum,average);
        printf("That's a handicap of %.0f\n",average - PAR);
    
        return 0;
    }
        /***
         * output
         * Enter 10 golf scores:
         * 99 95 109 105 100 96 98 93 99 97 98
         * The scores read in are as follows:
         * 99   95  109  105  100   96   98   93   99   97
         * Sum of scores = 991, average = 99.10
         * That's a handicap of 27
         */
    
    • 注意,int类型数组元素的用法与int类型变量的用法类似。要读取int类型变量fue,应该这样写scanf("%d",&fue)。上面程序是因为要读取int类型的元素score[index],所以写成scanf("%d",&score[index])

2,使用函数返回值的循环示例

  • 编写有返回值的函数,要完成以下内容。

    • 定义函数时,确定函数的返回类型。
    • 使用关键字return表明待返回的值。
  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/5 20:48
    * @description: 计算数的整数幂
    ********************************************************************************/
    
    #include <stdio.h>
    double power(double n,int p);       //ANSI函数原型
    
    int main(void)
    {
        double x,xpow;
        int exp;
    
        printf("Enter a number and the positive integer power");
        printf("to which\n the number will be raised. Enter q");
        printf(" to quit.\n");
        while (scanf("%lf%d", &x,&exp) == 2)
        {
            xpow = power(x , exp);          //函数调用
            printf("%.3g to the power %d is %.5g\n",x,exp,xpow);
            printf("Enter next pair of numbers or q to quit.\n");
        }
        printf("Hope you enjoyed this power trip -- bye!\n");
    
        return 0;
    }
    
    double power(double n,int p)            //函数定义
    {
        double pow = 1;
        int i;
        for (i = 1;i <= p; i++)
            pow *= n;
        return pow;                         //返回pow的值
    
    }
         /***
        * Enter a number and the positive integer powerto which
        * the number will be raised. Enter q to quit.
        * 2 2
        * 2 to the power 2 is 4
        * Enter next pair of numbers or q to quit.
        * 3 3
        * 3 to the power 3 is 27
        * Enter next pair of numbers or q to quit.
        * q
        * Hope you enjoyed this power trip -- bye!
         * /
    
  • **power()**函数在程序中出现了3次。首次出现是:

    • double power(double n, int p);				//ANSI函数原型
      
      • 这是power()函数的原型,它声明程序将使用一个名为power()的函数。开头的关键字double表明power()函数返回一个double类型的值。编译器要知道**power()函数返回值的类型,才能知道有多少字节的数据,以及如何解释它们。这就是为什么必须声明函数的原因。圆括号中的double nint p表示power()**函数的两个参数类型。
  • 第二次出现:

    • xpow = power(x,exp);						//函数调用
      
      • 程序调用power(),把两个值传递给它。该函数计算xexp次幂,并把计算结果返回给主调函数。在主调函数中,返回值将被赋给变量xpow
  • 第三次出现:

    • double power(double n, int p)			  //函数定义
      
      • power()有两个形参,一个是double类型,一个是int类型,分别由变量n和变量p表示。
  • 为什么在使用scanf()的返回值之前没有声明scanf()?为什么在定义中说明power()的返回类型为double,还要单独声明这个函数?

    • 编译器在程序中首次遇到power()时,需要知道power()的返回类型。此时,编译器尚未执行到power()的定义,并不知道函数定义中的返回类型是double。因此,必须通过前置声明预先说明函数的返回类型。前置声明告诉编译器,power()定义在别处,其返回类型为double。如果把power()函数的定义置于main()的文件顶部,就可以省略前置声明,因为编译器在执行到main()之前已经知道power()的所有信息。但是,这不是C的标准风格。因为**main()通常只提供整个程序的框架,做好把main()**放在所有函数定义的前面。另外,通常把函数放在其他文件中,所以前置声明必不可少。
    • stdio.h头文件中已经包含了scanf(),printf()和其他I/O函数的原型。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值