2013-11-20 2 views
2

EDIT: минимальный код компиляции, воспроизводящий поведение.strtok (я полагаю) ошибка Не могу понять

Этот код читает дерьмовый файл словаря, чтобы попытаться извлечь из него какую-то интересную информацию. Каждая строка преобразуется в запись структуры. Слово всегда извлекается, поэтому newentry() не проверяет правильность аргумента слова.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef struct entry { 
char *word; 
char *cat; 
char *gen; 
} entry; 

entry *newentry(char *word, char *cat, char *gen) { 
entry *w = malloc(sizeof(entry)); 
w->word = malloc(sizeof(strlen(word)) + 1); 
strcpy(w->word, word); 
if (cat) { 
    w->cat = malloc(sizeof(strlen(cat)) + 1); 
    strcpy(w->cat, cat); 
} 
else { 
    w->cat = ""; 
} 
if (gen) { 
    w->gen = malloc(sizeof(strlen(gen)) + 1); 
    strcpy(w->gen, gen); 
} 
else { 
    w->gen = ""; 
} 
return w; 
} 


int main() { 
FILE *original = fopen("French.txt", "r"); 
char *line = NULL; 
size_t len = 0; 
ssize_t read; 
while ((read = getline(&line, &len, original)) != -1) { 
    char *word = strtok(strdup(line), "\t"); 
    char *tmp = strtok(NULL, "[\n"); 
    char *cat = strtok(NULL, "]\n"); 
    newentry(word, cat, tmp);   //bugs here 
} 
return 0; 
} 

Этот код выходит из строя на линии (код), и я абсолютно не знаю почему. Если бы я заменил tmp на слово, cat или константу, он будет работать каждый раз. Если бы я изменил порядок аргументов newentry(), он терпит неудачу каждый раз, если tmp является аргументом. Я пытался отладить, сломавшись в то время. Файл, который разбирается, составляет около 4 тысяч строк, поэтому я представил, что какая-то строка (это очень дрянной файл) каким-то образом была повреждена, и я попытался продолжить 1000 и получил исключение. Поэтому я перезапустил и попробовал другие значения continue, но, продолжая 100 11 раз, я смог превысить прежний 1000.

Мое заключение состоит в том, что tmp поврежден каким-то образом следующим strtok. Поэтому я попробовал char * tmp = strdup (strtok (NULL, "[\ n")); и это не сработало лучше.

Замена строки с ошибкой newentry() по printf ("% s% s% s", word, tmp, cat); работает в 100% случаев, хотя я не могу проверить 4000 значений на глаз.

Я действительно не знаю, как выйти из этого беспорядка, и будет признателен за любые указатели.

EDIT: несколько строк из файла данных:

courthouse palais de justice[Noun] 
courtier courtisan[Noun] 
courtliness e/le/gance[Adjective] 
courtly e/le/gant[Adjective] 
courtmartial conseil de guerre[Noun] 
courtroom salle d'audience[Noun] 

Спасибо.

Весь входной файл, в случае, если кто-то действительно любопытно: http://pastebin.com/VPp8WpuK

+0

Пока это теперь может не возникнуть проблема, вы должны проверить, если 'malloc' fail (return 'NULL'). – user694733

+0

Вы выделяете память в 'newentry', но ни в коем случае не освобождаете эту память –

+0

Пожалуйста, покажите пример строки файла. – Hogan

ответ

2

Разбирающая строка которые вы выбираете для strtok, возможно, придется отрегулировать. С примером входного файла. Я получаю нуль во второй строке strtok, потому что вся строка считывается при первом вызове strtok (т. Е.нет «\ т» в строке

char *word = strtok(StrDup(line), "\t");//reads entire line of input 
char *tmp = strtok(NULL, "[\n");//NULL is returned here 
char *cat = strtok(NULL, "]\n"); 

Таким образом, вы передаете нуль в вашу функцию newentry(,,)

Будет ли это работать изменить разбор строки:

char *word = strtok(StrDup(line), "\t ");//added space 

Также следующие строки

w->word = malloc(sizeof(strlen(word)) + 1); 
w->cat = malloc(sizeof(strlen(cat)) + 1); 
w->gen = malloc(sizeof(strlen(gen)) + 1); 

должен быть:

w->word = malloc(strlen(word) + 1); 
w->cat = malloc(strlen(cat) + 1); 
w->gen = malloc(strlen(gen) + 1); 

одна вещь, вам нужно освободить память, выделенную в newentry(), который будет проблемой, если вам нужно вернуть-структуру ш. Предложил бы выделить все это в main(), передав структуру как указатель, а затем освободив ее, когда она вернется.

Это, как сделать это ...
Создать массив struct entry:

typedef struct { 
    char *word; 
    char *cat; 
    char *gen; 
} ENTRY; 
ENTRY entry[linesInFile], *pEntry; 

Затем в main() инициализации:

int main(void) 
{ 
    pEntry = &entry[0]; 
    //allocate memory 
    //call redefined newentry() function 
    //use results of newentry() function 
    //free memory 
} 

Теперь, поскольку pEntry является указателем всему массиву entry, его можно легко передать как аргумент после вызова malloc для членов char *. (Не забудьте free(), когда он возвращается)

Вот редактирует я должен был сделать, чтобы запустить его (не включает в себя переписать, чтобы получить свободный() вызывает в)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef struct entry { 
    char *word; 
    char *cat; 
    char *gen; 
} entry; 

entry *newentry(char *word, char *cat, char *gen) 
{ 
    entry *w = malloc(sizeof(entry)); 
    w->word = malloc(strlen(word) + 1); 
    strcpy(w->word, word); 
    if (cat) 
    { 
     w->cat = malloc(strlen(cat) + 1); 
     strcpy(w->cat, cat); 
    } 
    else 
    { 
     w->cat = ""; 
    } 
    if (gen) 
    { 
     w->gen = malloc(strlen(gen) + 1); 
     strcpy(w->gen, gen); 
    } 
    else 
    { 
     w->gen = ""; 
    } 
    return w; 

} 


int main() 
{ 
    FILE *original = fopen("French.txt", "r"); 
    char line[260]; 
    int len = 260; 
    //ssize_t read; 
    while (fgets(line, len, original))    
    { 
     //char *word = strtok(StrDup(line), "\t ");//I dont have strdup, had to use this 
     char *word = strtok(strdup(line), "\t "); 
     char *tmp = strtok(NULL, "[\n"); 
     char *cat = strtok(NULL, "]\n"); 

     if((!word)||(!tmp)||(!cat)) return 0; 
     word[strlen(word)]=0; 
     tmp[strlen(tmp)]=0; 
     cat[strlen(cat)]=0; 

     newentry(word, cat, tmp);   //bugs here 
    } 
    return 0; 
} 
+0

входные файлы печально ошибочны. В исходном файле есть вкладка, но оба SO и PB превратили их в пробелы. Приношу извинения за потерю времени. – pouzzler

3

Это неправильно:

entry *w = malloc(sizeof(entry *)); 

Вы хотите:

entry *w = malloc(sizeof *w); 

или:

entry *w = malloc(sizeof(entry)) 
+0

Не могли бы вы объяснить, что не так, пожалуйста? Оба выражения не изменяют прослушивание. – pouzzler

+0

'malloc (sizeof (entry *)' выделяет размер памяти указателя на запись, а 'malloc (sizeof * w)' выделяет память размером, на который указывает w. – Hogan

+0

@pouzzler 'sizeof (entry *)' возвращает только размер указателя, а не целая структура.Так что у вас слишком мало памяти – user694733

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