if else 语句的通用形式为:git
if (expression)express
statement1编程
else函数
statement2性能
若是expression为真(非零),就执行statement1;若是expression为假或零,则执行跟在else后的那一条语句(statement2)。测试
若是但愿在if和else之间有多条语句,必须使用花括号建立一个代码块。ui
if语句使您可以选择是否执行某个动做。if else语句使您能够在两个动做之间进行选择。spa
7.2.1 另外一个例子:介绍getchar()和putchar()设计
如今咱们将接触专门 为面向字符I/O而设计的一对C函数:getchar()和putchar()。code
getchar()函数没有参数,它返回来自输入设备的下一个字符。
ch=getchar();与scanf("%c",&ch);有一样的效果。
putchar()函数打印它的参数。例如,下面的语句将先前赋值给ch的值做为字符打印出来:
putchar(ch);
该语句与printf("%c",ch);有一样的效果。
由于这些函数仅仅处理字符,因此它们比更通用的scanf()和printf()函数更快并且更简洁。一样,注意到它们不须要格式说明符,由于它们只对字符 起做用。
这两个函数一般都是在stdio.h文件中定义的。
下面的示例将说明这些函数是如何工做的,“若是字符 是空格,打印之;不然,打印它们在ASCII序列中的下一个字符”。
程序清单7.2 cypher1.c 程序
/*cypher1.c --改变输入,只保留其中的空格*/ #include #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; } /*下面是一个运行示例: CALL ME HAL. DBMM NF IBM/ */
C灵活的语法使您能够经过将读取和判断合并为单个表达来仿效程序清单7.1。就是说,您能够把这种形式的循环:
ch=getchar();
while(ch!='\n')
{
...
ch=getchar();
}
替换为下面的形式:
while((ch=getchar())!='\n')
{
....
}
关键的一行是while( (ch=getchar()) != '\n' )
这体现了c的编程风格:将两个动做合并为一个表达式。
圆括号是必须的,由于!=的优先级要比=的高。
putchar(ch+1)再次证实了字符其实是做为整数存储的。
7.2.2 ctype.h系列字符函数
ctype.h头文件包含了一些能够用来分析字符的函数的原型。这些函数接受一个字符做为参数,若是该字符 属于某特定的种类则返回非零值(真),不然返回零(假)。
例如,若是isalpha()函数的参数是一个字母,则它返回一个非零值。程序清单7.3经过使用该函数扩展了程序清单7.2。
程序清单7.3 cypher2.c
#include #include int main (void) { char ch; while((ch=getchar())!='\n') { if(isalpha(ch)) //若是是一个字母 putchar(ch+1); //则改变它 else //不然 putchar(ch); //原样打印它 } putchar(ch); //打印换行符 return 0; }
表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
平常生活中,常常会给咱们提供两个以上的选择。
程序清单7.4 electric.c
/*electric.c --计算用电账目*/ #include #define RATE1 0.12589 /*第1 个360KWH的费率*/ #define RATE2 0.17901 /*下一个320KWH的费率*/ #define RATE3 0.20971 /*超过680KWH的费率*/ #define BREAK1 360.0 /*费率的第一个分界点*/ #define BREAK2 680.0 /*费率的第二个分界点*/ #define BASE1 (RATE1*BREAK1) /*用电360KWH的费用*/ #define BASE2 (BASE1+(RATE2*(BREAK2-BREAK1))) /*用电680KWH的费用*/ 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-680kwh之间*/ bill = BASE1 + (RATE2 * (kwh-BREAK1)); else /*用电超出680kwh时*/ bill = BASE2 + (RATE3 * (kwh-BREAK2)); printf("The charge for %.1f kwh is $1.2f.\n",kwh,bill); return 0; }
程序清单7.4用符号常量表示费率,以便这些常量能够很方便的被放置在一块儿。该清单也用 符号表示了费率的分界点。BASE1和BASE2根据费率和分界点来表示。这样,若是费率或分界点改变了,它们也会自动的更新。您可能回想起预处理器是不作计算的,程序中BASE1出现的地方将使用0.12589*360.0代替。不用担忧,编译器会求得该表达式的数值(45.3204)以便最终的程序代码使用45.3204而不是一个计算表达式。
程序的流程简单明了。应该特别注意的是仅当KWH大于360时程序才到达第一个else。因此,像程序注释的那样,else if 行实际上至关于要求kwh在360和680之间。一样仅当kwh超过680才能到达最后一个else。
说到编译器的嵌套限制,C99标准要求编译器最少支持127层嵌套。
7.2.4 把else 与 if 配对
当有众多的if和else的时候 ,计算机是怎样判断哪一个if对应哪一个else的?
规则是若是没有花括号指明,else与和它最接近的一个if相匹配。
7.2.5 多层嵌套的if
前面所看到的if...else if...else序列是嵌套if的一种形式,这是从一系列的二选一中进行选择的。当进行了特定的选择后又致使了额外的选择时将使用另外一种嵌套if。
咱们试着用这种形式的嵌套if来解决下面的问题:给定一个整数,显示全部能整除它的约数;若是没有约数,则报告该数是个素数。
首先,对程序进行总体设计,为了方便,程序须要用一个循环来使您能输入被测试的数。
下一步,须要 计划怎么来找到除数。或许最显而易见的方法是这样的:
for(dir=2;div
if(num%div==0)
printf("%d is divisible by %d\n",num,div);
该循环检查界于2到num之间的全部数,看它们是否能够整除num。不幸的是这样浪费了计算机的时间。咱们能够作的更好。例如,考虑搜索144的约数。能够发现144%2为0,这意味着144能被2整除。若是明确的拿144除以2,能够获得72,这也是一个约数,所以一次成功的num%div测试能够获得两个约数而不是一个。然而,真正的性能指标在于循环测试界限的改变。
为了弄清这是怎么工做的,看一下循环中所获得的成对的约数:2和7二、3和4八、4和3六、6和2四、8和1八、9和1六、12和十二、16和九、18和8等。哦,在获得12和12这对约数后,又开始获得与已找到的相同的约数(以相反的次序)。无须循环到143,在达到12后就能够中止。这就节省 了大量的循环周期。
概括之后,能够肯定必须测试的数只要到num的平方根就能够了,而没必要到num。对于像9这样的数,这并不会节省不少时间,但对于像10000这样的数,差异就很大了。然而,咱们没必要在程序中计算平方根,而是像下面这样描述判断条件:
for (div=2;(div*div)<=num;div++)
if(num%div==0)
printf("%d is divisible by %d and %d.\n",num,div,num / div);
若是num为144,循环运行到div=12终止。若是Num为145,循环运行到div=13终止。
咱们还须要提出两个问题,而后才能准备开始编程。第一,若是测试的数是一个彻底平方数怎么办?报告144可被12和12整除显然有些愚蠢,但能够用嵌套if语句来判断div是否等于num / div。若是是,程序将只打印一个约数,而不是两个。
for (div = 2;(div*div)<=num;div++)
{
if(num % div == 0)
{
if(div*div!=num)
printf( "%d is divisible by %d\n",num,div);
else
printf("%d is divisible by %d.\n",num,div);
}
}
第二,怎么知道一个数是素数呢?若是一个数是素数,程序永远也进不了if语句。为了解决这个问题,能够在循环外设置一个变量为某一值,比方说1,在if语句中将这个变动重设为0.那么循环完成后,检查该变量是否仍然是1.若是是,则历来没有进入过if语句,这个数是素数。
这样的变量一般称为标志(flag)。
传统上,C习惯了用Into类型做为标志,可是新型的_Bool型变量极佳地符合了这种需求。并且经过使用stdbool.h头文件,能够用bool代替_Bool表示这种类型,并用标识符true和false代替1和0.
程序清单 7.5 divisors.c
//divisors.c --使用嵌套if显示一个数的约数 #include <stdio.h> #include <stdbool.h> int main(void) { unsigned long num; //要检查的数 unsigned long div; //可能的约数 bool isprime; //素数的标志 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; //不是一个素数 } } 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判断为素数,而实际上1不是素数。下一部分将要介绍的逻辑运算符将使你可以把1排除在外。