Я вижу некоторое нечетное поведение из функции strncat
в стандартной библиотеке string.h
и хотел бы, чтобы какая-то помощь понимала, что происходит.strncat выглядит как сохраняющий данные через вызовы?
Суть моего вопроса в функции я создал называется readLine
с целью возвращения строк файла как char *
строки без завершающего символа новой строки терминатор. Эта функция выглядит следующим образом:
char * readLine(FILE * fp) {
char * chunk = NULL;
char * line = NULL;
int count = 0;
// iterate through chunks of a line until we reach the end (or an error)
while (fgets((chunk = malloc(sizeof(char) * BUFFER_SIZE)), BUFFER_SIZE, fp) != NULL) {
// realloc on a null pointer works like malloc
line = realloc(line, ++count * BUFFER_SIZE * sizeof(char));
printf("chunk's contents: %s\n", chunk);
// does chunk contain the end of a line?
if(strchr(chunk, '\n') == NULL) {
// concatenate string parts and continue loop
strncat(line, chunk, strlen(chunk) + 1);
free(chunk);
} else {
// we want to return a \0 terminated string without the \n
// expected position of \n in chunk is ({length of chunk}-1)
chunk[(strlen(chunk) - 1)] = '\0';
// concatenate string parts
strncat(line, chunk, strlen(chunk) + 1);
printf("readLine line: %s\n", line);
free(chunk);
break;
}
}
return line;
}
Я называю это в главном в цикле, который выглядит следующим образом:
FILE * fp = NULL;
if ((fp = fopen(FILE_PATH, "r")) != NULL) {
char * line = NULL;
while ((line = readLine(fp)) != NULL) {
printf("main line: %s\n\n", line);
free(line);
}
fclose(fp);
}
Теперь странное поведение приходит в моем определении #define BUFFER_SIZE 1000
. С его установить, как я получаю следующий результат (который не то, что я хочу):
chunk's contents: I am on line 1
readLine line: I am on line 1
main line: I am on line 1
chunk's contents: Over here I am on line 2
readLine line: I am on line 1Over here I am on line 2
main line: I am on line 1Over here I am on line 2
chunk's contents: Line 3 here
readLine line: I am on line 1Over here I am on line 2Line 3 here
main line: I am on line 1Over here I am on line 2Line 3 here
chunk's contents: Look out for 4
readLine line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4
main line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4
chunk's contents: Johnny 5 alive!
readLine line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4Johnny 5 alive!
main line: I am on line 1Over here I am on line 2Line 3 hereLook out for 4Johnny 5 alive!
НО если я изменить это определение к чему-то вроде #define BUFFER_SIZE 20
, я получаю выход я ищу :
chunk's contents: I am on line 1
readLine line: I am on line 1
main line: I am on line 1
chunk's contents: Over here I am on l
chunk's contents: ine 2
readLine line: Over here I am on line 2
main line: Over here I am on line 2
chunk's contents: Line 3 here
readLine line: Line 3 here
main line: Line 3 here
chunk's contents: Look out for 4
readLine line: Look out for 4
main line: Look out for 4
chunk's contents: Johnny 5 alive!
readLine line: Johnny 5 alive!
main line: Johnny 5 alive!
Я думаю, что у меня есть проблемы, суженные до strncat(line, chunk, strlen(chunk) + 1);
линии. Я не понимаю, почему предыдущие line
s включены, когда мой BUFFER_SIZE
достаточно высок.
Попробуйте помешать вашим буферам до 0 перед их использованием. –
Обратите внимание, что ваш 'strncat' реализует алгоритм Painter's Schlemiel: http://www.joelonsoftware.com/articles/fog0000000319.html – ecatmur
Обратите внимание, что с помощью' line = realloc (line, ... 'у вас будет неустранимая память утечка должна быть переполнена и вернуть NULL (что вы должны проверить). Функция 'realloc' ужасна с точки зрения API, среди других причин, потому что она приглашает написать неправильный код, подобный этому. – hlovdal