我刚刚购买了K& R的“C编程语言”,并尽我所能在其中进行练习(如果你知道这本书,那就是练习1.20)。
该程序用于从键盘输入,并将制表符转换为适当数量的空格,由TABLENGTH指定。
代码如下。当我尝试运行它时,我会出现分段错误。
detab.c:
#include <stdio.h>
#define TABLENGTH 8
#define MAXLINE 1000
int getline(char line[], int len);
int main()
{
char line[MAXLINE];
int length;
while((length = getline(line, MAXLINE)) > 0) {
printf("%s");
}
}
int getline(char line[], int len)
{
int i = 0;
int c;
for(i = 0; i < (MAXLINE - 1) &&
((c = getchar()) != EOF && c != '\n'); i++) {
// if c is tab, replace with spaces
if(c == '\t') {
while((TABLENGTH - (i % TABLENGTH)) != 0) {
line[i] = ' ';
i++;
}
i--;
continue;
}
}
line[i] = c;
}
if(c == '\n') {
line[i] = c;
i++;
}
line[i] = '\0';
return i;
}
答案 0 :(得分:6)
经典初学者错误1A:getchar()
返回int
,因为EOF
不适合char
。
我还认为你有一个索引问题,因为如果你找到一个标签,你会在空格插入循环中增加i
,然后for
循环会再次增加i
,在字符串中留下古怪。这可能会导致缓冲区溢出和您看到的崩溃。
请注意,空格插入循环不会针对i
检查MAXLINE
。
答案 1 :(得分:2)
致电printf
printf("%s");
可能是段错误的原因。它将尝试将堆栈上的某些任意数据解释为指向0终止char
数组的指针。
对于段错误,某种方式是'\t'
:
if(c == '\t') {
while((TABLENGTH - (i % TABLENGTH)) != 0) {
line[i] = ' ';
i++;
}
i--;
continue;
}
自i >= 0
和TABLENGTH > 0
以来,您始终拥有0 <= (i % TABLENGTH) < TABLENGTH
,因此无论何时遇到标签,您都会输入一个无限循环,在line
之外添加空格,超出分配的空间当它试图在进程内存之外写入空格或写入内存的只读部分时,迟早会导致段错误。一个简单但不是很优雅的修复方法是将循环改为
if (c == '\t') {
do {
line[i] = ' ';
++i;
}while(((TABLENGTH - (i % TABLENGTH)) % TABLENGTH) != 0);
--i;
continue;
}
另一种解决方法可能是使用单独的计数器或switch
使用直通。