我有以下代码,并且从我用来调试的一些打印中得到了奇怪的输出,只是想问清楚为什么它会这样。
int *counter(const char *filename, bool bytes_flag, bool words_flag, bool lines_flag) {
int *counts = malloc(sizeof(int) * 3);
int line_count = 0;
int word_count = 0;
int byte_count = 0;
size_t line_size = LINE_MAX;
FILE *file_stream;
char *line_buffer;
printf("%d %d %d\n", line_count, word_count, byte_count);
file_stream = fopen(filename, "r");
if (file_stream == NULL) {
printf("File count not be opened.\n");
} else {
line_buffer = (char *)malloc(line_size);
while (getline(&line_buffer, &line_size, file_stream) != EOF) {
if (lines_flag) {
line_count++;
}
printf("LINE - %s\n", line_buffer);
for (int i = -1; line_buffer[i] != '\n'; i++) {
printf("%c ", line_buffer[i]);
byte_count++;
if (isspace(line_buffer[i]) && !isspace(line_buffer[i - 1])) {
word_count++;
}
}
printf("\n");
byte_count++; //Count last \n character
}
fclose(file_stream);
printf("\n");
printf("%d\n", line_count);
printf("%d\n", word_count);
printf("%d\n", byte_count);
printf("\n");
counts[0] = line_count;
counts[1] = word_count;
counts[2] = byte_count;
}
return counts;
}
我的结果是
LINE - The Project Gutenberg eBook of The Art of War
T h e P r o j e c t G u t e n b e r g e B o o k o f T h e A r t o f W a r
LINE -
LINE - This ebook is for the use of anyone anywhere in the United States and
T h i s e b o o k i s f o r t h e u s e o f a n y o n e a n y w h e r e i n t h e U n i t e d S t a t e s a n d
3
24
130
来自文本文件
The Project Gutenberg eBook of The Art of War
This ebook is for the use of anyone anywhere in the United States and
注意第二行似乎有 4 个空格。我认为这是罪魁祸首,但如果这一行出现在打印字符之后,即下一次迭代,为什么会在
T h e
之前打印呢?
该代码具有未定义的行为,因为您在
中访问数组开头之前的字节 for (int i = -1; line_buffer[i] != '\n'; i++)
从
-1
开始没有意义,只有在 line_buffer[i - 1]
时才应进行测试 i > 0
。
此外,如果
line_buffer[i]
是空终止符,则应始终停止,以防文件中的最后一行没有尾随换行符。
测试从空间到非空间的转换更简单。
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *counter(const char *filename, bool bytes_flag, bool words_flag, bool lines_flag) {
int *counts = malloc(sizeof(int) * 3);
if (counts == NULL) {
fprintf(stderr, "Cannot allocate memory\n");
return NULL;
}
int line_count = 0;
int word_count = 0;
int byte_count = 0;
printf("%d %d %d\n", line_count, word_count, byte_count);
FILE *file_stream = fopen(filename, "r");
if (file_stream == NULL) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
} else {
size_t line_size = 0;
char *line_buffer = NULL;
while (getline(&line_buffer, &line_size, file_stream) >= 0) {
if (lines_flag) {
line_count++;
}
printf("LINE - %s\n", line_buffer);
unsigned char last = '\n', ch;
for (size_t i = 0; (ch = line_buffer[i]) != '\0'; i++) {
printf("%c ", ch);
byte_count++;
if (!isspace(ch) && isspace(last)) {
word_count++;
}
last = ch;
}
}
fclose(file_stream);
printf("\n");
printf("%d\n", line_count);
printf("%d\n", word_count);
printf("%d\n", byte_count);
printf("\n");
}
counts[0] = line_count;
counts[1] = word_count;
counts[2] = byte_count;
return counts;
}