1.1递增(减)运算符的表达式例如:i=3,a=(++i)+(++i)+(++i);大多数学生都知道i++和++i的最终结果都是使i的值加1,但i++和++i作为表达式的用途是不一样的,++i是“先加后用”,i++是“先用后加”。上面的题目是“++”运算符最典型的应用,其中a的结果是18,而不是有些书上分析的4+5+6=15。因为在这里要考虑运算符的优先级,很显然“++”的优先级高于“+”。若是“i=3,a=(++i)+(++i)+(++i)”则a结果是9,而两者最终的i值都将自增3即为6。“—”运算符和“++”运算符使用方式一样,不再赘述。1.2输入语句中缺取址符&例如:scanf(“%d”,x);这一语句错在x前缺取址符,导致输入的数值没有赋给变量x,所以结果出错。再如:chara[10];scanf(“%s”,&a);有学生想,输入语句的输入变量前一定要加取址符,所以这个语句里加了取址符,肯定不会出错。而结果却又恰恰错了,这是为什么呢?因为a在这里既表示数组名字,又表示数组首地址,它本身已经代表了地址,所以就不用再加取址符了。解决此类问题的办法就是在使用输入语句的时候要仔细观察,什么时候该加取地址符号,什么时候不该加,一定要搞清楚。1.3逻辑运算符&&和位运算符&相混淆例如:if(x&y)编辑人员此判别条件的本意是将x和y的“与”(&&)运算结果作为条件。程序运行时,并不出错,但是结果却不对。原因是误用按位“与”运算符‘&’替代了“与”运算符‘&&’,这种错误初学者很容易犯,但是又十分隐秘,在某些特殊情况下甚至可以得出正确的结果,所以更具有迷惑性。位运算符是C语言独特的一种运算符,其中“&”表示对两个操作数按二进制位进行“与”运算,规则是:0&0=0,0&1=0,1&0=0,1&1=1。如6&5=4,其中6变为00000110,5变为00000101,按位“与”运算的结果为100即4。1.4误把赋值=当恒等==例如:if(a==0)误写成if(a=0)。上述写法将导致条件始终为假,进入不了if语句条件为真的分支。编程的时候要仔细,要遵守c语言的语法规则。1.5条件语句(if)和循环条件语句后误加分号例如:if(xy);x=y;这样相当于满足条件执行空语句。下面的x=y语句将被无条件执行。一般情况下if()条件后不需要加分号。例如:for(i=1;i10;i++);{````}上述for语句相当于满足条件执行空语句,真正的循环语句则没有被执行。一般情况下for()循环条件后不需要加分号。这两个都是初学者容易犯的错误,又很难察觉出来。1.6循环语句中改变了循环变量的值例如:求水仙花数main(){inti,a,b,c;for(i=100;i1000;i++){a=i%10;i=i/10;b=i%10;i=i/10;c=i%10;/*i的值被改变*/if(a*a*a+b*b*b+c*c*c==i)printf(“%d”,i);}}此程序看起来思路非常正确,可是高度的时候就是死循环,运行不出结果。为什么呢?仔细观察可知,在循环语句里,循环变量i每次进入循环后都被改变了,导致了i永远都满足循环条件,所以就死循环了。为了避免此类错误,在编程时应尽量避免在循环语句中改变循环变量。1.7作为输出结果的变量没有赋初值例如:求数组中的最大值能最大值的下标main(){inta[10]={8,2,3,4,5,6,3,7},max=a[10],m,i;for(i=0;i10;i++)if(a[i]max){max=a[i];m=i;}printf(“%d%d”,max,m);}程序看似一点毛病都没有,上机调试也都通过,但是结果却不对。原因就在下标变量m没有赋初值,系统随机赋了初值,导致结果错误。给m赋初值0就可以了。1.8初值赋了,但是赋的位置不对例如:求100以内的完数s=0;for(i=1;i=100;i++){for(j=1;j=i/2;j++)if(i%j==0)s+=j;if(s==i)printf(“%d”,i);}是不是这样每一次循环s都变了?程序运行的结果预期是6和28,可是实际上却没有任何结果。原因就是s=0这个语句放错了位置,应该放在外层循环里面,也就是每判断一个数都应该从0开始累加。再如:求1!+2!+……+100!main(){inti,j,s=0,t=1;for(i=1;i=100;i++){for(j=1;j=i;j++)t=t*j;s+=t;}printf(“%d”,s);}t=1应该放在第三行此程序看似正确,可是运行结果却不对,原因也是在t=1这个赋值语句,它的位置应该在外层循环的里面,而不是在外面。这种错误,对于初学者来讲,很容易犯,却又发现不了,在程序调试的时候会浪费很多时间,又会影响编程的自信心。1.9数组和整型或者实型变量不能重名例如:main(){inta[10],a;…}数组名为a,其他变量的名字就不能再用a。1.10数组输出时的错误例如:现在想输出数组a中的所有数值。inta[10]={1,2,3,4,5,6},i;for(i=0;i10;i++)printf(“%d”,a[10]);这个程序看似输出数组的十个元素,其实只输出其中的一个元素。解决此类问题的办法是大家要理解数组下标和循环变量的关系。再如:inta[10]={1,2,3,4,5,6},i;for(i=0;i10;i++)printf(“%d”,a[i]);这个错误也是初学者经常犯的,解决的办法就是牢记C语言中数组下标是从0开始的。1.11字符串不加结束标记例如:chara[3]=“abc”,b[3]=“def”;strcat(a,b);printf(“%s”,a);编程者本意是把字符串a和b连接后输出。可上机的运行结果则是abcdef$%#&,即连接的后面又带了一些乱码。看看好像又挑不出程序有任何毛病,再仔细观察下,原来字符串都有结束标记‘\0’,所以在定义数组的时候应该是字符串的实际长度加1,而我们这两个字符串的长度就不够了,应该改成长度为4,或者更大。这样程序就不会有问题了。所以在处理字符串的时候一定要注意结束标记‘\0’,否则会有不可预料的结果出现。再如:main(){chara[10]=“abc”,b[4]=“def”;inti=0,j=0;while(b[i]!=‘\0)a[j]=b[i];puts(a);}此程序的编程本意是想把字符串b复制到字串a中。可是在输出的时候结果为def^&*,即在复制结果后面带了一些乱码。这个错误对于初学者来讲,可能也很难发现,实际上应该在输出字符串a之前,应该给字符串加个结束标记‘\0’。这样程序就不会出错了。1.12字符串复制,比较等出现的错误例如:chara[4]=“abc”,b[4]=“def”;a=b;编写这段代码的本意是把字符串b复制到字符串a中,初学者往往想通过语句a=b来实现,结果出错。正确的写法则应该是利用函数strcpy(a,b)来实现此功能。再如:chara[4]=“abc”,b[4]=“def”;if(ab){}这一段代码的本意是比较字符串a和字符串b的大小,但是这样比较是不正确的,应该改成if(strcmp(a,b)0){}解决这类问题关键是要记住字符数组名字代表的是字符数组的地址,是常量,不能直接进行复制等操作。这是个容易忽视的地方,也是考试经常出题的地方,希望引起大家的注意。1.13函数调用时参数传递出错例如:voidswap(inta,intb){intt;t=a;a=b;b=t;}此段代码的本意是一个交换两个变量值的函数,但实际上这个函数完不成这个功能,因为本函数传递的是数值,函数调用时传递数值只是对实际参数值的一个拷贝,并不能改变实际参数的值,要完成此功能必须传入地址。因此上例应该为:voidswap(int*a,int*b){intt;t=*a;*a=*b;*b=t;}1.14忘记加头文件例如:求1-1/3+1/5-1/7…,求此序列的和,直到最后一项的绝对值小于1e-6为止。程序如下:main(){doubles=0,x=1;longk=1;intflag=1;while(fabs(x)1e-6){s+=x;k+=2;flag=-flag;x=flag/k;}}学生在调试这个程序时,未发现错误,可就是结果运行不出来。其实程序是没有任何错误。解决此类问题的办法就是要在程序的前面加上一个头文件#include“math.h”,如果不加这个头文件的话,系统将不认识fabs这个函数。1.15函数定义中未声明形参类型这种情况下调用函数,系统默认把其处理为整型参数,若没有声明函数的类型,返回值也为整型。调用时所有参数以整型传递,会出现参数不匹配的情况。解决办法就是明确定义函数参数的类型和个数。2教学建议结合实际教学过程中出现的问题,我们认为教师可以向学生提出几点建议:(1)C语言编程是一个循序渐进的过程。不要好高骛远,一开始学,就想编写那些很复杂很大的程序,这是不切合实际,要踏踏实实打基础。(2)C语言一定要仔细,不能毛毛草草,该写逗号的地方,就不能写成分号。(3)学习C语言的过程中,要善于总结、积累。一是积累一些编程的方法、思想,下次再遇到类似的问题,就会有思路。二是要积累编程过程中遇到的错误,最好准备一个小本子,把它记录下来。下次再遇到这样的问题,就会解决了,这样会节省很多时间。1.关于条件表达式。形如:逻辑表达式?表达式1:表达式2。逻辑表达式的值若为非零(真),则条件表达式的值等于表达式1,若逻辑表达值的值为零(假),则条件表达式的值等于表达式2的值。特别要注意的是条件表达式的结合方向是从右向左结合的。例:与y=(x0?1:x0?-1:0);的功能相同的if语句是:if(x0)y=1;elseif(x0)y=-1;elsey=0;解:y=(x0?1:x0?-1:0)与y=(x0?1:(x0?-1:0))等价。2.关于赋值表达式,将赋值号=右侧表达式的值赋给赋值号左边的变量。赋值表达式的值为执行赋值后被赋值的变量的值。形如a=b,b会被转换为符合a的类型,如果不能转换,要么报警告,要么报错。赋值表达式也是从右向左结合的。例:下列选项中,不正确的赋值语句是__C__A)++tB)n1=(n2=(n3=0))C)k=1=jD)a=b+c=1解:C选项里先执行的是右结合的1=j显然错误,注意B选项是以赋值表达式赋值,是正确的,其整个表达式最终的值是0。3.关于逗号表达式,顺序求(表达式1,表达式2……表达式n)的值,则整个表达式的类型和值都为表达式n的值。例:设有以下定义:main(){intx=10,y=3,z;printf(%d\n,z=(x%y,x/y));}输出结果是__3__4.关于实型表达式,只要表达式中有一个运算量是实型(float或double),运算过程中所有的运算量都要转换为double型,表达式的结果也为实型。其余类似,即往宽的地方转换。如果两个整形值相除,其结果被截尾取整,如果该操作数是负数,则截断的方向并无规定。例:若已定义X和Y为double型,则表达式:x=1,y=x+3/2的值是__C__A)1B)2C)2.0D)2.5解:'/'的优先级较高,所以先算3/2,这是两个整形相除,结果是1,而不是1.5。然后算x+1,因为x是double型,所以整形的运算量1要转换为double型,最终结果为double型。5.形如a+=x的表达式的等价于a=a+x。例:设inta=12,则执行完语句a+=a-=a*a后,a的值是__-264___解:赋值表达式的结合顺序是从右向左结合的。先执行a-=a*a,即a=a-a*a,在这一步时a=12-12*12,即a=-132再执行a+=,即a=a+a,在这一步时a=-132+(-132),所以a=-2646.常用字符ASCII码:'0'——48,'9'——57,'A'——65,'a'——97,'\0'或'\000'——0(代表空操作字符,同时也是字符