2013-11-21 99 views
0

在成功运行entabulator之后,我的detabulator将不会选择应该退出while循环的字符比较。将“0(制表符)8(进入)(ctrl + D)”作为输入后,制表符被正确写入空格,但rp递增后指向8,应读取8的while循环不会退出我得到一个seg故障。这里的代码:C:字符比较失败

#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); 
} 

回答

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'; 
} 

你用炭's'填充doc阵列和这比写'\t'也,所以上面的循环将会无限。

+0

你说得对,我看不懂的输入,因为我已经覆盖它。谢谢。 – user3003268

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-变音符号,带有DIAERESIS的拉丁小字母Y,U + 00FF),你将检测到EOF。

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

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

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

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

您分析问题的方式非常棒! – 2013-11-21 05:29:52

+0

感谢您向我展示代码失败的地方。显然我需要记住可移植性和安全性问题。 – user3003268