学习资料|笔记|算法|转载|题解

去除多余空白字符的代码实例分析

凝神长老 · 11月25日 · 2016年 959次已读

转载

原文标题:《20161116 – 一次DEBUG的小结》

原文链接:http://www.starrylyc.com/wordpress/?p=77

原文作者:Summerfirefly

转载授权:

sp161125_010012


//本程序目的为去除一段文字开头和每行末尾的 Whitespace
//以及单词之间多余的 whitespace,仅保留第一个 whitespace
//ECNU OJ Problem 3167
#include <stdio.h>
int main()
{
    int i,n;
    char a[1000],x;
    i=0;
    scanf("%c",&x);
    for (;x==' '||x=='\t'||x=='\n';)
        scanf ("%c",&x);
    a[i]=x;
    i++;
    while (scanf("%c",&x)!=EOF)
    {
        if ((x==' '||x=='\t'||x=='\n')&&a[i-1]!=' '&&a[i-1]!='\t'&&a[i-1]!='\n')
        {
            a[i]=x;
            i++;
        }
        if(x!=' '&&x!='\t'&&x!='\n')
        {
            a[i]=x;
            i++;
        }
    }
    if(a[i-1]==' '||a[i-1]=='\t'||a[i-1]=='\n')
    {
        i=i-1;
        a[i]='\0';
    }
    else
        a[i]='\0';
    for (n=0;n<i;n++)
        printf ("%c",a[n]);
    return 0;
}

以上为一位同学于 20161116 晚发来的一段代码,EOJ 测试 Wrong Answer,本地测试通过(注:这里的本地测试就是本次总结的重点之一)无法理解便交给我,整体 debug 用时一个多小时(注:总结重点之二,debug 的方式要注意)

拿到代码后第一步在 Code::Blocks下进行 debug 测试,用单行数据进行测试,完全无误(事后证明确实无误),用文件重定向在终端模拟OJ的文件测试多行数据,无误,但事后证明这里的测试出现严重的失误,对于可能的输入方式没有考虑完全,导致浪费大量时间

经过长时间的不全面的测试数据进行测试后想到存在如下情况:

Input:

\t\taaaaa     aaa\t      \t\n

aa        a\n

EOF

即多行数据,且非末行的末尾换行符之前连接一串 whitespace,上述错误的代码输出结果为

Output:

aaaaa aaa\taa a\n

显然不正确,本应输出两行,最终只有一行,问题出在Line 19的判断条件上,由于本算法是一次性处理整个文件,而又没有考虑到连续多个空白字符之后紧跟换行符的情况,导致 \t\t\n 这类型序列只存入了 \t 而丢弃了 \n,导致行的缺失,debug 时同样没有注意到这一点,白白浪费大量时间

总结:

  1. 本地测试时一定要将所有输入的可能性考虑完全
  2. 考虑可能的输入时一定要结合自己的算法的特点,如本例,由于我自己写的算法是逐行处理,将整个文件作为类似二维的处理,所有换行符都在一行的末尾,因此不存在丢失应有的换行符的问题,但上述代码为整体处理,类似在一维上处理多行文本,换行符不一定在数组末尾。如果仍然按照单行处理的思路,即两个单词之间的 whitespace 只保留第一个,来一次性处理多行文本,就会有丢失换行符的可能性。

Debug 是一项非常重要的技能!非常重要!同时 Debug 的时候一定要注意方法和以前的经验教训,否则将会浪费大量时间。

全面的测试数据将为程序的调试节省大量时间

2016-11-17 Summerfirefly

0 0 投票
文章评分
订阅评论动态
提醒
guest
2 评论
最新
最旧 得票最多
行内反馈
查看所有评论
sscjwdyzdw
sscjwdyzdw
2016年12月8日 15:21

这题难主要是因为末尾就算有whitespace输出也看不到,所以不如假定n t ‘ ‘是实在的abc,然后输出会比较容易的看出程序问题