2012-06-19 4 views
0

Я только что купил «язык программирования C» K & R, и прилагаю все усилия, чтобы выполнять упражнения в нем (если вы знаете книгу, это упражнение 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

В какой строке находится сбой? – JeremyP

+0

В строке 29 строка [i] = ''; согласно gdb. В цикле while есть некоторая логика. – ManWithAPlan

+0

Посмотрите на мой обновленный ответ, я думаю, что я его прибил. –

ответ

2

Вызов printf

printf("%s"); 

является вероятной причиной Segfault. Он попытается интерпретировать некоторые произвольные данные в стеке как указатель на 0-концевой массив char.

Определенный путь к Segfault является петлей в случае '\t':

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

С i >= 0 и TABLENGTH > 0, у вас всегда есть 0 <= (i % TABLENGTH) < TABLENGTH, поэтому всякий раз, когда вы столкнулись с вкладкой, вы входите в бесконечный цикл при добавлении пространства до line за пределами выделенного пространства, и это рано или поздно вызовет segfault при попытке записать пробелы вне памяти процесса или в часть только для чтения в памяти. Легко, хотя и не очень элегантное исправление изменяет цикл для

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

другое исправление может использовать отдельный счетчик или switch с падением сквозной.

+0

Это будет помечено включением предупреждений в флагах компилятора или, вероятно, путем компиляции в режиме отладки для IDE, если он используется. – Potatoswatter

+0

Кажется, я перехитрил себя на этом. Это сработало обаяние. Большое вам спасибо! – ManWithAPlan

6

Классический новичок ошибка 1A: getchar() возвращается int, поскольку EOF не вписывается в char.

Я также думаю, что у вас есть проблемы индексации, так как если вы найдете вкладку, вы увеличите i в цикле пространственно-вставки, то цикл for увеличится i снова, оставив таинственность в строке. Это может привести к переполнению буфера и сбою, который вы видите.

Обратите внимание, что петля вставки пробела не проверяет i против MAXLINE.

+0

Я попытался изменить if-test на приведенное выше изменение (и изменив printf, чтобы на самом деле использовать нужную строку, но я все еще получаю ошибку сегментации. Я не получаю ошибку сегментации, если мой вход не включает символы табуляции, хотя (Я также изменил char на int, глупая ошибка). – ManWithAPlan

Смежные вопросы