// ************************************************************ //
// 本文源自飞燕之家在线测评论坛http://yzfy.org/,转载清注明出处 //
// ************************************************************ //
代码调试技巧小集合(C语言描述,但C/C++/Pascal通用)
1.输入重定向
有不少人对自己提交到网站里得到的错误的结果而感到莫名其妙。
但有可能由于题目的输入数据巨多,要是手工输入将会非常累。
例如输入的数据可能多达成千上万。其实以下将要介绍的代码技巧,
对于做ACM题目较多的人来说,他(她)们也肯定会知道的。
本文算是在做普及工作吧。
首先,从手工转为自动方式,最显然的就是从文件读入的数据代替手工。
如果在源代码里希望把输入从屏幕输入定向到一个文件,
可以使用freopen函数(C/C++均支持此方法),以下为示例:
#include <stdio.h>
int main(void)
{
        freopen("in.txt","r",stdin); //输入从in.txt
        int a,b;
        while(scanf("%d%d", &a, &b)!=EOF)
        {
                printf("%d\n", a+b);
        }
        return 0;
}
这样你可以把题目的输入内容先保存的in.txt文件里,
在程序运行后看看屏幕输出,看是否和题目的样例输出一样。
从这里也可以看出,输入和输出是完全独立的,
您不必把所有输入或输出保存,直到程序全部计算完毕再输出,
这样会很浪费内存,我们也不希望你这样做。
你应当在你能够确定输出内容的时候就马上输出,能少占用内存就少用。
如果你希望本地调试成功的代码不用修改就可以直接提交到OJ系统上,
那你应该加上如下预处理(OJ系统通用标准,不支持这个特性的OJ就不合格):
#ifdef ONLINE_JUDGE  //判断是不是OJ系统上编译
#define FINPUT(file) 0 // 如果是,则不重定向到文件
#else
#define FINPUT(file) freopen(file,"r",stdin)
#endif
#include <stdio.h>
int main(void)
{
        FINPUT("in.txt"); //如果不是则输入从本地in.txt
        int a,b;
        while(scanf("%d%d", &a, &b)!=EOF)
        {
                printf("%d\n", a+b);
        }
        return 0;
}
如果你懂得命令行下运行一个程序,那么你可以不用修改源代码,
假设你的代码所生成的程序名是temp.exe,在命令行下运行:
temp.exe<in.txt
一样实现了相同的功能。
如果程序输出内容过多,你需要保存下来分析的话,那么还可以使用输出重定向。
如上方法,你也可以定义这样一个宏:
        #define FOUTPUT(file) freopen(file,"w",stdout)
如果输入输出均需要重定向,上面的代码可以改写为:
#ifdef ONLINE_JUDGE  //判断是不是OJ系统上编译
#define FINPUT(file)  0 // 如果是,则不重定向到文件
#define FOUTPUT(file) 0
#else
#define FINPUT(file)  freopen(file,"r",stdin)
#define FOUTPUT(file) freopen(file,"w",stdout)
#endif
#include <stdio.h>
int main(void)
{
        FINPUT("in.txt"); //如果不是则输入从本地in.txt
        FOUTPUT("out.txt");
        int a,b;
        while(scanf("%d%d", &a, &b)!=EOF)
        {
                printf("%d\n", a+b);
        }
        return 0;
}
在命令行下则可以:
temp.exe <in.txt >out.txt

2.断言和运行时错误捕获
断言对于初学者来说,可能是一个很新鲜的名词。
但这个东西对于软件调试来说有一个非常有用的东西,
不过使用的时候也得小心,不正确的使用甚至会适得其反。
首先,断言就是在逻辑上,你认为一定会得到的结果,
例如你假定内存分配一定成功,那么返回值一定不为NULL,
在你包含了头文件assert.h或者cassert后,就可以使用
assert(exp);
exp是你需要断言的表达式,bool类型,当exp为true的时候,
断言成功,程序继续执行,否则程序强制停止,并且发出警告。
这样你就可以明确得知程序发生了逻辑问题,必须进行修改。
但问题就在于,如果你直接使用assert(exp)这个函数,
那么这个断言不管在什么情况下都会编译进执行文件,
如果提交到OJ上,并且断言在内循环里,就显得这个断言会占用相当的时间。
如果我们不希望发布正式版本的软件或者提交代码时去掉这个断言以提升速度,
我们又可以用宏封装一下:
#ifdef ONLINE_JUDGE  //判断是不是OJ系统,非OJ系统调试可另起名字
#define ASSERT_LEVEL 1
#else
#define ASSERT_LEVEL 0
#endif
#if (ASSERT_LEVEL>=1)
#define ASSERT(exp) _assert(#exp, __FILE__, __LINE__)
#else
#define ASSERT(exp) 0
#endif
double foo(int n) //计算阶乘
{
        ASSERT(n>=0);
        return n*foo(n-1);
}
#include <stdio.h>
int main(void)
{
        int n=10;
        printf("%d\n", foo(n));
        return 0;
}
以上为一个错误递归算阶乘的程序示例,运行一下你就知道断言的威力了。
那个foo函数应当改为:
double foo(int n) //计算阶乘
{
        ASSERT(n>=0);
        if(n==0)return 1;
        return n*foo(n-1);
}
使用断言还有很多技巧和需要注意的东西,这里暂不多说,先自己体会体会吧。

关于运行时错误捕获,很多人马上就想到了C++的try。但事实上,
这种方法不一定能把异常都捕获,但在OJ系统里面,
你任何一个没有进行处理的异常的抛出都会导致RE(注意main函数返回非0也RE),
尽管有些异常不会对运行结果有影响,操作系统也会忽略掉,
于是一般运行的时候用户也无法发现已经出现异常。
同样,VC也是MS的产品,连操作系统都忽略的异常,用它去调试同样也忽略,
你不能依赖VC调试器得到所有异常的信息,
所以你不要以为VC上调试没有出现任何异常信息就以为那真的是正确的代码,
有可能是系统忽略掉,也有可能是你自己的测试用的数据没有触发它。
对于这个问题目前本人也没有较好的解决办法,所以还是建议你,
养成良好的编程习惯,适当的地方就加上断言,以增加异常被捕获的机率,
这样就更容易发现出错的地方。

转载于:https://www.cnblogs.com/RootJie/archive/2012/01/22/2328785.html

代码调试技巧小集合(雨中飞燕出品)相关推荐

  1. 代码调试技巧小集合(C语言描述,但C/C++/Pascal通用)

    本文源自飞燕之家在线测评论坛http://yzfy.org/,转载清注明出处 1.输入重定向 有不少人对自己提交到网站里得到的错误的结果而感到莫名其妙. 但有可能由于题目的输入数据巨多,要是手工输入将 ...

  2. 转:Python 代码调试技巧

    Python 代码调试技巧 转载于:https://www.cnblogs.com/kira2will/p/4254754.html

  3. 代码调试技巧【OI缩水版】

    1 小黄鸭调试法 来自维基:小黄鸭调试法是软件工程中使用的调试代码方法之一. 就是在程序的调试.纠错或测试过程中,耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感. 2 输出中间值 在关键位置输出值 ...

  4. 【Android 逆向】代码调试器开发 ( 使用 NDK 中的 ndk-build + Android.mk 编译 Android 平台的代码调试器可执行应用 )

    文章目录 一.Android 平台代码调试器代码 二.Android.mk 构建脚本内容 三.Application.mk 构建脚本内容 四.正式编译 五.博客资源 一.Android 平台代码调试器 ...

  5. VSCode插件、快捷键及代码调试技巧

    vscode基本使用 快捷键 Ctrl + Shift + P 打开命令面板 Ctrl + Shift + ~ 打开vscode的终端 F5 开始调试 F12 Go to Define Ctrl + ...

  6. IDEA中JAVA代码调试技巧

    提示:以下debug调试方式仅适用于在IDEA中使用 文章目录 前言 一.条件断点调试 二.回到"上一步"调试 三.多线程调试 四.远程调试 (1)项目启动时,先允许远程调试: ( ...

  7. 【转】Python 代码调试技巧

    原文网址:http://www.ibm.com/developerworks/cn/linux/l-cn-pythondebugger/ Debug 对于任何开发人员都是一项非常重要的技能,它能够帮助 ...

  8. Java与JS代码调试技巧

    为什么80%的码农都做不了架构师?>>>    断点的分类,断点可以到到类名上,变量行上,方法名上.       java源码上可以打断点,断点打到方法头上,编译的时候断点信息不会被 ...

  9. java 调试js_Java与JS代码调试技巧

    断点的分类,断点可以到到类名上,变量行上,方法名上. java源码上可以打断点,断点打到方法头上,编译的时候断点信息不会被去除掉,编译后的class文件 在debug模式下运行,可以触发断点,挂起线程 ...

最新文章

  1. android gradle tools 3.X 中依赖,implement、api 和compile区别
  2. 机器学习算法加强——聚类实践
  3. ruby 执行函数_Ruby at()函数
  4. JAVA基础整理-6.Java数据类型
  5. AndroidStudio_从Eclipse到AndroidStudio开发工具_认识使用AndroidStudio_导入用eclipse开发的工程---Android原生开发工作笔记69
  6. python连接数据库oracle_python 连接oracle数据库:cx_Oracle
  7. java用 拼接字符串的原理_Java String 拼接字符串原理详解
  8. Kubernetes 弃用 Docker刷爆了网络,我们公司也慌了!
  9. 边工作边刷题:70天一遍leetcode: day 34-1
  10. php生成静态页的方法
  11. debian10将系统软件包和docker的软件源改成国内源
  12. MFC中有关鼠标单击双击响应的问题
  13. 拉丁超立方抽样方法 LHS
  14. 外网访问内网FTP服务器
  15. 介绍lookup函数十大常用的用法
  16. layui后台管理框架应用
  17. DIY自制STC单片机开发板
  18. VS2017 打包exe,msi文件
  19. Android之——实现应用卸载功能
  20. 做生意和追女人,“绝色真经”!

热门文章

  1. 数字IC测试领域发展简介
  2. 基于NDK、C++、FFmpeg的android视频播放器开发实战-夏曹俊-专题视频课程
  3. 注塑模具外观设计有哪些特点?
  4. 量化投资学习——全球交易所交易时间
  5. 【开学季】如何过好大学最后一年
  6. 用本地光盘建yum仓库安装Gcc
  7. 在3dmax里仿unity的Unlit/Texture shader并渲染
  8. snort mysql_linux入侵检测系统snort安装配置
  9. MySQL从删库到跑路(11):update——修改身高、颜值,人不风流枉少年
  10. 听说的一个治疗眼皮跳的小偏方