• C Primer Plus(6) 中文版 第7章 C控制语句:分支和跳转 7.2 if else 语句


    7.2 if else 语句
    简单形式的if语句让程序选择执行一条语句,或者跳过这条语句。C还提供了if else形式,可以在两条语句之间做选择。我们用if else形式修正程序7.1中的程序段。
    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");
    all_days就两个选择,要么等于0,要么不等于0,因此修改为:
    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");
    注意,if else语句的通用形式是:
    if( expression )
        statement1
    else
        statement2
    如果expression为真(非0),则执行statement1;如果expression为假或0,则执行else后面的statement2。statement1和statement2可以是一条简单语句或符合语句。C并不要求一定要缩进,但这是标准风格。缩进让根据测试条件的求值结果来判断执行哪部分语句
    一目了然。
    如果要在if和else之间执行多条语句,必须用花括号把这些语句括起来成为一个块。 
    7.2.1 另一个示例:介绍getchar()和putchar()
    scanf()和printf()根据%c转换说明读写字符。
    字符输入/输出函数:getchar()和putchar()。
    getchar()函数不带任何参数,它从输入队列中返回下一个字符。
    ch = getchar() 与 scanf( "%c", &ch )效果相同。
    putchar()函数打印它的参数。
    putchar( ch ) 与 printf( "%c", ch )效果相同。
    由于这些函数只处理字符,所以它们比更通用的scanf()和printf()函数更快、更简单。而且,注意getchar()和putchar()不需要转换说明,因为它们只处理字符。这两个函数通常定义在stdio.h头文件中(而且,它们通常是预处理宏,不是真正的函数)。
    下面给程序可描述为“如果打印时空白,原样打印;否则,打印原字符在ASCII序列中的下一个字符”。
    // cypher1.c -- alters input, preserving spaces 
    #include
    #define SPACE ' '             // that's quote-space-quote 
    int main(void)
    {
        char ch;
        
        ch = getchar();           // read a character         
        while (ch != '\n')        // while not end of line    
        {
            if (ch == SPACE)      // leave the space          
                putchar(ch);      // character unchanged      
            else
                putchar(ch + 1);  // change other characters  
            ch = getchar();       // get next character       
        }
        putchar(ch);              // print the newline        
        
        return 0;

    /* 输出:

    */

    把读取和测试合并成一个表达式。也就是说,可以把这种形式的循环: 
    ch = getchar();           // read a character         
    while (ch != '\n')        // while not end of line    
    {
        if (ch == SPACE)      // leave the space          
            putchar(ch);      // character unchanged      
        else
            putchar(ch + 1);  // change other characters  
        ch = getchar();       // get next character       
    }
    替换成下面形式的循环:
    while( (ch = getchar()) != '\n' ){
        ... /*处理字符*/ 

    while( (ch = getchar()) != '\n' )
    这体现了C特有的编程风格---把两个行为合并成一个表达式。
    还要记住合理使用圆括号组合子表达式。上例中的圆括号必不可少,因为赋值运算符的优先级低于关系运算符。
    putchar( ch + 1 ); /*改变其他字符*/
    再次演示了字符实际上是作为整数存储的。为计算方便,表达式ch + 1中的ch被转换成int类型,然后int类型的计算结果被传递给接受一个int类型参数的putchar(),该函数只根据最后一个字节确定显示哪个字符。
    7.2.2 ctype.h系列的字符函数
    斜杠(/)比点号(.)的ASCII码的值多1。
    ctype.h头文件包含了专门处理字符的函数的原型。这些函数接受一个字符作为参数,如果该字符属于某特殊的类别,就返回一个非零值(真);否则,返回0(假)。
    // cypher2.c -- alters input, preserving non-letters
    #include
    #include            // for isalpha()
    int main(void)
    {
        char ch;
        
        while ((ch = getchar()) != '\n')
        {
            if (isalpha(ch))      // if a letter,
                putchar(ch + 1);  // display next letter
            else                  // otherwise,
                putchar(ch);      // display as is
        }
        putchar(ch);              // display the newline
        
        return 0;
    }

    /* 输出:

    */ 

    ctype.h有些函数涉及本地化,指的是为适应特定区域的使用习惯或扩展C基本用法的工具。
    注意,字符映射函数不会修改原始的参数,这些函数只会返回已修改的值。也就是说,下面的语句不改变ch的值:
    tolower( ch ); //不影响ch的值
    这样做才会改变ch的值:
    ch = tolower( ch ); //把chi转换成小写字母
                表7.1 ctype.h头文件中的字符测试函数
    函数名            如果是下列参数时,返回值为真
    isalnum()        字母数字(字母或数字)
    isalpha()         字母
    isblank()         标准的空白字符(空格、水平制表符或换行符)或任何其他本地化指定为空白的字                           符
    iscntrl()           控制字符 如Ctrl + B
    isdigit()           数字
    isgraph()        除空格之外的任意可打印字符
    islower()        小写字母
    isprint()          可打印字符
    ispunct()        标点符号(除空格或字母数字字符意外的任何可打印字符)
    isspace()       空白字符(空格、换行符、换页符、回车符、垂直制表符、水平制表符或其他本地                          化定义的字符)
    isupper()        大写字母
    isxdigit()         十六进制字符
                表7.2 ctype.h头文件中的字符映射函数
    函数名            行为 
    tolower()        如果参数是大写字符,该函数返回小写字母;否则,返回原始参数
    toupper()        如果参数是小写字符,该函数返回大写字符;否则,返回原始参数
    7.2.3 多重选择else if
    在程序中可以用else if扩展if else结构模拟多种选择的情况。
    电费的程序。
    // electric.c -- calculates electric bill 
    #include
    #define RATE1   0.13230       // rate for first 360 kwh      
    #define RATE2   0.15040       // rate for next 108 kwh  
    #define RATE3   0.30025       // rate for next 252 kwh
    #define RATE4   0.34025       // rate for over 720 kwh       
    #define BREAK1  360.0         // first breakpoint for rates  
    #define BREAK2  468.0         // second breakpoint for rates 
    #define BREAK3  720.0         // third breakpoint for rates
    #define BASE1   (RATE1 * BREAK1)
    // cost for 360 kwh            
    #define BASE2  (BASE1 + (RATE2 * (BREAK2 - BREAK1)))
    // cost for 468 kwh
    #define BASE3   (BASE1 + BASE2 + (RATE3 *(BREAK3 - BREAK2)))
    //cost for 720 kwh
    int main(void)
    {
        double kwh;               // kilowatt-hours used         
        double bill;              // charges                     
        
        printf("Please enter the kwh used.\n");
        scanf("%lf", &kwh);       // %lf for type double         
        if (kwh <= BREAK1)
            bill = RATE1 * kwh;
        else if (kwh <= BREAK2)   // kwh between 360 and 468     
            bill = BASE1 + (RATE2 * (kwh - BREAK1));
        else if (kwh <= BREAK3)   // kwh betweent 468 and 720
            bill = BASE2 + (RATE3 * (kwh - BREAK2));
        else                      // kwh above 680               
            bill = BASE3 + (RATE4 * (kwh - BREAK3));
        printf("The charge for %.1f kwh is $%1.2f.\n", kwh, bill);
        
        return 0;

    /* 输出:

    */

    实际上,else if是已学过的if else语句的变式。例如。该程序对的核心部分只不过是下面代码的另一种写法:
    if (kwh <= BREAK1)
            bill = RATE1 * kwh;
    else 
        if (kwh <= BREAK2)   // kwh between 360 and 468     
            bill = BASE1 + (RATE2 * (kwh - BREAK1));
        else 
            if (kwh <= BREAK3)   // kwh betweent 468 and 720
                bill = BASE2 + (RATE3 * (kwh - BREAK2));
            else                      // kwh above 680               
                bill = BASE3 + (RATE4 * (kwh - BREAK3)); 
    整个if else语句被视为一条语句,因此不必把嵌套的if else语句用花括号括起来。当然,花括号可以更清楚地表明这种特殊格式的含义。
    这两种形式完全等价。唯一不同的是使用空格和换行的位置不同,不过编译器会忽略这些。尽管如此,第1种形式还是好些,因为这种形式更清楚地显示了有4种选择。在浏览程序时,这种形式让读者更容易看清楚各项选择。在需要时要缩进嵌套的部分。
    对于编译器的限制范围,C99标准要求编译器至少支持127层套嵌。
    7.2.4 else与if配对
    规则是,如果没有花括号,else与离它最近的if匹配,除非最近的if被花括号括起来。
    记住,编译器是忽略缩进的。
    7.2.5 多层嵌套的if语句
    前面介绍的if...else if...else序列是嵌套if的一种形式,从一系列选项中选择一个执行。有时,选择一个特定选项后又引出其他选择,这种情况可以使用另一种嵌套if。
    验证素数
    在编写代码之前要先规划好。
    不使用平方根而用div * div <= num这样的测试条件,有两个原因。其一,整数乘法比求平方根块。其二,我们还没有正是介绍平方根函数。
    注意
    从技术角度看,if else语句作为一条单独的语句,不必使用花括号。外层if也是一条单独的语句,也不必使用花括号。但是,当语句太长时,使用花括号能提高代码的可读性,而且还可以防止今后在if循环中添加其他语句时忘记加花括号。
    可以在外层循环把一个变量设置为某个值(如,1),然后在if语句中把该变量重新设置为0。循环完成后,检查该变量是否为1,如果是,说明没有进入if语句,那么该数就是素数。这样的变量通常称为标记(flag)。
    一直以来,C都习惯用int作为标记的类型,其实新增的_Bool类型更合适。另外,如果在程序中包含了stdbool.h头文件,便可用bool代替_Bool类型,用true和false分别代替1和0。
    为扩大该程序的应用范围,程序用long类型而不是int类型(如果系统不支持stdbool.h头文件,可以把isPrime的类型改为int,并用1和0分别代替程序中的true和false)。
    // divisors.c -- nested ifs display divisors of a number
    #include
    #include
    int main(void)
    {
        unsigned long num;          // number to be checked
        unsigned long div;          // potential divisors
        bool isPrime;               // prime flag
        
        printf("Please enter an integer for analysis; ");
        printf("Enter q to quit.\n");
        while (scanf("%lu", &num) == 1)
        {
            for (div = 2, isPrime = true; (div * div) <= num; div++)
            {
                if (num % div == 0)
                {
                    if ((div * div) != num)
                        printf("%lu is divisible by %lu and %lu.\n",
                               num, div, num / div);
                    else
                        printf("%lu is divisible by %lu.\n",
                               num, div);
                    isPrime= false; // number is not prime
                }
            }
            if (isPrime)
                printf("%lu is prime.\n", num);
            printf("Please enter another integer for analysis; ");
            printf("Enter q to quit.\n");
        }
        printf("Bye.\n");
        
        return 0;
    }  

    /* 输出:

    */

    该程序会把1认为是素数,其实它不是。
    小结:用if语句进行选择
    形式3:
    if( expression1 )
        statement1
    else if( expression2 ) 
        statement2
    else
        statement3
    如果expression1为真,执行statement1部分;如果expression2为真,执行statement2部分;否则,执行statement3部分。 

  • 相关阅读:
    行列转换:MySQL中的数据变形魔法
    线段树——维护序列(两个懒标记的情况)
    【深度学习】torch.utils.data.DataLoader相关用法 | dataloader数据加载器 | pytorch
    SPRINGBOOT整合CXF发布WEB SERVICE和客户端调用(用户和密码验证)
    使用 Go 和 Wails 构建跨平台桌面应用程序
    Puppeteer 启动 chromium问题
    USB-PD快充和QC快充的区别
    测试环境自动构建
    AV1时域滤波相关代码
    【前后缀 + 推公式整理】 Codeforces Round #813 (Div. 2) D. Empty Graph
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126206810