c语言按钮事件,《C语言编程初学者指南》一1.8 调试C程序

本节书摘来自异步社区《C语言编程初学者指南》一书中的第1章,第1.8节,作者【美】Keith Davenport(达文波特) , M1ichael Vine(维恩),更多章节内容可以访问云栖社区“异步社区”公众号查看

1.8 调试C程序

如果你的程序编译了,然后退出了或在执行中出现异常,程序中一定存在一个错误(一个bug)。我们将要花费很多的时间来找到并删除这些bug。本小节介绍了帮助你开始这一工作的一些技巧。然而,请记住,调试是计算机科学,同样也是一门艺术,当然,你的编程实践越多,调试也就变得越容易!往往一个程序编译和执行得很好,但总是产生你意料之外的或者不想要的结果。例如,如下的程序的编译和执行没有错误,但是输出却是无法读懂的,或者说不是我所期望的,其输出如图1.11所示。include int main(){ printf("Chapter 1 - Getting Started with C Programming"); printf("This is an example of a format bug."); printf("The format issue can be corrected by using"); printf(" the

and \ escape sequences"); return 0;}

829acbc425da980e10c30afcc6a73be8.png

图1.11 错误的格式化

你能看到格式有什么问题吗?漏掉了什么,应该在哪里进行修改?下一段代码及其输出如图1.12所示,它通过放置相应的转义序列而改正了格式。

e1cd59fb94c1c7d625ad9b1348169759.png

图1.12 通过在需要的地方添加n和转义序列,改正了格式include int main(){ printf("Chapter 1 - Getting Started with C Programming

"); printf("This is an example of a format bug.

"); printf("The format issue can be corrected by using"); printf(" the \n and \\ escape sequences"); return 0;}

格式问题是编程初学者经常遇到的问题。通常,可以通过熟练使用printf()函数和各种转义序列来快速地解决这些问题。

另一类常见的bug是逻辑错误,包括循环在期望退出的时候没有退出、数学计算公式的错误或者可能是一次有瑕疵的相等性测试(条件)。调试逻辑错误的第一个步骤是,找到程序bug存在的第一行代码。做到这一点的一种方式是使用打印语句,也就是在整个代码中分散地使用printf()函数。例如,可以在源代码中做一些如下的事情:anyFunction(int x, int y){ printf("Entering anyFunction()

"); fflush(stdout); —— lots of your code here ——— printf("Exiting anyFunction()

"); fflush(stdout);}

fflush()函数确保了printf语句的结果会立即发送到屏幕,并且如果你想要使用printf()进行调试的话,应该使用fflush()函数。传递给fflush()函数的stdout参数是标准输出,这通常是计算机屏幕。

在将发生逻辑错误的地方的范围缩窄到代码行或函数之后,下一步就是搞清楚你的变量在彼时的值。还是可以使用printf()函数来打印出变量值,这对于确定非正常的程序行为的源头有很大的帮助。第2章将详细介绍使用printf()函数来显示变量值。

记住,当你修复了任何的bug之后,必须重新编译程序,运行它,并且如果必要的话,再次进行调试。

作为程序员新手,你经常会遇到的是编译错误,而不是逻辑错误,而编译错误通常是语法问题所导致的,例如漏掉了标识符和终结符,或者使用了无效的指令、转义序列或注释语句块等语法问题。

调试编译错误可能会令人沮丧,特别是当你在计算机屏幕上看到50条或者更多的错误的时候。需要记住的重要的一点是,程序开始处的一个错误,可能在编译的时候导致一系列层叠性的错误。因此,开始调试编译错误的最好的地方,就是错误列表中的第一个错误。在接下来的几个小节中,我们将介绍在刚开始编写C程序的时候的一些较为常见的编译错误。

1.8.1 常见错误之1:漏掉程序语句块标识符

如果忘记了插入一个开始或对应的结束程序语句块的标识符({和}),你将会看到如图1.13所示的错误消息。在下面的示例中,我们故意在main()函数名的后面,漏掉开始程序语句块标识符({}。include int main() printf("Welcome to C Programming

");return 0;}

873b4967f7bb2e7b26d7a426693bd102.png

图1.13 由于漏掉了程序语句块标识符而导致的错误

由于忘记使用开始程序语句块标识符({),导致了很多的错误,如图1.13所示。当调试编译错误的时候,记住要从第1个错误开始,如下所示,它告诉你就在printf()函数之前有一个错误。你将会发现,解决了第1个错误之后,也就更正了很多甚至是所有剩下的错误。hello.c:5:2: error: expected declaration specifiers before 'printf' printf("Welcome to C Programming

"); ^

技巧

为了帮助你找到一个错误的位置,编译器试图向你显示捕获到错误的代码的行号。在前面的示例中,hello.c:5:是告诉你在hello.c源代码的第 5 行捕获到了错误。注意,编译器在统计行号的时候,将空行和代码行都算在内。

尽管编译器错误指向了printf开始处,但重要的是要知道,可能并不是printf而是在它之前的某处出现了错误,在这个例子中,是因为漏掉了语句块标识符。

1.8.2 常见错误之2:漏掉语句终结符

图1.13展示了由几个常见场景所导致的一条常见错误消息。这种类型的错误可能会由于几个原因而导致。除了漏掉程序语句块的缩进,漏掉了语句终结符(分号)也可能会导致解析错误。

图1.14展示了如下程序中的一个bug。你能看出这个bug隐藏在哪里吗?include int main(){ printf("Welcome to C Programming

") return 0;}

1b0c48762acfcb729213100faed152d8.png

图1.14 漏掉终结符导致的错误

由于C编译器不能够确定一条程序语句(如一条打印语句)到哪里结束,导致了解析错误。在图1.14所示的例子中,C编译器(gcc)告诉你,它期望在第6行的return语句之前有一个分号(语句终结符)。

1.8.3 常见错误之3:无效的预处理器指令

如果输入了一条无效的预处理器指令,例如,把库的名称拼写错了,你将会接收到一条如图1.15所示的错误消息。

f491d8dce88748132297368b027e97df.png

图1.15 无效的预处理器指令导致错误

在如下的程序语句块中,预处理器指令中的库名称拼写错了,导致了如图1.15所示的错误消息。你能看出错误吗?include int main(){ printf("Welcome to C Programming

"); return 0;}

由于不存在库文件sdio.h,导致了这个错误。标准输入输出库的名称应该是stdio.h。

1.8.4 常见错误之4:无效的转义序列

在使用转义序列的时候,常常会使用无效的字符或者无效的字符序列。例如,图1.16展示了一个无效的转义序列所导致的错误。gcc 编译器更为具体地指出了这个错误,如图 1.16所示。特别是,它指出错误在第7行,并且指明这是一个未知的转义序列。

432c3d6c6a72726a02f2f87113f2f0a9.png

图1.16 无效的转义序列导致的错误

你能够找出如下的程序中的无效的转义序列吗?include int main(){ printf("Welcome to C Programmingm");return 0;}

用诸如n这样的一个有效的序列,来替代无效的转义序列m,就可以改正这个问题。

1.8.5 常见错误之5:无效的注释语句块

正如本章前面的1.3节所提到的,无效的注释语句块也会导致编译错误,如图1.17所示。include int main(){ */ This demonstrates a common error with comment blocks /* printf("Welcome to C Programming

"); return 0;}

f8ff65c0170d0bc8dafefbae77d6238c.png

图1.17 无效的注释语句块导致错误

对于注释语句块进行一个简单的修改,如下所示,就可以解决这个问题,并能够让程序成功地编译。/* This corrects the previous comment block error

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值