1、C 语言常见错误及解决方法(注:红色粗体是常见的错误,请大家检查自己的程序,并注意尽量不要犯这些常见的错误。其余它体是避免错误的方法和正确的写法)一、基础知识和数据类型、表达式1、 拼写错误,尤其是 include,main,void,float 等词。C 语言的 32 个关键字与基本含义如下:double :声明双精度变量或函数 int: 声明整型变量或函数char :声明字符型变量或函数float:声明浮点型变量或函数void :声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)auto :声明自动变量 一般不使用 struct:声明结构体变量或函数 break:跳出当前循环
2、else :条件语句否定分支(与 if 连用) long :声明长整型变量或函数 switch :用于开关语句 case:开关语句分支 enum :声明枚举类型 register:声明积存器变量 typedef:用以给数据类型取别名(当然还有其他作用) extern:声明变量是在其他文件正声明(也可以看做是引用变量) return :子程序返回语句(可以带参数,也看不带参数) union:声明联合数据类型 const :声明只读变量 short :声明短整型变量或函数 unsigned:声明无符号类型变量或函数 continue:结束当前循环,开始下一轮循环 for:一种循环语句(可意会不可言
3、传) signed:生命有符号类型变量或函数 default:开关语句中的“其他 ”分支 goto:无条件跳转语句 sizeof:计算数据类型长度 volatile:说明变量在程序执行中可被隐含地改变 do :循环语句的循环体 while :循环语句的循环条件 static :声明静态变量 if:条件语句2、 , , () , , “”不配对。解决这个问题最好的方法就是每当写这些符号的时候就先写成一对,然后再在中间加内容。3、 忘记在语句的末尾加分号,或在预处理命令后多加分号。记住:每一个语句的后边都要加分号,而预处理命令并不是语句,所以不加分号,他们必须每行一条,不能把多个命令写在一行。4、
4、 混淆/和;注释对应的符号是/* */,而转义字符是以开头,除号是 /。5、 printf()和 scanf()的参数设置有误,主要表现在以下几方面: 类型不匹配的问题。 (例如:有 float a=3.5,但输出的时候 printf(“a=%d”,a);则屏幕上会显示出 a=0.00000 或者提示其它运行错误) 。基本原则是:float 对应%f, int 对应%d, char 对应%c。 个数不匹配。无论是哪个函数,都可以有 n 个参数,第一个永远是“”括起来的内容,表示输出格式。剩下的 n-1 个是输出的变量或者输入的变量的地址。需要注意的是,如果后边有 n-1 个参数,那么前边一定对
5、应 n-1 个%f 一类的格式说明符。 scanf()中变量前忘了加 。记住:scanf()中变量前要有 (但后边学到的字符数组名和指针前不用加) 6、 定义标识符的时候经常出现使用非法字符的情况,例如:标识符中不能用空格,也就是说不能有这样的定义:int radium of circle;一般情况下可用下划线将三个单词连接在一起。7、 在使用变量前未定义,或未初始化。例如:若下边的 sum 未定义,则在编译时会提示相应的错误信息,而若未初始化为 0,则求和的结果一定是错误的。void main() int I,a10, sum=0; /*只要下边要用,这个定义就必须要有,一般情况下也要有初始
6、值*/for(I=0;I。二、流程控制1、 丢掉语句结束标记“;” ,尤其是 for 语句中表达式后或 do-while 语句后的分号,或在预处理命令后边、while()后、for()后加“;” ;2、 If 语句或循环语句中逻辑表达式或关系表达式书写错误。一定要注意 C 语言的条件与数学表达式的区别(例如我们数学中经常写到的 0x9,在 C 语言中应该写成x=05、 随意修改循环控制变量 i 的值,导致循环次数的改变,尤其是当循环有嵌套时。在循环体中,不要将循环控制变量进行另外的改变。6、 分不清什么情况下用双重循环,什么情况下用两个控制变量写成一重循环。当 I 不变,j 又循环一遍的时候用
7、双重循环。当 I,j 同时变化的时候用一重循环,此时,循环控制变量有两个,但条件只写一个就可以,因为另一个总是进行相应的变化的。7、 忽略循环体与循环控制变量的关系。其实,很多情况下,循环控制变量都在循环体中起到非常重要的作用。应该利用上这种关系。三、数组与指针1、 字符串的输入有错误:主要表现在使用 scanf()或 gets()时加了,或输入字符串时用循环, (这样的话,字符个数无论多长,都不会为自动加0,将来引用的时候也就不能以字符串的形式引用。 )2、 对字符串的处理中,循环条件仍然写成 IN。由于字符串是不定长的,所以循环条件一般为 strI!=0 或 Istrlen(str)3、
8、而输入所对应的变量是指针时(常见的有:输入的变量是字符数组名或指向字符串的指针)不能加。4、 指针定义后未赋值就引用。如果在定义时不知道赋什么值,可以用 p=NULL 赋初值,以避免引起的灾难性错误。5、 分不清 p 和p 。前者是指针,即地址,后者表示指针所间接引用的数据,但如果是二级指针或多级指针,取*以后得到的仍然可能是地址。四、函数1、 函数定义的时候,函数头部加分号,而函数声明的地方忘了加分号2、 函数实参格式不对,主要表现在:给出实参时,多给出数组类型,或者,形参是数组int a;的时候,给出的 a或 aI.3、 递归时忘了设置边界条件,这样易造成死循环调用。4、使用函数之前未声明
9、(包括 C 库函数的声明) 。建议大家,将所定义的一切函数都在程序开始的预处理命令后加上函数原型的声明,这样做不仅可以避免错误,而且整个程序的结构看起来更清楚。五、结构体共用体1、 结构体类型定义有误,主要表现在:结构体类型里还有嵌套的时候,忘记了成员名称。(例如:下边的例子中,有些同学经常忽略了 birthday)2、 结构体类型名和结构体变量名混淆。例如:struct STU.Struct dataint year,month,day;birthday;struct STU a; struct STU 是类型名称,而且不分配空间,且不能直接引用。只有定义了结构体类型 struct STU
10、的变量 a 以后,才为 a 分配相应的内存空间,引用时也要是 a.?3、 结构体变量的成员引用不正确,尤其是当结构体类型中有嵌套定义的时候。一定要一级一级的引用。例如:上边的例子:如果引用其中的年的话,一定是 a.birthday.year. 不能直接 a.year.4、 对结构体变量进行输入输出的时候,整体输入或整体输出。除作为函数参数外,不能对结构体变量整体操作,只能一个成员一个成员地输入、输出。5、 不理解共用体的“共占内存” 。对共用体中的成员变量,一定要靠一个标记区别它们,并分别按不同类型引用它们。切记:共用体变量不能做函数形参。六、文件1、 使用之前没有打开文件,使用之后没有关闭文
11、件。2、 相关函数的调用格式有误。请一定注意实参的类型、顺序、个数上与函数原型(或函数声明)的一致。Visual C+6.0 中的调试工具使用入门一、程序开发过程中出现的错误类型我们在进行程序设计时,不可避免地会犯错误。程序中的错误可以分为三类:编译错误、运行时错误和逻辑错误。编译错误(Compile errors)又称为编译时错误(Compiling-time errors): 是由于错误的编码产生的。例如关键字拼写错误、将中文标点符号当成英文符号使用、遗漏了某些必要的标点符号或者使用了一个没有定义的标识符。编译错误一般都是语法错误,当编译器对程序进行语法检查时,都能发现这些错误,并能够指出
12、产生错误的位置(标出行号) 。我们可以根据编译出错信息指出的行号找到对应的源代码行改正错误,重新编译源程序。只有当所有的编译错误被改正后,才能通过编译检查,产生目标代码文件。改正编译错误的关键是要能正确理解编译器给出的编译错误信息。VC+ 环境中的编译、链接错误信息是用英文表示的。对于英文基础薄弱的读者,可以参考本实验指导书后面的“VC+编译、链接常见错误和警告信息中英文对照” 。通常情况下,一个语法错误可能产生多条编译错误信息,这是由于株连错误造成的,建议读者在处理编译错误时,找到第一个出现错误的位置改正后重新编译。这样能够避免被株连错误迷惑。值得指出的是,现在大部分编译器对错误的定位不精确
13、,如果在编译器指出的行没有发现错误,应该向前查找错误。例如,当提示第 10 行发生错误时,如果在第10 行没有发现错误,请从第 10 行开始往前查找错误并修改之。运行时错误(Run-time errors)是在程序的运行阶段出现的,当运行环境检测到程序的某些操作无法执行,例如除数为零时,就会出现运行时错误。当运行环境检测到程序的某些操作是被禁止的,也会产生运行时错误。例如,访问数组时超越数组的边界,空指针引用(NULL pointer assignment,空指针赋值,即有指针未赋具体地址就使用了)等等。逻辑错误(Logic errors):当程序没有按照程序员的意图执行时,就表明程序中存在逻
14、辑错误。一个应用程序可能既没有语法错误,运行时也没有执行任何无效的操作,但是有可能产生错误的结果,这种错误结果一般都是程序内部的逻辑错误造成的。只有通过测试应用程序并分析它产生的结果,我们才能核实应用程序是否正确地执行了。当然,如果输入了错误的或者无效的数据,执行程序后肯定也得不到正确的结果。软件行业中有一句名言“输入的是垃圾,输出也是垃圾。(Garbage in, garbage out.)”因此,一般的实用程序还需要对输入数据的正确性和有效性进行检验。很显然,必须找出并改正程序中的错误,才能得到正确的执行结果。对于语法错误,我们可以根据编译错误信息指出的位置和错误原因来改正错误。请记住:编
15、译器不能发现程序中的逻辑错误和运行时错误。我们可以通过仔细阅读源程序来发现逻辑错误,还可以借助开发环境中提供的调试工具来查找程序中的逻辑错误和运行时错误。所谓调试(debug)就是定位程序中的错误并改正错误的过程。为了帮助程序员找出并改正程序中的错误,微软公司在 Visual C+6.0 环境中集成了调试器( debugger), 调试器就是调试工具(debugging tools) 。下面我们将介绍 Visual C+6.0 中的调试工具及其使用方法。二、Visual C+6.0 中的调试工具简介Visual C+6.0 环境中的调试工具功能十分强大,既可以支持 C+语言源代码级的调试,也可
16、以支持汇编语言级和机器语言级的调试。我们在此仅介绍 C+语言源代码级的调试。Visual C+6.0 中的调试器允许我们在程序中设置断点(breakpoint) ,单步运行程序(step) ,运行到光标处(run to cursor) ,监视(watch)变量值等等。断点是我们通过调试器在源程序中设置的一个位置。当运行到断点时,程序中断执行,这样我们可以观察断点处各个相关变量的值,通过变量的值分析、判断到断点处时程序的执行是否符合我们的期望。断点是最常用、最基本的技巧。在 Visual C+6.0 中设置断点的最简单方法就是通过点击 Build 工具条上的插入断点按钮(手掌形状按钮)或者按键盘
17、上的功能键 F9。如图 13 所示,图 13 在源程序中设置断点图 14 开始调试程序一次可以设置多个断点,设置了断点之后,就可以通过点击 Build 工具条上的开始调试程序按钮或者按键盘上的功能键 F5 开始调试程序。如图 14 所示,插入/移去断点按钮小红点表示断点按功能键 F9 也能在当前行插入断点开始调试程序按钮图 15 程序运行至断点处暂停当程序运行至断点处会暂停,我们可以在断点暂停处通过 Watch 窗口观察有关变量的值,如图 15 所示。如果 Watch 窗口没有显示我们所关心的变量,可以自行添加。另外还有一个更简单的观看变量的值方法:当程序运行到断点时,把鼠标光标移动到源程序中
18、的某个变量上,停留一秒钟就可以看到这个变量的值。移去断点:把键盘光标(插入符)移动到断点所在的行,再次按功能键 F9 就可以移去断点。也可以通过点击 Build 工具条上的插入/移去断点按钮(手掌形状按钮)取消断点。单步运行程序就是每一次只执行一条语句就暂停。Visual C+6.0 中的调试工具提供三种单步运行方式:Step Into, Step Over, Step Out,如图 16 所示。Step Into 命令的快捷键是功能键 F11,Step Over 命令的快捷键是功能键 F10,Step Out 命令的快捷键是功能键Shift+F9。Run to Cursor(运行到光标处)命
19、令的快捷键是功能键 Ctrl+F10。程序运行至断点处暂停在断点暂停处可以通过Watch( 监视)窗口观察有关变量的值图 16 单步运行每次单步运行一条语句后,都可以通过 Watch(监视)窗口观察有关变量的值,或者将鼠标光标移动到源程序中的某个需要观察的变量上,停留一秒钟就可以看到这个变量的值,如图 17 所示。如果我们确认当前函数中没有错误时,可以使用 Step Out 命令快速地执行完毕当前的函数,暂停在该函数调用的下一条语句上。如果我们确认某一段源代码中没有错误时,可以将键盘光标(插入符)放置在这段代码的末尾处,使用 Run to Cursor(运行到光标处)命令快速地执行完毕这一段代
20、码,暂停在光标所在语句上。例如我们可以将键盘光标移动到 main 函数的结尾处,然后按功能键Ctrl+F10 执行 Run to Cursor 命令。这样程序将运行到结束处停止。单步运行,可以进入函数内部单步运行,不进入函数内部从当前函数调用中出来运行到光标处图 17 单步运行后观察相关变量的值需要停止调试程序时,可以执行 Stop Debugging(停止调试)命令,如图 18 所示。Stop Debugging 命令的快捷键是功能键 Shift+F5,Restart (重新开始调试程序)命令的快捷键是功能键 Ctrl+Shift+F5。Go (开始调试程序)命令的快捷键是功能键 F5。Go
21、 命令还可以使程序从当前语句运行到下一个断点处,如果后面没有断点,就运行到到程序的结尾。除了使用快捷键和 Debug(调试)菜单执行调试命令,还可以使用 Debug 工具条,如图 19 所示。使用工具条上的 QuickWatch 可以添加要观察的变量或者表达式。工具条上还有一些其他工具可以帮助我们查看 CPU 内部的寄存器(Registers) 、内存单元(Memory)和堆栈(Stack )的情况。Visual C+6.0 中的调试工具功能强大,在这里我们只介绍最基本的操作。当读者积累了一定的调试经验后可以继续学习调试工具的高级使用方法。最后要强调一点,当程序员对程序进行调试时,一定要理解程
22、序的算法,熟悉程序的结构和流程,准确估计变量和表达式的期望值。这样才能做出正确的分析和判断。调试的过程实质上是一个思考的过程。单步运行后,可以通过 Watch (监视)窗口观察有关变量的值将鼠标光标停留在变量上一秒钟,就可以看到这个变量的值图 18 停止调试命令等图 19 调试工具条停止调试命令重新开始调试程序命令开始调试程序命令调试工具条QuickWatch按钮VC+编译、链接常见错误和警告信息中英文对照1、fatal error C1010: unexpected end of file while looking for precompiled header directive。寻找预编
23、译头文件路径时遇到了不该遇到的文件尾。 (一般是没有#include “stdafx.h“) 2、fatal error C1083: Cannot open include file: R.h: No such file or directory不能打开包含文件“R.h”:没有这样的文件或目录。3、error C2011: C: class type redefinition类“C”重复定义。4、error C2018: unknown character 0xa3不认识的字符0xa3。 (一般是汉字或中文标点符号)5、error C2057: expected constant expre
24、ssion希望是常量表达式。 (一般出现在 switch 语句的 case 分支中)6、error C2065: IDD_MYDIALOG : undeclared identifier“IDD_MYDIALOG”:未声明过的标识符。7、error C2082: redefinition of formal parameter bReset函数参数“bReset”在函数体中重定义。8、error C2143: syntax error: missing : before 句法错误:“”前缺少 “:”。9、error C2146: syntax error : missing ; before
25、identifier dc句法错误:在“dc”前丢了“;” 。10、error C2196: case value 69 already used值 69 已经用过。 (一般出现在 switch 语句的 case 分支中)11、error C2509: OnTimer : member function not declared in CHelloView成员函数“OnTimer”没有在“CHelloView ”中声明。12、error C2511: reset: overloaded member function void (int) not found in B重载的函数“void re
26、set(int)”在类“B ”中找不到。13、error C2555: B:f1: overriding virtual function differs from A:f1 only by return type or calling convention 类 B 对类 A 中同名函数 f1 的重载仅根据返回值或调用约定上的区别。14、error C2660: SetTimer : function does not take 2 parameters“SetTimer”函数不传递 2 个参数。15、warning C4035: f: no return value f”函数 f没有返回值。
27、16、warning C4553: = = : operator has no effect; did you intend =?没有效果的运算符“= =” ;是否改为“= ”?17、warning C4700: local variable bReset used without having been initialized局部变量“bReset”没有初始化就使用。18、error C4716: CMyApp:InitInstance : must return a value“CMyApp:InitInstance”函数必须返回一个值。19、LINK : fatal error LNK1168: cannot open Debug/P1.exe for writing连接错误:不能打开 P1.exe 文件,以改写内容。 (一般是 P1.Exe 还在运行,未关闭)20、error LNK2001: unresolved external symbol “ 连接时发现没有实现的外部符号(没有定义的变量、没有定义的函数等) 。