0

我刚买了K&R的《The C programming language》,并尽我所能做其中的练习(如果你知道这本书,那就是练习1.20)。

该程序旨在从键盘获取输入,并将制表符转换为由 TABLEENGTH 指定的适当数量的空格。

代码如下。当我尝试运行它时,出现分段错误。

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

2 回答 2

6

经典初学者错误 1A:getchar()返回int,因为EOF不适合char.

我也认为你有一个索引问题,因为如果你找到一个标签,你会增加i空格插入循环,然后for循环会i再次增加,在字符串中留下奇怪的东西。这可能会导致缓冲区溢出和您看到的崩溃。

请注意,空格插入循环不会检查i.MAXLINE

于 2012-06-19T08:56:29.373 回答
2

呼吁printf

printf("%s");

是段错误的可能原因。它将尝试将堆栈上的一些任意数据解释为指向以 0 结尾的char数组的指针。

段错误的某种方式是在 a 的情况下循环'\t'

if(c == '\t') {
    while((TABLENGTH - (i % TABLENGTH)) != 0) {
        line[i] = ' ';
        i++;
    }
    i--;
    continue;
}

因为i >= 0and TABLENGTH > 0,你总是有0 <= (i % TABLENGTH) < TABLENGTH,所以每当你遇到一个选项卡时,你会进入一个无限循环,将空格添加到line分配的空间之外,当它尝试将空间写入进程内存之外或读取时迟早会导致段错误 -只是记忆的一部分。一个简单但不是很优雅的修复方法是将循环更改为

if (c == '\t') {
    do {
        line[i] = ' ';
        ++i;
    }while(((TABLENGTH - (i % TABLENGTH)) % TABLENGTH) != 0);
    --i;
    continue;
}

一个不同的解决方法可能是使用一个单独的计数器或一个switch带有故障的计数器。

于 2012-06-19T09:04:50.503 回答