程序设计方法:
1.从问题的全局出发,写出一个概括性的抽象的描述。
2.定义变量,选取函数,确定算法。算法这个东西不好说,遇到的问题多了,自然就会形成自己一整套的算法。
3.按照解决问题的顺序把语句和函数在main()里面堆砌起来。
一个好的C程序员应该做到:
1.在运行程序之前存盘
2.所有在程序中用到的常量都用预处理语句在程序开头定义
3.所有在程序中用到的函数都在程序开头声明
4.头文件的#ifndef
5.变量名和函数名使用有意思的英文单词或汉语拼音
6.尽量少用全局变量或不用全局变量
7.采用层次的书写程序格式,对for,while,if_else,do_while,switch_case等控制语句或他们的多重嵌套,采用缩格结构
8.所有对应的{}都对齐
9.尽量用for,而不用while做记数循环
10.尽量不用goto语句
11.一个函数不宜处理太多的功能,保持函数的小型化,功能单一化
12.一个函数要保持自己的独立性,如同黑匣子一样,单进单出
13.函数的返回类型不要省略
14.用malloc()分配内存空间时,以后一定要用free()释放
15.打开文件后,记住在退出程序前要关闭
16.出错情况的处理
17.写上必要的注释
这里说的是一些基本的,经常遇到的情况,还有其他很多要注意的地方,在实际编程中都会遇到.
一个表达式的返回值都可以用来判断真假,除非没有任何返回值的void型和返回无法判断真假的结构。当表达式的值不等于0时,它就是“真”,否则就是假。一样个表达式可以包含其他表达式和运算符,并且基于整个表达式的运算结果可以得到一个真/假的条件值。因此,当一个表达式在程序中被用于检验其真/假的值时,就称为一个条件。
一、if语句
if(表达式) 语句1;
如果表达式的值为非0,则执行语句1,否则跳过语句继续执行下面的语句。
如果语句1有多于一条语句要执行时, 必须使用{和} 把这些语句包括在其中, 此时条件语句形式为:
if(表达式)
{
语句体1;
}
例如:
if(x>=0) y=x;
if(a||b&&c)
{
z=a+b;
c+=z;
}
二、if--else语句
除了可以指定在条件为真时执行某些语句外,还可以在条件为假时执行另外一段代码。在C语句中利用else语句来达到这个木的。
if(表达式) 语句1;
else 语句2;
同样,当语句1或语句2是多于一个语句时,需要用{}把语句括起来。
例如:
if(x>=0) y=x;
else y=-x;
三、if--else if--else结构。
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
.
.
.
else
语句n;
这种结构是从上到下逐个对条件进行判断,一旦发现条件满点足就执行与它有关的语句, 并跳过其它剩余阶梯;若没有一个条件满足,则执行最后一个else 语句n。最后这个else常起着缺省条件的作用。同样,如果每一个条件中有多于一条语句要执行时,必须使用{和}把这些语句包括在其中。
条件语句可以嵌套,这种情况经常碰到,但条件嵌套语句容易出错,其原因主要是不知道哪个if对应哪个else。
例如:
if(x>20||x<-10)
if(y<=100&&y>x)
printf(Good);
else
printf(Bad);
对于上述情况, Turbo C2.0规定: else语句与最近的一个if语句匹配, 上例中的else与if(y<=100&&y>x)相匹配。为了使else与if(x>20||x<-10)相匹配, 必须用花括号。如下所示:
if(x>20||x<-10)
{
if(y<=100&&y>x)
printf(Good);
}
else
printf(Bad);
下面举几个例子:
1.输入一个数,如果大于0,输出plus;如果是负数,输出negative;如果正好是0,则输出zero。
main()
{
float num;
scanf(%f,&f);
if(num>0)
printf(plus\n);
else if(num<0)
printf(negative\n);
else
printf(zero\n);
}
先定义两个变量,然后输入一个数,然后判断这个数的范围,输出对应的字符串。
2.输入一个数x,输出y。其中y是x的绝对值。
main()
{
float x,y;
scanf(%f,&x);
if(x>=0) y=x;
else y=-x;
printf(%f\n,y);
}
程序比较简单,这儿就不分析了。
其实Trubo C 2.0把一些常用的功能都写好了,我们只需要使用就可。例如求绝对值的功能在C的库里面就有。看下面的:
#include math.h
main()
{
float x,y;
scanf(%f,&x);
y=fabs(x); /*求x的绝对值,然后赋值给y*/
printf(%f\n,y);
}
这个程序和上面的程序完成的功能是一模一样的,都是求绝对值。可以看出,用下面这个方法比上面就要好一些。由于fabs()是一个函数,系统自带的,所以在使用它的时候,我们必须把它所在的库文件math.h包含都程序中,即程序最前面一行。类似的还有求开方sqrt(),求指数幂exp()等等,这些与数学方面有关的函数都在math.h里面。具体哪些有哪些没有,在什么库里面,可以查看一些手册。
3.输入x,输出y,x和y满足关系:
x<-5 y=x;
-5<=x<1 y=2*x+5;
1<=x<4 y=x+6;
x>=4 y=3*x-2;
程序如下:
main()
{
float x,y;
scanf(%f,&x);
if(x<-5)
y=x;
else if(-5<=x&&x<1)
y=2*x+5;
else if(1<=x&&x<4)
y=x+6;
else
y=3*x-2;
printf(%f\n,y);
}
这里要说明两点:
(1).-5<=x&&x<1不能写成-5<=x<1;1<=x&&x<4也不能写成1<=x<4;在C语言中,不能认识连续不等式。
(2).y=2*x+5不能写成y=2x+5;y=3*x-2也不能写成y=3x-2;这与我们平时所写的方法不一样。
4.输入三个数x,y,z,然后按从大到小输出。
main()
{
float x,y,z;
scanf(%f%f%f,&x,&y,&z);
if(x>=y&&x>=z)
{
printf(%f\t,x);
if(y>=z) printf(%f\t%f\n,y,z);
else printf(%f\t%f\n,z,y);
}
else if(y>=x&&y>=z)
{
printf(%f\t,y);
if(x>=z) printf(%f\t%f\n,x,z);
else printf(%f\t%f\n,z,x);
}
else
{
printf(%f\t,z);
if(x>=y) printf(%f\t%f\n,x,y);
else printf(%f\t%f\n,y,x);
}
}
说明:这是一个典型的if语句嵌套结构,如果不使用括号,那么if和else的对应关系就乱了。
四、switch--case语句
在编写程序时, 经常会碰到按不同情况分转的多路问题, 这时可用嵌套if -else-if语句来实现, 但if-else-if语句使用不方便, 并且容易出错。对这种情况, Turbo C2.0提供了一个开关语句。开关语句格式为:
switch(变量)
{
case 常量1:
语句1或空;
case 常量2:
语句2或空;
.
.
.
case 常量n:
语句n或空;
default:
语句n+1或空;
}
执行switch开关语句时,将变量逐个与case后的常量进行比较,若与其中一个相等,则执行该常量下的语句,若不与任何一个常量相等,则执行default后面的语句。
注意:
1.switch中变量可以是数值,也可以是字符,但必须是整数。
2.可以省略一些case和default。
3.每个case或default后的语句可以是语句体,但不需要使用{和}括起来。
例如:
main()
{
int x,y;
scanf(%d,&x);
witch(x)
{
case 1:
y=x+1;
break; /*退出开关语句,遇到break才退出*/
case 4:
y=2*x+1;
break;
default:
y=x--;
break;
}
printf(%d\n,y);
}
从上面的例子可以看出,用开关语句编的程序一定可以用if语句做。那么在什么情况下需要用switch语句呢?一般在出现比较整的情况下或者能转化成比较整数的情况下使用。看下面的例子:
例子:一个学生的成绩分成五等,超过90分的为'A',80-89的为'B',70-79为'C',60-69为'D',60分以下为'E'。现在输入一个学生的成绩,输出他的等级。
(1).用if语句
main()
{
float num;
char grade;
scanf(%d,&num);
if(num>=90) grade='A';
else if(num>=80&&num<89) grade='B';
else if(num>=70&&num<79) grade='C';
else if(num>=60&&num<69) grade='D';
else grade='E';
printf(%c,grade);
}
(2).用switch语句
main()
{
int num;
char grade;
scanf(%d,&num);
num/=10;
switch(num)
{
case 10:
case 9:
grade='A';
break;
case 8:
grade='B';
break;
case 7:
grade='C';
break;
case 6:
grade='D';
break;
default:
grade='E';
break;
}
printf(%c,grade);
}
说明一点,并不是每个case里面有都语句,有时侯里面是空的,就好象这一题。switch语句执行的顺序是从第一case判断,如果正确就往下执行,直到break;如果不正确,就执行下一个case。所以在这里,当成绩是100分时,执行case 10:然后往下执行,grade='A';break;退出。
想想看,这里为什么要用num/=10;?
假设当程序中有浮点数时怎么办呢?
Turbo C 2.0提供三种基本的循环语句: for语句、while语句和do-while语句。
一、循环语句
(一)、for循环 它的一般形式为:
for(<初始化>;<条件表过式>;<增量>)
语句;
初始化总是一个赋值语句,它用来给循环控制变量赋初值;条件表达式是一个关系表达式,它决定什么时候退出循环;增量定义循环控制变量每循环一次后按什么方式变化。这三个部分之间用;分开。
例如:
for(i=1;i<=10;i++)
语句;
上例中先给i赋初值1,判断i是否小于等于10,若是则执行语句,之后值增加1。再重新判断,直到条件为假,即i>10时,结束循环。
注意:
(1).for循环中语句可以为语句体,但要用{和}将参加循环的语句括起来。
(2).for循环中的初始化、条件表达式和增量都是选择项,即可以缺省,但;不能缺省。省略了初始化,表示不对循环控制变量赋初值。省略了条件表达式,则不做其它处理时便成为死循环。省略了增量,则不对循环控制变量进行操作,这时可在语句体中加入修改循环控制变量的语句。
(3).for循环可以有多层嵌套。
例如:
for(;;) 语句;
for(i=1;;i+=2) 语句;
for(j=5;;) 语句;
这些for循环语句都是正确的。
main()
{
int i,j;
printf(i j\n);
for(i=0;i<2;i++)
for(j=0;j<3;j++)
printf(%d %d\n,i,j);
}
输出结果为:
i j
0 0
0 1
0 2
1 0
1 1
1 2
用for循环求1+2+……+100的和:
main()
{
int sn=0,i;
for(i=1;i<=100;i++)
sn+=i; /*1+2+……+100*/
printf(%d\n,sn);
}
从程序可以看出,使用循环语句可以大大简化代码。
(二)、while循环 它的一般形式为:
while(条件)
语句;
while循环表示当条件为真时,便执行语句。直到条件为假才结束循环。并继续执行循环程序外的后续语句。
例如:
#include stdio.h
main()
{
char c;
c='\0'; /*初始化c*/
while(c!='\n') /*回车结束循环*/
c=getche(); /*带回显的从键盘接收字符*/
}
上例中,while循环是以检查c是否为回车符开始,因其事先被初始化为空,所以条件为真,进入循环等待键盘输入字符;一旦输入回车,则c='\n',条件为假,循环便告结束。与for循环一样,while循环总是在循环的头部检验条件,这就意味着循环可能什么也不执行就退出。
注意:
(1).在while循环体内也允许空语句。
例如:
while((c=getche())!='\n');
这个循环直到键入回车为止。
(2).可以有多层循环嵌套。
(3).语句可以是语句体, 此时必须用{和}括起来。
用while循环求1+2+……+100的和:
main()
{
int sn=0,i=0;
while(++i<=100)
sn+=i; /*求1+2+……+100*/
printf(%d\n,sn);
}
(三)、do--while循环 它的一般格式为:
do
{
语句块;
}
while(条件);
这个循环与while循环的不同在于:它先执行循环中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while循环至少要执行一次循环语句。
同样当有许多语句参加循环时,要用{和}把它们括起来。
用do--while循环求1+2+……+100的和:
main()
{
int sn=0,i=1;
do
sn+=i; /*求1+2+……+100*/
while(++i<=100);
printf(%d\n,sn);
}
从上面三个程序看出,使用for,while和do--while求解同样的问题,基本思路都差不多,只是在第一次计算时,注意初值。
二、循环控制
(一)、break语句
break语句通常用在循环语句和开关语句中。当break用于开关语句switch中时,可使程序跳出switch而执行switch以后的语句;如果没有break语句,则将成为一个死循环而无法退出。break在switch中的用法已在前面介绍开关语句时的例子中碰到,这里不再举例。
当break语句用于do-while、for、while循环语句中时,可使程序终止循环而执行循环后面的语句,通常break语句总是与if语句联在一起。即满足条件时便跳出循环。
例如:
main()
{
int sn=0,i;
for(i=1;i<=100;i++)
{
if(i==51) break; /*如果i等于51,则跳出循环*/
sn+=i; /*1+2+……+50*/
}
printf(%d\n,sn);
}
可以看出,最终的结果是1+2+……+50。因为在i等于51的时候,就跳出循环了。自己写写怎样在while和do--while循环中增加break语句。
注意:
1. break语句对if-else的条件语句不起作用。
2. 在多层循环中,一个break语句只向外跳一层。
例如:
main()
{
int i,j;
printf(i j\n);
for(i=0;i<2;i++)
for(j=0;j<3;j++)
{
if(j==2) break;
printf(%d %d\n,i,j);
}
}
输出结果为:
i j
0 0
0 1
1 0
1 1
当i==0,j==2时,执行break语句,跳出到外层的循环,i变为1。
(二)、continue语句
continue语句的作用是跳过循环本中剩余的语句而强行执行下一次循环。
continue语句只用在for、while、do-while等循环体中, 常与if条件语句一起使用,用来加速循环。
例如:
main()
{
int sn=0,i;
for(i=1;i<=100;i++)
{
if(i==51) continue; /*如果i等于51,则结束本次循环*/
sn+=i; /*1+2+……+50+52+……+100*/
}
printf(%d\n,sn);
}
从程序中可以看出,continue语句只是当前的值没有执行,也就是说当前的值跳过去了,接着执行下次循环。
main()
{
int i,j;
printf(i j\n);
for(i=0;i<2;i++)
for(j=0;j<3;j++)
{
if(j==1) continue;
printf(%d %d\n,i,j);
}
}
输出结果为:
i j
0 0
0 2
1 0
1 2
(三)、goto语句
goto语句是一种无条件转移语句,与BASIC中的goto语句相似。goto语句的使用格式为:
goto 标号;
其中标号是Turbo C 2.0中一个有效的标识符,这个标识符加上一个:一起出现在函数内某处,执行goto语句后,程序将跳转到该标号处并执行其后的语句。标号既然是一个标识符,也就要满足标识符的命名规则。另外标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。通常goto语句与if条件语句连用,当满足某一条件时,程序跳到标号处运行。goto语句通常不用,主要因为它将使程序层次不清,且不易读,但在多层嵌套退出时,用goto语句则比较合理。
main()
{
int sn=0,i;
for(i=1;i<=100;i++)
{
if(i==51) goto loop; /*如果i等于51,则跳出循环*/
sn+=i; /*1+2+……+50*/
}
loop: ;
printf(%d\n,sn);
}
可以看出,这儿的goto语句和break作用很类似。
这儿的loop: ;
printf(%d\n,sn);
也可以写成loop: printf(%d\n,sn);
main()
{
int sn=0,i;
for(i=1;i<=100;i++)
{
if(i==51) goto loop; /*如果i等于51,则跳出本次循环*/
sn+=i; /*1+2+……+50+52+……+100*/
loop: ;
}
printf(%d\n,sn);
}
可以看出这儿的loop语句和continue的作用类似。
但是某些情况下又必须使用goto语句,否则会让程序大大臃肿。如:
main()
{
int i,j,k;
printf(i j k\n);
for(i=0;i<2;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
{
if(k==2) goto loop;
printf(%d %d %d\n,i,j,k);
}
loop: ;
}
输出结果为:
i j k
0 0 0
0 0 1
如果不使用goto语句,而使用break,continue语句,应该这样
main()
{
int i,j,k;
printf(i j\n);
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
{
for(k=0;k<3;k++)
{
if(k==2) break;
printf(%d %d %d\n,i,j,k);
}
if(k==2) break;
}
if(k==2) break;
}
}
输出结果为:
i j k
0 0 0
0 0 1
所以在同时跳出多层循环时,应该使用goto语句。记住,所有的goto语句其实都是可以用break,continue代替的。
下面举几个例子:
1.求两个整数的最大公约数。例如10和15的最大公约数是5。
分析:最大公约数一定小于等于最小的那个数一半,同时能被两数整除。
main()
{
int num1,num2,i,min;
scanf(%d%d,&num1,&num2);
min=num1<num2?num1:num2; /*得到最小值*/
for(i=min/2;i>0;i--)
if(num1%i==0&&num2%i==0) break;
printf(最大公约数为%d\n,i);
}
2.求1!+2!+……+n!(n<10)
main()
{
int n,i;
long temp=1,sn=0; /*从9!以后,所得的值就超过了int范围*/
scanf(%d,&n);
for(i=1;i<=n;i++)
{
temp*=i;
sn+=temp; /*如果没有这一步,求的就是n!*/
}
printf(%ld\n,sn);
}
那么想想,如果求1!+3!+5!+……+n!应该怎么办?
3.判断一个整数是不是素数(素数就是只能被本身和1整除的数)。
#include math.h
main()
{
int num,i,flag=0;
scanf(%d,&num);
for(i=2;i<sqrt(num);i++) /*这里面使用sqrt()是为了减少循环步骤,如果写成i<num也可以,但是所花费的时间将多很多。*/
{
flag=0; /*标志变量复位*/
if(num%i==0)
{
flag=1;
break;
}
}
if(flag==0) printf(是素数\n);
else printf(不是素数\n);
}
可以说,在所有的C语言书上,都有判断素数的例题。它的编程思想是:把一个变量作为标志变量,用来标志是不是素数;循环体是从2到sqrt(num),因为如果一个数不是素数的话,一定能分解成num=num1*num2,它们中的最小值一定小于sqrt(num),所以循环的时候只要到sqrt(num)就可以了。同时要注意变量复位的问题。