gpt4 book ai didi

c - 逐行读取文件,包括多个换行符

转载 作者:行者123 更新时间:2023-11-30 15:05:19 25 4
gpt4 key购买 nike

我正在尝试逐行读取未知大小的文件,包括单个或多个换行符。例如,如果我的sample.txt 文件如下所示

abc   cd er  dj
text

more text


zxc cnvx

我希望我的字符串看起来像这样

string1 = "abc   cd er  dj\n";
string2 = "text\n\n";
string3 = "more text\n\n\n";
string4 = "zxc convex";

我似乎无法想出可以正常工作的解决方案。我尝试使用以下代码来获取每行的长度(包括换行符),但它给出的长度不正确

while((temp = fgetc(input)) != EOF) {
if (temp != '\n') {
length++;
}
else {
if (temp == '\n') {
while ((temp = fgetc(input)) == '\n') {
length++;
}
}
length = 0;
}
}

我在想,如果我可以获得包括换行符在内的每行的长度,然后我可以 malloc 该长度的字符串,然后使用 fread 读取该大小的字符串,但我不确定这是否有效,因为我必须移动文件指针才能获取下一个字符串。

我也不想使用缓冲区,因为我不知道每行的长度。任何形式的帮助将不胜感激。

最佳答案

如果行很短并且行数不多,您可以使用 realloc 根据需要重新分配内存。或者您可以使用较小(或较大)的 block 并重新分配。这有点浪费,但希望最终能达到平均水平。

如果您只想使用一个分配,则找到下一个非空行的开头并保存文件位置(使用ftell)。然后获取当前位置和前一个起始位置之间的差异,就知道要分配多少内存。对于读取,是的,您必须来回查找,但如果不是很大,所有数据都将在缓冲区中,而只是修改一些指针。读取后寻找保存的位置并将其作为下一个起始位置。

那么您当然可以memory-map the file 。这会将文件内容放入内存映射中,就像已全部分配一样。对于 64 位系统,地址空间足够大,因此您应该能够映射数 GB 文件。那么你不需要寻找或分配内存,你所做的只是操作指针而不是寻找。读取只是简单的内存复制(但是由于文件已经“在”内存中,所以您实际上并不需要它,只需保存指针即可)。

<小时/>

关于 fseek非常简单示例和 ftell ,这与你的问题有些相关,我为你整理了这个小程序。它实际上并没有做任何特别的事情,但它展示了如何以可用于我上面讨论的第二种方法的原型(prototype)的方式使用这些函数。

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

int main(void)
{
FILE *file = fopen("some_text_file.txt", "r");

// The position after a successful open call is always zero
long start_of_line = 0;

int ch;

// Read characters until we reach the end of the file or there is an error
while ((ch = fgetc(file)) != EOF)
{
// Hit the *first* newline (which differs from your problem)
if (ch == '\n')
{
// Found the first newline, get the current position
// Note that the current position is the position *after* the newly read newline
long current_position = ftell(file);

// Allocate enough memory for the whole line, including newline
size_t bytes_in_line = current_position - start_of_line;
char *current_line = malloc(bytes_in_line + 1); // +1 for the string terminator

// Now seek back to the start of the line
fseek(file, start_of_line, SEEK_SET); // SEEK_SET means the offset is from the beginning of the file

// And read the line into the buffer we just allocated
fread(current_line, 1, bytes_in_line, file);

// Terminate the string
current_line[bytes_in_line] = '\0';

// At this point, if everything went well, the file position is
// back at current_position, because the fread call advanced the position
// This position is the start of the next line, so we use it
start_of_line = current_position;

// Then do something with the line...
printf("Read a line: %s", current_line);

// Finally free the memory we allocated
free(current_line);
}

// Continue loop reading character, to read the next line
}

// Did we hit end of the file, or an error?
if (feof(file))
{
// End of the file it is

// Now here's the tricky bit. Because files doesn't have to terminated
// with a newline, at this point we could actually have some data we
// haven't read. That means we have to do the whole thing above with
// the allocation, seeking and reading *again*

// This is a good reason to extract that code into its own function so
// you don't have to repeat it

// I will not repeat the code my self. Creating a function containing it
// and calling it is left as an exercise
}

fclose(file);

return 0;
}

请注意,为了简洁起见,该程序不包含任何错误处理。还应该指出的是,我实际上并没有尝试过该程序,甚至没有尝试编译它。这都是专门为这个答案而写的。

关于c - 逐行读取文件,包括多个换行符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39934530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com