成功运行一个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);
}
答案 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'
,所以上面的循环将变为无限。