条件运算符:?:
条件运算符。 该运算符分为两部分, 需要 3 个运算对象。 带一个运算对象的运算符称为一元运算符, 带两个运算对象的运算符称为二元运算符。 以此类推, 带 3 个运算对象的运算符称为三元运算符。 条件运算符是C语言中唯一的三元运算符。
x = (y < 0) ? -y : y;
在=和;之间的内容就是条件表达式, 该语句的意思是“如果y小于0, 那么x = -y;否则, x = y”。 用if else可以这样表达:
if (y < 0)
x = -y;
else
x = y;
条件表达式的通用形式如下:
expression1 ? expression2 : expression3
如果 expression1 为真(非 0) , 那么整个条件表达式的值与 expression2的值相同; 如果expression1为假(0) , 那么整个条件表达式的值与expression3的值相同。
需要把两个值中的一个赋给变量时, 就可以用条件表达式。
max = (a > b) ? a : b;
如果a大于b, 那么将max设置为a; 否则, 设置为b。
该程序使用的变量都是int类型, 除法的计算结果(sq_feet /COVERAGE) 会被截断。
小结: 条件运算符
条件运算符: ?:
一般注解:
条件运算符需要3个运算对象, 每个运算对象都是一个表达式。
循环辅助: continue和break
程序进入循环后, 在下一次循环测试之前会执行完循环体中的所有语句。 continue 和break语句可以根据循环体中的测试结果来忽略一部分循环内容, 甚至结束循环。
continue语句
3种循环都可以使用continue语句。 执行到该语句时, 会跳过本次迭代的剩余部分, 并开始下一轮迭代。 如果continue语句在嵌套循环内, 则只会影响包含该语句的内层循环。
while循环读取输入, 直至用户输入非数值数据。 循环中的if语句筛选出无效的分数。
有两种方法可以避免使用continue, 一是省略continue, 把剩余部分放在一个else块中:
if (score < 0 || score > 100)
/* printf()语句 */
else
{
/*语句*/
}
另一种方法是, 用以下格式来代替:
if (score >= 0 && score <= 100)
{
/*语句 */
}
使用continue的好处是减少主语句组中的一级缩进。 当语句很长或嵌套较多时, 紧凑简洁的格式提高了代码的可读性。
continue还可用作占位符。 循环读取并丢弃输入的数据,直至读到行末尾:while (getchar() != '\n');
对于while和 do while 循环, 执行 continue 语句后的下一个行为是对循环的测试表达式求值。
count = 0;
while (count < 10)
{
ch = getchar();
if (ch == '\n')
continue;
putchar(ch);
count++;
}
该循环读取10个字符(除换行符外, 因为当ch是换行符时, 程序会跳过count++;语句) 并重新显示它们, 其中不包括换行符。 执行continue后, 下一个被求值的表达式是循环测试条件
对于for循环, 执行continue后的下一个行为是对更新表达式求值, 然后是对循环测试表达式求值。
break语句
程序执行到循环中的break语句时, 会终止包含它的循环, 并继续执行下一阶段。break和continue。如果break语句位于嵌套循环内, 它只会影响包含它的当前循环。
break还可用于因其他原因退出循环的情况。
在for循环中的break和continue的情况不同, 执行完break语句后会直接执行循环后面的第1条语句, 连更新部分也跳过。 嵌套循环内层的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);
}
多重选择:switch和break
switch语句
要对紧跟在关键字 switch 后圆括号中的表达式求值。表达式是刚输入给 ch的值。 然后程序扫描标签(这里指, case 'a' :、case 'b' :等) 列表, 直到发现一个匹配的值为止。 然后程序跳转至那一行。如果有default :标签行, 就跳转至该行; 否则, 程序继续执行在switch后面的语句。
break语句让程序离开switch语句, 跳至switch语句后面的下一条语句如果没有break语句, 就会从匹配标签开始执行到switch末尾。
break语句可用于循环和switch语句中, 但是continue只能用于循环中。 尽管如此, 如果switch语句在一个循环中, continue便可作为switch语句的一部分。 这种情况下, 就像在其他循环中一样, continue让程序跳出循环的剩余部分, 包括switch语句的其他部分。C语言的case一般都指定一个值, 不能使用一个范围。
switch在圆括号中的测试表达式的值应该是一个整数值(包括char类型) 。 case标签必须是整数类型(包括char类型) 的常量或整型常量表达式(即, 表达式中只包含整型常量) 。 不能用变量作为case标签。
只读每行的首字符
animals.c的另一个独特之处是它读取输入的方式。当输入dab时, 只处理了第1个字符。 这种丢弃一行中其他字符的行为, 经常出现在响应单字符的交互程序中。
while (getchar() != '\n')
continue; /* 跳过输入行的其余部分 */
循环从输入中读取字符, 包括按下Enter键产生的换行符。 注意, 函数的返回值并没有赋给ch, 以上代码所做的只是读取并丢弃字符。 由于最后丢弃的字符是换行符, 所以下一个被读取的字符是下一行的首字母。 在外层的while循环中, getchar()读取首字母并赋给ch。
多重标签
如果ch是字母i, switch语句会定位到标签为case 'i' :的位置。 由于该标签没有关联break语句, 所以程序流直接执行下一条语句, 即i_ct++;。如果 ch是字母I, 程序流会直接定位到case 'I' :。 本质上, 两个标签都指的是相同的语句。
严格地说, case 'U'的 break 语句并不需要。 因为即使删除这条 break 语句, 程序流会接着执行switch中的下一条语句, 即default : break;。 所以, 可以把case 'U'的break语句去掉以缩短代码。 但是从另一方面看, 保留这条break语句可以防止以后在添加新的case(例如, 把y作为元音) 时遗漏break语句
如果使用ctype.h系列的toupper()函数可以避免使用多重标签, 在进行测试之前就把字母转换成大写字母
小结: 带多重选择的switch语句
关键字: switch
程序根据expression的值跳转至相应的case标签处。 然后, 执行剩下的所
有语句, 除非执行到break语句进行重定向。 expression和case标签都必须是整数值(包括char类型) , 标签必须是常量或完全由常量组成的表达式。 如果没有case标签与expression的值匹配, 控制则转至标有default的语句(如果有的话) ; 否则, 将转至执行紧跟在switch语句后面的语句。
switch和if else
何时使用switch? 何时使用if else?如果是根据浮点类型的变量或表达式来选择, 就无法使用 switch。 如果根据变量在某范围内决定程序流的去向, 使用 switch 就很麻烦, 这种情况用if就很方便:
if (integer < 1000 && integer > 2)
使用switch要涵盖以上范围, 需要为每个整数(3~999) 设置case标签。 但是, 如果使用switch, 程序通常运行快一些, 生成的代码少一些。
goto语句
goto语句有两部分: goto和标签名。 标签的命名遵循变量命名规则,
goto part2;
要让这条语句正常工作, 函数还必须包含另一条标为part2的语句, 该语句以标签名后紧跟一个冒号开始:
part2: printf("Refined analysis:\n");
避免使用goto
goto的常见情况
处理包含多条语句的if语句:
if (size > 12)
goto a;
goto b;
a: cost = cost * 1.05;
flag = 2;
b: bill = cost * flag;
转换成等价的C代码, 标准C用复合语句或块来处理这种情况
if (size > 12)
{
cost = cost * 1.05;
flag = 2;
}
bill = cost * flag;
C通过if else表达二选一更清楚:
if (ibex > 14)
sheds = 3;
else
sheds = 2;
help = 2 * sheds;
创建不确定循环:
readin: scanf("%d", &score);
if (score < O)
goto stage2;
lots of statements
goto readin;
stage2: more stuff;
C用while循环代替:
scanf("%d", &score);
while (score <= 0)
{
lots of statements
scanf("%d", &score);
}
more stuff;
跳转至循环末尾, 并开始下一轮迭代。 C使用continue语句代替。
跳出循环。 C使用break语句。 实际上, break和continue是goto的特殊形式。 使用break和 continue 的好处是: 其名称已经表明它们的用法, 而且这些语句不使用标签, 所以不用担心把标签放错位置导致的危险。
小结: 程序跳转
关键字: break、 continue、 goto
这3种语句都能使程序流从程序的一处跳转至另一处。
break语句:
所有的循环和switch语句都可以使用break语句。 它使程序控制跳出当前循环或switch语句的剩余部分, 并继续执行跟在循环或switch后面的语句。
switch (number)
{
case 4: printf("That's a good choice.\n");
break;
case 5: printf("That's a fair choice.\n");
break;
default: printf("That's a poor choice.\n");
}
continue语句:
所有的循环都可以使用continue语句, 但是switch语句不行。 continue语句使程序控制跳出循环的剩余部分。 对于while或for循环, 程序执行到continue语句后会开始进入下一轮迭代。 对于do while循环, 对出口条件求值后, 如有必要会进入下一轮迭代。
goto语句:
goto语句使程序控制跳转至相应标签语句。 冒号用于分隔标签和标签语句。 标签名遵循变量命名规则。 标签语句可以出现在goto的前面或后面。
关键概念
C语言通过if、 if else和switch语句, 以及条件运算符(?:) 可以实现智能选择。
if 和 if else 语句使用测试条件来判断执行哪些语句。 所有非零值都被视为 true, 零被视为false。 测试通常涉及关系表达式(比较两个值) 、 逻辑表达式(用逻辑运算符组合或更改其他表达式) 。
如果要测试两个条件, 应该使用逻辑运算符把两个完整的测试表达式组合起来。
本章小结
if语句使用测试条件控制程序是否执行测试条件后面的一条简单语句或复合语句。 如果测试表达式的值是非零值, 则执行语句; 如果测试表达式的值是零, 则不执行语句。 if else语句可用于二选一的情况。 如果测试条件是非零, 则执行else前面的语句; 如果测试表达式的值是零, 则执行else后面的语句。 在else后面使用另一个if语句形成else if, 可构造多选一的结构。
测试条件通常都是关系表达式, 即用一个关系运算符(如, <或==) 的表达式。 使用C的逻辑运算符, 可以把关系表达式组合成更复杂的测试条件
在多数情况下, 用条件运算符(?:) 写成的表达式比if else语句更简洁。
ctype.h系列的字符函数(如, issapce()和isalpha()) 为创建以分类字符为基础的测试表达式提供了便捷的工具。switch 语句可以在一系列以整数作为标签的语句中进行选择。 如果紧跟在 switch 关键字后的测试条件的整数值与某标签匹配, 程序就转至执行匹配的标签语句, 然后在遇到break之前, 继续执行标签语句后面的语句
break、 continue和goto语句都是跳转语句, 使程序流跳转至程序的另一处。 break语句使程序跳转至紧跟在包含break语句的循环或switch末尾的下一条语句。 continue语句使程序跳出当前循环的剩余部分, 并开始下一轮迭代。