C和C++程序设计常见的错误代号收集
第一章  C/C++程序设计概述
第二章  数据类型和运算符
第三章  结构化程序设计
第四章  数组
第五章  函数
第六章  面向对象程序设计基础
第七章  基于对话框的应用程序
第八章  文档/视图结构应用程序
第九章  文件
第一章  C/C++程序设计概述                   
1. 为什么语句末要加分号“;”?
分号是C语句的组成部分,不能漏掉或忘记。例如:
double  r        // 该语句编译时就会出现语法错误。并提示错误信息:
cin>>r ;         // error C2146: syntax error : missing ';' before identifier 'cin'
2. 为什么变量要先定义后使用?
C/C++规定任何变量都必须在使用前定义,否则编译时会出错。例如:
main ( )
{
int x=3,y=5;  //变量z没有定义就使用,编译时会出错。
z=x+y;      //编译时提示错误信息:error C2065: 'z' : undeclared identifier
3. 标识符大小写有什么区别?
C/C++严格区分大小字符,标识符大小写也有严格区别。例如:
double  r;
cin>>R;
C/C++将小写变量r和大写变量R看作两个不同的变量,所以编译时将提示错误信息:
error C2065: 'R' : undeclared identifier。
4. 为什么要加预处理命令(头文件)?
在输入、输出、函数调用时必须在#include命令中包含相应的头文件*.h。
void main() 
{ int x,y,t;
cout<<"输入 x y:"<<endl;
cin>>x>>y;
if (x<y)
t=x;
else
y=t;
cout<<x<<">"<<y<<endl;
}
由于缺少#include "iostream.h"命令,编译时的出错信息:
error C2065: 'cout' : undeclared identifier
error C2065: 'endl' : undeclared identifier
初学者常用的头文件:
(1)用cout、cin进行输入输出时,需要头文件:iostream.h
(2)用scanf( )、printf( ) 进行输入输出时,需要头文件:stdio.h
(3)使用sqrt( )、abs( )等数学函数时,需要头文件:math.h
(4)使用gets( )、puts( )等有关字符处理函数时,需要头文件:string.h
第二章  数据类型和运算符                                 
1. 关于求余运算符“%”的问题?
%是求余运算符;C/C++规,定a%b运算中变量a和b必须为整形。如:8%3的结果是2;而8.6%3是非法运算。
2. 关于整除运算“/”的问题?
整除运算的结果依然为整型数。例如:9/2的结果为4,而9.0/2的结果为4.5。
特别注意:1/3+1/3+1/3的结果为0。
printf怎么加endl3. 字符常量与字符串常量有何区别?
字符常量是由单引号括起的一个字符,如:'s'。而"s"是字符串常量,由双引号括起,包含两个字符:'s'和'\'。使用时不能混淆,例如:
char c, p;
p='s';        //正确
c="s";       //错误,字符变量c和p只能存放一个字符
4. 输入输出时要注意的问题?
(1)输入输出格式符要与数据类型保持一致;否则会输出莫名其妙的结果。
例如:float a=3.7, b=4.2;  printf("a=%d, b=%d\n", a,b);
输出结果为:a=-1610612736,  b=1074633113 显然是错的
(2)不能忘记使用地址符号“&”。
例如:错误的输入语句:scanf ("%d%d",a,b);
正确的语句:scanf ("%d%d",&a,&b);
(3)输入数据的方式与格式要求要相符
例如:scanf("a=%d,b=%d",&a,&b);
输入数据的形式为:a=20,b=67
5. “=”与“= =”有何区别?
“=”是赋值运算符,“= =”是关系运算符;误用会造成严重后果。
例如:if (a= =3)  a=b; 表示如果a等于3,将b值赋给a。若误成:
if (a=3)  a=b; 无论a为何值,条件总是成立,即b值总是赋给a。
这与本意不符。
6. ++和--运算要注意哪些问题?
(1)++和--运算只能适用于整型变量;
例如:n*m++ 正确的,而(n * m)++是错误的;因为(n * m)是表达式。
(2)前置和后置有区别:
int n = 2, post, pre;
post = n++;        //执行后post为2,n为3
pre = ++n; //执行后post为3,n为3
第三章  结构化程序设计                       
1. 为何if语句中的条件总是成立或不成立?
在排除可能出现的逻辑错误外,有可能与条件表达式书写不正确有关。
例如:条件语句if (x=3) x=x+8; 这时的条件x=3始终成立,语句x=x+8也总是执行。要判断x是否等于3就必须写成x = = 3。
又如:条件语句if (x=0) x=x+8; 这时条件x=0总是不成立,语句x=x+8永远不执行。要判断x是否等于0就必须写成x= =0。
同样,在其它使用条件的语句中也要注意类似问题。
2. 为什么会出现if-else不匹配?
这种错误的原因可能比较复杂;总的原则是:
(1)有一个else必有一个if,所以首先在数量上要匹配
(2)逻辑关系要合理;若执行的是复合语句,不要漏掉复合语句标志{ }。
例如: if (x<y)  t=a; a=b; b=t;  else  t=m; 编译时就会提示出错信息:
error C2181: illegal else without matching if;
即if-else不匹。正确的写法:
if (x<y) {t=a; a=b; b=t;} else t=m;
(3)若条件不成立时要求执行的语句有多条,else后必须为复合语句。
例如:if (x<y) {t=a; a=b; b=t;} else {t=m; m=n; n=t;}
3. if-else if语句中多分支问题?
(1)多边选择ElseIf子句的关键字Else If之间必须有空格。
(2)在多个条件表达式的表示时,应从最小或最大的条件依次表示,以避免条件的过滤。例如,已知输入某课程的百分制成绩mark,要求显示对应五级制的评定,评定条件如下:
有以下几种表示方式,语法上都没有错,但执行后结果有所不同,请读者分析哪些正确?哪些错误?
方法一:
if (mark >= 90)
cout<< "优";
else if (mark >= 80)
cout<< "良";
else if (mark >= 70)
cout <<"中";
else if (mark >= 60)
cout <<"及格";
else
cout <<"不及格";
方法二:
if (mark < 60)
cout "不及格";
elseif (mark < 70)
cout<< "及格";
elseif (mark < 80)
cout<< "中";
elseif (mark < 90)
cout<< "良";
else
cout<< "优";
方法三:
if ( mark >= 60)
cout<< "及格";
else if (mark >= 70)
cout<< "中";
else if (mark >= 80)
cout<< "良";
else if (mark >= 90)
cout<< "优";
else
cout<< "不及格";
上述答案中,方法一、二的执行结果正确,三的执行结果错误。
下面的两个方法中有一个是正确的,请读者分析各自的原因。
方法四:
if (mark >= 90)
cout<< "优";
else if (80 <= mark < 90)
cout<< "良";
else if (70 <= mark < 80)
cout<< "中";
else if (60 <= mark < 70)
cout<< "及格";
else
cout<< "不及格";
方法五:
if (mark >= 90)
cout<< "优";
else if (80 <= mark and mark < 90)
cout<< "良";
else if (70 <= mark and mark < 80)
cout<< "中";
else if (60 <= mark and mark < 70)
cout<< "及格";
else
cout<< "不及格";
4. 为什么for循环体不运行?
若for语句的有关条件设置正确,问题可能出在for语句后加了分号“;”。例如:
sum=0;
for (k=0;k<10;k++);
sum+=k;
设计者有意无意中在for后加了“;”,循环体就变成了空语句分号“;”语句sum+=k;没有参与循环。
同样:while(k<10); 只有空语句分号“;”进行循环。类似情况用户多加注意。
5. switch语句各分支中漏写 break语句时,会产生什么问题?
例如:根据考试成绩等级打印出百分制数段。
switch(grade)
{
case 'A': printf("85~100\n");
case 'B': printf("70~84\n");
case 'C': printf("60~69\n");
case 'D': printf("<60\n");
default: printf("error\n");
}
由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数。
正确写法应在每个分支后再加上“break;”。如:case 'A':printf("85~100\n");break;
6. 求累加和、累乘积时赋初值问题?
累加的初值应为0、连乘的初值应为1。
求累加和:
sum=0; 
for (k=10,k<=20; k++)
sum=sum+k;
求累乘积
fact=1;
for(k=1;k<8;k++)
fact=fact*k;
7. 循环嵌套问题?
(1)内循环与外循环控制变量不能同名;
(2)外循环必须完全包含内循环,不能交叉;
(3)goto语句可以从循环体内转向循环体外,不能从循环体外转向循环体内;
(4)循环控制变量初始条件、终止条件、变化的规律要非常清楚;
第四章  数组                       
1.数组长度不能是变量?
C/C++不允许定义可变长度的数组;否则编译时出错。例如:
int n=20;      //编译时会提示错误信息:
int s[n];       //error C2057: expected constant expression. 希望数组大小是一个常量表达式。
可以将N定义成符号常量;间接定义大小可变的数组。例如:
#define  N  100  //改变N的大小相当于改变数组体积
int s[N]; 
2.数组初始化和赋值时要注意的问题?
(1)不能对数组名赋值。
例如:int a[10];  a={1,3,5,7,9};   //错误
(2) int a[10]; a[10]={1,3,5,7,9};        //错误,因为a[10]不是数组a的元素。
3.引用数组元素时下标超界问题?
(1)引用数组元素时下标不能越界。例如:
int k,a[5]={1,2,3,4,5};
for (k=1;k<=5;k++) 
cout<<a[k];
数组a有5个元素,下标范围由0到4;所以数组元素a[5]不存在,即下标的值超出了数组范围。但是编译器不给出错误, 还会获得莫名其妙的结果。所以用户在使用数组时要特别注意下标超界问题;否则会产生非常严重的后果。
(2)语句int a[4]={1,3,5,7,9};是错误的,常数个数超过数组定义的长度。
4.引用数组元素时误用圆括号?
例如:int  k,a[5]={1,2,3,4,5};
for (k=1;k<=5;k++)
      cout<<a(k);          // a(k)写法错误;
5. 字符数组与字符指针的区别?
字符指针可以直接赋值,数组名不可以。例如:
char str[10];                                                          char *str;
str="COMPUTER";   //错误                  str="COMPUTER";    //正确
6. 将字符串与逐个字符分别赋给字符数组时的区别?
例如:
char s[8]={ "COMPUTER"}; //是错的,串"COMPUTER"超出了数组s的长度
char s[8] = {'C', 'O', 'M', P', 'U'. 'T', 'E', 'R'}; //可以,但数组中不是字符串
分析下列程序:
#include  "stdio.h"
#include  "iostream.h"
void main( )
{int   k;
     char  c[5] = {'C', 'h', 'i', 'n', 'a'};       //C数组内容不是字符串
     char  b[ ] = "China";                       // b数组内容是字符串   
     for ( k = 0; k<5; k++)           
         cout<< c[i];                //不能用puts(c);  也不能用cout<<c; 
puts(b);                                   //或 cout<<b;
     for (i = 0; b[i] !='\0'; i++)     
cout<< b[i]; }                  //可以,但不好,不主张用这种方法
7. 使用CString类时的问题?
(1)必须使用#include “afx.h”预处理命令; 否则编译时出现错误信息:
error C2065: 'CString' : undeclared identifier。
(2)要进行必要的设置;
必须在“工程|设置”命令对话框中,将“Microsoft Foundation Class”下拉框设为:
“Use MFC in a Static Library”。否则链接时也会出现错误。
(3) cin不支持CString对象,只能通过字符数组间接输入。
例如:#include "iostream.h"
#include "afx.h"
void main()
{
char st1[80];
CString   st2,st3;
CString   st4=" Microsoft Foundation Class";       //定义st4对象并获得字符串
   cin>>st1;
          st2=st1;                                    //字符数组赋值给对象st2
   cin>>st3;                                    //错的,Cstring对象st3不能通过cin输入值
}
8. 指针与维数组名有区别?
有定义语句:int s[6]={2,3,4,5,6,7}, *p=s; 则数组名s与指针p既有联系亦有区别。
(1)S[k]等价于*(p+k);均表示数组元素
(2) s+k等价于p+k;均表示元素地址,但p++可以,s++错。
(3)*p++:取p指对象内容后,在使p指向下一元素。
(4)(*p)++:取p指对象的值,并将该值加1后再赋给该对象。
9. C++中一级指针不能指向二维数组?
例如: int a[3][4], *p=a; 在C++中是错的;错误信息为:
cannot convert from 'int [2][3]' to 'int *'
但在C中语句int a[3][4], *p=a;是正确的。
第五章  函数                             
1. 运行时报“missing function header”错误是什么原因?
函数头不是语句,其后不能有分号,若加分号则成了一条说明语句,故其后的函数体缺少函数头。
2. 如何确定函数中形参的个数?
函数的作用是实现函数与调用者的数据通信。一方面,函数要实现某一功能需要的数据,调用者需为其提供初值,这是通过实参传递给形参实现的;另一方面,函数将结果传递给调用者,除了可以通过return语句返回一个结果外,其余的要通过引用或指针传递方式实现。因此,形参的个数就是由上述两方面决定的。
3. 函数间参数传递方式如何确定?
形参与实参的结合有传值、传址和引用等方式。
形参是变量名,这是传值方式,它是单向的,即只能从外界向函数传入初值,但不能将结果传出。
形参是指针或数组名,这是传址方式,它是双向的,既可传入又可传出。
形参是引用,其作用同传址方式,也是双向的,但它比传址方式更方便、直接。
4. 实参与形参类型对应问题
(1)引用或传址方式时,形参与实参的类型必须要一致。例如:
#include "iostream.h" 
 void f(int &a)
 {
   a=a*a;
 }
 void main()
{
   float x=5;
   f(x);
   cout<<x<<endl;
 }
程序编译后会显示“cannot convert parameter 1 from 'float' to 'int &'”的语法错误。
(2)传值方式时,若是数值型,则实参按形参的类型将值传递给形参。例如:
#include "iostream.h" 
int f(int a)
 {
   a=a*a;
   return a;
 }
 void main()
{
  float x=5.5;
  cout<< f(x)<<endl;        //输出25
}
程序编译后显示“conversion from 'float' to 'int', possible loss of data”的警告错误,有结果输出,但由于类型不同数据可能会丢失,故形参与实参的类型应保持一致。
5. 函数swap是交换两变量的值,用下面两种形式使a,b交换后的值返回为何不行?
(1)int swap(int a,int b)
{
int temp;
temp=a;a=b;b=temp;
return a,b;
}
(2)int swap(int a,int b)
{
int temp;
temp=a;a=b;b=temp;
return a;
return b;
}
形式1中返回的a,b是一逗号表达式,该表达式的值是最后一表达式的值即b的值,所以它只能把b值返回;而形式2中当执行return a;语句后即返回到调用处。变量b的值无法返回。
6. 用指针变量作函数形参时,形参的改变一定会影响对应的实参值吗?
下面这个例子运行后的结果是1而不是3,原因是函数f中,指针s的指向改变了,它指向新申请的一个存储单元,当函数调用结束,该存储单元即被释放。所以,主函数中s指针所指的存储单元的值没有改变。若将函数f中的s=new int;语句删除,则程序运行后的结果是3,因为此时形参s与对应的实参s指向的是同一存储单元,所以,只有当它们指向同一存储单元时,对形参所指内容的修改才会影响对应的实参值。
 #include "iostream.h"
 
void f(int x,int y,int *s)
 {
s = new int;
   *s=x+y;
 }
 void main()
 {
int a=1, b=2,*s=&a;
  f(a, b,s);
  cout<<*s<<endl;
 }
7. 数组作为参数传递时形参与实参写法上的区别
形参与实参都是数组时,它们的写法是有区别的。例如:
#include "iostream.h" 
 void f(int a[ ],int n)
 {
   for(int i=0;i<n;i++)
     a[i]=a[i]*a[i];
 }
 void main()
{
   int a[10],i;
   for(i=0;i<10;i++)a[i]=i+1;
   f(a,10);
   for(i=0;i<10;i++)cout<<a[i]<<endl;
 }
实参只能写数组名a,不能写成a[ ]或a[10]的形式;而其对应的形参数组可以不必说明其具体的大小,通常在数组名后跟一对[]说明即可,因为编译器对形参数组大小不作检查。
第六章  面向对象程序设计基础               
1. 在类定义结尾处忘加分号是一种常见的语法错误。
2. 对构造函数指定返回类型或是构造函数中有返回值的语句都是语法错误。
3. 在类定义中显式初始化类的数据成员是语法错误。如:
class A
{
private:
int year=2002, month=10, day=12;
……
};
4. 在类体外定义类的成员函数时,漏写类名和作用域运算符。
5. 在主函数中访问类的私有成员或保护成员是不允许的。
6. 把修改对象数据成员的成员函数定义为常成员函数。
7. 对常对象调用非常成员函数是不允许的。
8. 当提供了有参构造函数,而没有显式地给出默认的构造函数,而定义的对象中既有有参对象,又有无参对象时,则无参对象无法创建。如:
#include "iostream.h"
class Circle1
{
private: 
   double x,y,r,s;
 public: 
     void print( );
     Circle1( ){};          //缺少该语句会产生语法错误
         Circle1(double x1,double y1,double r1);
};
//成员函数的具体定义略
void main()
{
Circle1 p1(0,0,2),p2(1,1,4),p3;
   ……
}
9. 派生类的成员函数中引用了基类的私有成员是不允许的。
10. 在派生类的成员函数中要调用基类中的同名成员函数时,漏写了基类类名和作用域运算符,便会变成派生类调用自身,产生运行错误。
11. 定义抽象类对象是一种语法错误。