第七章 C控制语句:分支和跳转

1,if语句

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/9 15:34
    * @description: 统计温度低于0℃的百分比
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const int FREEZING = 0;
        float temperature;          
        int cold_days = 0;          //温度低于0℃的天数
        int all_days = 0;           //总天数
    
        printf("Enter the list of daily low temperatures.\n");
        printf("Use Celsius, and enter q to quit.\n");
        while (scanf("%f",&temperature) == 1)
        {
            all_days++;
            if (temperature < FREEZING)           //判断温度是否低于0℃
            cold_days++;
        }
        if (all_days != 0)
            printf("%d days total: %.1f%% were below freezing.\n",
                    all_days, 100.0 * (float) cold_days / all_days);
        if (all_days == 0)
            printf("No data entered!\n");
    
        return 0;
    }
    /***
     * output
     * Enter the list of daily low temperatures.
     * Use Celsius, and enter q to quit.
     * 12 5 -2.5 0 6 8 -3 -10 5 10 q
     * 10 days total: 30.0% were below freezing.
      */
    
  • if语句被称为分支语句branching statement)或选择语句selection statement)。if语句的通用形式如下:

    • if (expression)
      	statement
      
  • 如果对expression求值为非0),则执行statement;否则,跳过statementstatement可以是一条简单语句复合语句。如下:

    • if (score > big)
      	printf("Jackpot!\n");		//简单语句
      
      if (joe > ron)
        {								//复合语句
        	joecash++;	
        	printf("You lose, Ron.\n");
        }
      
    • 注意:即使if语句由复合语句构成,整个if语句仍被视为一条语句。
  • if语句和while语句的区别:

    • 如果满足条件可执行的话,if语句只能测试和执行一次,而while语句可以测试和执行多次。

2,if else 语句

  • 可以在两条语句之间作选择。

  • if else 格式

    • if (expression)
      	statement1
      else
      	statement2
      
    • 如果expression为真,则执行statement1;如果expression假或0,则执行else后面的statement2statement1statement2可以是一条简单语句复合语句

  • 例如上面的语句可修改为

    •     if (all_days != 0)
              printf("%d days total: %.1f%% were below freezing.\n",
                      all_days, 100.0 * (float) cold_days / all_days);
          else
              printf("No data entered!\n");
      
  • 如果要在ifelse之间执行多条语句,必须用花括号把这些语句括起来成为一个块。如下:

    • if (x > 0)
      {
      	printf("Incrementing x:\n");
      	x++;
      }
      else
      	printf("x <= 0 \n");
      
  • if elseif语句区别

    • if语句用于选择是否执行一个行为,而if else语句用于在两个行为之间选择。

1,getchar()和putchar()

  • 字符输入/输出函数。

  • getchar()函数不带任何参数,它从输入队列中返回下一个字符。如下面的语句读取下一个字符输入,并把该字符的值赋给变量ch:

    • ch = getchar();
      //该语句与下面的语句效果相同
      scanf("%c",&ch);
      
  • putchar()函数打印它的参数。如下面的语句把之前赋给ch的值作为字符打印出来。

    • putchar(ch);
      //该语句与下面的语句效果相同
      printf("%c",ch);
      
  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/9 17:09
    * @description: 更改输入,空格不变用户输入的字符后移一位,如输入abc,输出bcd。
    ********************************************************************************/
    #include <stdio.h>
    #define SPACE ' '                       //SPACE表示单引号-空格-单引号
    int main(void)
    {
        char ch;
    
        ch = getchar();                     //读取一个字符
        while (ch != '\n')                  //当一行未结束时
        {
            if (ch == SPACE)                //留下空格
                putchar(ch);                //该字符不变
            else
                putchar(ch + 1);        //改变其他字符
            ch = getchar();                 //获取下一个字符
        }
        putchar(ch);                        //打印换行符
    
        return 0;
    }
    /***
     * output
     * abcd.
     * bcde/
     */
    
    
    • 上面程序中最后输入的点号(.)被转换成斜杠(/),这是因为斜杠字符对应的ASCII码比点号ASCII码多1。如何让程序只转换字母,保留所有的非字母字符(不只是空格)?解决方案ctype.h

2,ctype.h系列字符函数

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/9 18:04
    * @description: 替换输入的字母,非字母字符保持不变
    ********************************************************************************/
    #include <stdio.h>
    #include <ctype.h>          
    int main(void)
    {
        char ch;
        
        while ((ch = getchar()) != '\n')
        {
            if (isalpha(ch))            //如果是一个字符,isalpha()是ctype.h内的函数
                putchar(ch + 1);    //显示该字符的下一个字符
            else
                putchar(ch);            //原样显示
        }
        putchar(ch);                    //显示换行符
        return 0;
    }
    /***
     * output
     * 注意大小写
     * AbCd.
     * BcDe.
     */
    
  • ctype.h头文件中的字符测试函数

函数名如果是下列函数时,返回值为真
isalnum()字母数字(字母或数字)
isalpha()字母
isblank()标准的空白字符(空格,水平制表符或换行符)或任何其他本地化指定为空白的字符
iscntrl()控制字符,如Ctrl+B
isdigit()数字
isgraph()除空格外的任意可打印字符
islower()小写字母
isprint()可打印字符
ispunct()标点符号(除空格或字母数字字符以外的任何可打印字符)
isspace()空白字符(空格,换行符,换页符,回车符,垂直制表符,水平制表符或其他本地化定义的字符)
isupper()大写字母
isxdigit()十六进制数字符
  • ctype.h头文件中的字符映射函数
函数名行为
tolower()如果参数是大写字符,该函数返回小写字符;否则,返回原始参数
toupper()如果参数是小写字符,该函数返回大写字符;否则,返回原始参数

3,多重选择else if

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/13 16:45
    * @description: 计算阶梯电费
    ********************************************************************************/
    #include <stdio.h>
    #define RATE1 0.13230                                           //首次使用360kwh的费率
    #define RATE2 0.15040                                           //接着使用108kwh的费率
    #define RATE3 0.30025                                           //接着再使用252kwh的费率
    #define RATE4 0.34025                                           //使用超过720kwh的费率
    #define BREAK1 360.0                                            //费率的第一个分界点
    #define BREAK2 468.0                                            //费率的第二个分界点
    #define BREAK3 720.0                                            //费率的第三个分界点
    #define BASE1 (RATE1 * BREAK1)                                  //使用360kwh的费用
    #define BASE2 (BASE1 + (RATE2 * (BREAK2 - BREAK1)))             //使用468kwh的费用
    #define BASE3 (BASE2 + (RATE3 * (BREAK3 - BREAK2)))             //使用720kwh的费用
    int main(void)
    {
        double kwh;                                                 //使用的千瓦时
        double bill;                                                //电费
    
        printf("Please enter the kwh used.\n");
        scanf("%lf",&kwh);                                  //%lf对应的double类型
        if (kwh <= BREAK1)  
            bill = RATE1 * kwh;
        else if (kwh <= BREAK2)                                     //360~468kwh
            bill = BASE1 + (RATE2 * (kwh - BREAK1));
        else if (kwh <= BREAK3)                                     //468~720千瓦时
            bill = BASE2 + (RATE3 * (kwh - BREAK2));
        else                                                        //超过720kwh
            bill = BASE3 + (RATE4 * (kwh - BREAK3));
        printf("The charge for %.1f kwh is $%1.2f.\n",kwh,bill);
    
        return 0;
    }
    /***
     * output
     * Please enter the kwh used.
     * 580
     * The charge for 580.0 kwh is $97.50.
     */
    
    
  • 可以把多个else if语句连成一串使用。如下所示:

    • if (soure < 10000)
      	bouns = 0;
      else if (soure < 1500)
      	bouns = 1;
      else if (soure < 2000)
      	bouns = 2;
      else if (soure < 2500)
      	bouns = 4;
      else
      	bouns = 6;
      	
      //对于编译器的限制范围,C99标准要求编译器最少支持127层套嵌。
      

4,else与if配对

  • 如果程序中有多个ifelse,编译器如何判断那个if对应那个else?如下:

    • if (number > 6)
      	if (number < 12)
      		printf("You're close!\n");
      else
      	printf("Sorry, you lose a turn!\n");
      
    • 规则是,如果没有花括号,else与离它最近的if匹配,除非最近的if被花括号括起来。

3,逻辑运算符

1,3种逻辑运算符

  • 逻辑运算符含义
    &&
    ||
  • 假设exp1exp2是两个简单的关系表达式,那么:

    • 当且仅当exp1exp2都为真时,exp1 && exp2才为真。
    • 如果exp1exp2为真,则exp1 || exp2为真。
    • 如果exp1为假,则**!exp1为真;如果exp1为真,则!exp1**为假。
  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/14 20:49
    * @description: 统计输入的字符数,包含空格
    ********************************************************************************/
    #include <stdio.h>
    #define PERIOD '.'
    
    int main(void)
    {
        char ch;
        int charcount = 0;
    
        while ((ch = getchar()) != PERIOD)
        {
            if (ch != '"' && ch != '\'')        //使用&&判断是否满足两个条件
                charcount++;
        }
        printf("There ard %d non-quote characters.\n",charcount);
    
        return 0;
    }
    /***
     * output
     * 123456.
     * There ard 6 non-quote characters.
     */
    
    
  • 逻辑运算符的优先级比关系运算符低。

2,iso646.h头文件

  • C99标准新增了可代替逻辑运算符的拼写,它们被定义在iso646.h头文件中。如果在程序中包含该头文件,便可使用and代替**&&or代替||not代替!**。使用此方法上述程序可改为。

    • /********************************************************************************
      * @author: Mr.Y
      * @date: 2022/2/14 20:49
      * @description: 统计输入的字符数,包含空格
      ********************************************************************************/
      #include <stdio.h>
      #include <iso646.h>
      #define PERIOD '.'
      
      int main(void)
      {
          char ch;
          int charcount = 0;
      
          while ((ch = getchar()) != PERIOD)
          {
              if (ch != '"' and ch != '\'')        //使用&&判断是否满足两个条件
                  charcount++;
          }
          printf("There ard %d non-quote characters.\n",charcount);
      
          return 0;
      }
      /***
       * output
       * 123456789.
       * There ard 9 non-quote characters.
       */
      
  • 逻辑运算符的备选拼写

    传统写法iso646.h
    &&and
    ||or
    !not

3,优先级

  • **!运算符的优先级很高,比乘法运算符还高,与递增运算符的优先级相同,只比圆括号的优先级低。&&运算符的优先级比||**运算符高,但是两者的优先级都比关系运算符低,比赋值运算符高。

4,求值顺序

  • 逻辑表达式的求值顺序是从左往右。一旦发现有使整个表达式为假的因素,立即停止求值。如下:

    • x != 0 && (20/x) < 5
      //只有当x不等于0时,才会对第2个表达式求值。
      

5,范围

  • &&运算符可用于测试范围。如,要测试score是否在90~100的范围内,可以这样写:

    • if (range >= 90 && range <= 100)
      
  • 不要模仿数学上的写法:

    • if (90 <= tange <= 100)
      
    • 这样写的问题是代码有语义错误,而不是语法错误,由于<=运算符的求值顺序是从左往右,所以编译器把测试表达式解释为:(90 <= range) <= 100。子表达式90 <= range的值要么是1(为真),要么是0(为假)。这两个值都小于100,所以不管range的值是多少,整个表达式都恒为真。

4,条件运算符:?:

  • C提供条件表达式作为表达if else语句的一种便捷方式,该表达式使用**?:条件运算符。该运算符分为两部分,需要3个运算对象,称为三元运算符**,条件运算符是C语言中唯一的三元运算符。下面的代码得到一个数的绝对值:

    • x = (y < 0) ? -y : y;
      
    • = 和 ; 之间的内容就是条件表达式,该语句的意思是”如果y小于0,那么x = -y;否则,x = y“。用if else可以这样表达:

      • if ( y < 0)
        	x = -y;
        else
        	x = y;
        

5,循环辅助:continue和break

  • 程序进入循环后,在下一次循环测试之前会执行完循环体中的所有语句。continuebreak语句可以根据循环体中的测试结果来忽略一部分循环内容,甚至结束循环。

1,continue语句

  • 执行到该语句时,会跳过本次迭代的剩余部分,并开始下一轮迭代。如果continue语句在嵌套循环内,则只会影响包含该语句的内层循环。

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/19 17:46
    * @description: 使用continue跳过部分循环
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const float MIN = 0.0f;
        const float MAX = 100.0f;
    
        float score;
        float total = 0.0f;
        int n = 0;
        float min = MAX;
        float max = MAX;
        
        printf("Enter the first score (q to quit): ");
        while (scanf("%f",&score) == 1)
        {
            if (score < MIN || score > MAX)
            {
                printf("%0.1f is an invalid value. Try again: ",score);
                continue;   //跳转至while循环的测试条件
            }
            printf("Accepting %0.1f:\n",score);
            min = (score < min) ? score:min;
            max = (score > max) ? score:max;
            total += score;
            n++;
            printf("Enter next score (q to quit): ");
        }
        if (n > 0)
        {
            printf("Average of %d scores is %0.1f.\n",n,total / n);
            printf("Low = %0.1f,high = 0.1f\n",min,max);
        } else
            printf("No valid scores were entered.\n");
        return 0;
        
    }
    /***
     * output
     * Enter the first score (q to quit):55
     * Accepting 55.0:
     * Enter next score (q to quit):0.1
     * Accepting 0.1:
     * Enter next score (q to quit):-1
     * -1.0 is an invalid value. Try again:10
     * Accepting 10.0:
     * Enter next score (q to quit):q
     * Average of 3 scores is 21.7.
     * Low = 0.1,high = 0.1f
     */
    
  • 有两种方法可以避免使用continue,一是省略continue,把剩余部分放在一个else块中:

    • if (score < 0 || score > 100)
      /*printf()语句*/
      else
      {
          /*语句*/
      }
      
    • if (score >= 0 && score <= 100)
      {
          /*语句*/
      }
      

2,break语句

  • 程序执行到循环中的break语句时,会终止包含它的循环,并继续执行下一阶段。如果break语句位于嵌套循环内,它只会影响包含它的当前循环。

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/20 16:19
    * @description: 使用break跳过循环
    ********************************************************************************/
    #include <stdio.h>
    int main(void)
    {
        const float MIN = 0.0f;
        const float MAX = 100.0f;
    
        float score;
        float total = 0.0f;
        int n = 0;
        float min = MAX;
        float max = MAX;
    
        printf("Enter the first score (q to quit): ");
        while (scanf("%f",&score) == 1)
        {
            if (score < MIN || score > MAX)
            {
                printf("%0.1f is an invalid value. Try again: ",score);
                break;
            }
            printf("Accepting %0.1f:\n",score);
            min = (score < min) ? score:min;
            max = (score > max) ? score:max;
            total += score;
            n++;
            printf("Enter next score (q to quit): ");
        }
        if (n > 0)
        {
            printf("Average of %d scores is %0.1f.\n",n,total / n);
            printf("Low = %0.1f,high = 0.1f\n",min,max);
        } else
            printf("No valid scores were entered.\n");
        return 0;
    
    }
    /***
     * output
     * Enter the first score (q to quit):12
     * Accepting 12.0:
     * Enter next score (q to quit):14
     * Accepting 14.0:
     * Enter next score (q to quit):a
     * Average of 2 scores is 13.0.
     * Low = 12.0,high = 0.1f
     */
    
    
    
  • for循环中的breakcontinue的情况不同,执行完break语句后会直接执行循环后面的第一条语句,连更新部分也跳过。嵌套循环内层的break只会让程序跳出包含它的当前循环,要跳出外层循环还需要一个break

    • int p,q;
      scanf("%d",&p);
      while (p > 0)
      {
      	printf("%d\n",p);
          scanf("%d",&q);
          while (q > 0)
          {
              printf("%d\n",P*q);
              if(q > 100)
                  break;						//跳出内层循环
              scanf("%d",&q);
          }
          if(q > 100)
              break;							//跳出外层循环
          scanf("%d",&p);
      }
      

6,多重选择:switch和break

  • /********************************************************************************
    * @author: Mr.Y
    * @date: 2022/2/20 16:56
    * @description: 使用switch语句
    ********************************************************************************/
    #include <stdio.h>
    #include <ctype.h>
    
    int main(void) {
        char ch;
    
        printf("Give me a letter of the alphabet, and I will give");
        printf("an animal name\nbeginning with that letter.\n");
        printf("Please type in a letter; type # to end my act.\n");
        while ((ch = getchar()) != '#') {
            if ('\n' == ch)
                continue;
            if (islower(ch))
                switch (ch) {
                    case 'a':
                        printf("argali, a wild sheep of Asia\n");
                        break;
                    case 'b':
                        printf("babirusa, a wild pig of Malay\n");
                        break;
                    case 'c':
                        printf("coati, racoonlike mammal\n");
                        break;
                    case 'd':
                        printf("desman, aquatic, molelike critter\n");
                        break;
                    case 'e':
                        printf("echidna, the spiny anteater\n");
                        break;
                    case 'f':
                        printf("fisher, brownish marten\n");
                        break;
                    default:
                        printf("That's a stumper!\n");
                }
            else
                printf("I recognize only lowercase letters.\n");
            while (getchar() != '\n')
                continue;
            printf("Please type another letter or a #.\n");
        }
        printf("Bye!\n");
        return 0;
    }
    
    /***
     * output
     * Give me a letter of the alphabet, and I will givean animal name
     * beginning with that letter.
     * Please type in a letter; type # to end my act.
     * a
     * argali, a wild sheep of Asia
     * Please type another letter or a #.
     * b
     * babirusa, a wild pig of Malay
     * Please type another letter or a #.
     * c
     * coati, racoonlike mammal
     * Please type another letter or a #.
     * d
     * desman, aquatic, molelike critter
     * Please type another letter or a #.
     * e
     * echidna, the spiny anteater
     * Please type another letter or a #.
     * f
     * fisher, brownish marten
     * Please type another letter or a #.
     * g
     * That's a stumper!
     * Please type another letter or a #.
     * 1
     * I recognize only lowercase letters.
     * Please type another letter or a #.
     * q
     * That's a stumper!
     * Please type another letter or a #.
     * #
     * Bye!
     */
    
  • break语句可用于循环和switch语句,但是continue只能用于循环中。

  • switch语句构造

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

7,goto语句

  • 早期版本的BASICFORTRAN所依赖的goto语句,在C中仍然可用。没有goto语句C程序也能运行良好。C中建议”谨慎使用,或者根本不用“。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值