C:字符比较失败

时间:2013-11-21 03:59:18

标签: c entab-detab

成功运行一个entabulator后,我的详细设备将不会接受应该退出while循环的字符比较。在尝试“0(tab)8(enter)(ctrl + D)”作为输入之后,选项卡被正确地写为空格,但是在rp递增到指向8之后,应该读取8的while循环将不会退出而我得到一个段错误。这是代码:

#include <string.h>
#include <stdio.h>
#define MAXLINE 100
char doc[9001];
main(int argc, char *argv[])
{
    int max = 0;
    char *rp = doc;
    char *wp = rp;
    char *tf = wp;
    char *lp = doc;

    while ((*(rp++) = getchar()) != EOF);
    *--rp = '\0';
    rp = doc;
    j = 0;
    while  ( (*rp != '\0') && (argc == 1)) {
        if (*rp == '\n') {
            lp = rp + 1;
            *wp++ = *rp++;
        }

        while( (*rp != '\t') && (*rp != '\0') && (*rp != '\n') ) { /*this loops after a tab*/
            *wp++ = *rp++;
        }
        if (*rp == '\t') {
            rp++;
            tf = lp + ((((wp - lp) / 8) + 1) * 8);
            while ((tf - wp) != 0) 
                *wp++ = 's';
        }
    }
    if (*rp == '\0')    
        *wp = '\0';
    printf("%s\n", doc);
}

2 个答案:

答案 0 :(得分:1)

初始输入循环有一些尚未探索的问题。

即使为它分配了9001个字节,也不应该冒着溢出缓冲区的风险。这就是病毒和事物侵入程序的方式。此外,您遇到问题,因为您正在将字符与EOF进行比较。不幸的是,getchar()返回int:它必须因为它返回任何有效字符值作为正值,EOF作为负值(通常为-1,但没有任何保证该值)。

因此,您可以更安全地编写该循环,并且明确地说:

char *end = doc + sizeof(doc) - 1;
int c;

while (rp < end && (c = getchar()) != EOF)
    *rp++ = c;
*rp = '\0';

按照你的循环编写,会发生以下两种不良事件之一:

  • 如果char是无符号类型,那么您将永远不会检测到EOF。
  • 如果char是签名类型,那么当您读取有效字符时(通常是ÿ,y-umlaut,带有DIAERESIS的拉丁文小写字母,U + 00FF),您将检测到EOF。

两者都不好。上面的代码避免了这两个问题,无需知道普通char是签名还是未签名。

传统上,如果你有一个空的循环体,你可以通过将分号放在一条线上来强调这一点。在while条件之后,许多无限循环是由分散的分号引起的;通过将分号放在下一行,你强调它是有意的,而不是偶然的。

while ((*(rp++) = getchar()) != EOF);

while ((*(rp++) = getchar()) != EOF)
    ;

答案 1 :(得分:0)

我的感觉是,下面的循环进入无限循环。

while( (*rp != '\t') && (*rp != '\0') && (*rp != '\n') ) { /*this loops after a tab*/
    *wp++ = *rp++;

这是因为,您正在检查rp!= '\t'等等,但此处

if (*rp == '\t') 
{
    rp++;
    tf = lp + ((((wp - lp) / 8) + 1) * 8);
    while ((tf - wp) != 0) 
        *wp++ = 's';
}

您正在使用char doc填充's'数组,并且还在写'\t',所以上面的循环将变为无限。