作为一项学校作业,我的任务是编写一个程序,打开任何文本文件并对文本执行许多操作。必须使用链表加载文本,这意味着包含char指针和指向下一个struct的指针的结构数组。每个结构一行。
但是我在加载文件时遇到了问题。在我实际读取文本之前,似乎必须分配将文本加载到内存中所需的内存。因此,我必须多次打开文件。一旦算出行数,那么每行两次;一旦计算行中的字符然后一次读取它们。打开文件数百次只是为了将其读入内存似乎很荒谬。
显然有更好的方法可以做到这一点,我只是不知道: - )
实施例
fgetc
移动字符的点吗? 答案 0 :(得分:3)
不需要多次打开文件,也不需要多次传递它。
查看POSIX getline()
函数。它将行读入分配的空间。您可以使用它来读取行,然后复制链接列表的结果。
没有必要使用链表来提前知道有多少行;这是列表的优势。
因此,代码可以通过一次完成。即使您不能使用getline()
,也可以使用fgets()
并监视它是否每次都读取到行尾,如果不是,您可以分配(并重新分配)空间来保存根据需要行malloc()
,realloc()
,最后free()
来自<stdlib.h>
。
如果你采用我建议的方法,你的具体问题在很大程度上是无关紧要的,但是:
使用fseek()
(以及在extremis rewind()
中)将移动读指针(对于fgetc()
和所有其他函数),除非'file'不支持搜索(例如,作为标准输入提供的管道。
可以使用stat()
或fstat()
或变体来确定字符。除非通过阅读文件,否则无法确定行。
由于文件大小可能从零字节到千兆字节,因此没有一种合理的方法可以进行固定大小的分配。使用malloc()
等人,你几乎被迫进入动态内存分配。 (在幕后,getline()
使用malloc()
和realloc()
。)
答案 1 :(得分:1)
如果没有实际遍历文件,则无法计算文件中的行数。你可以得到总文件大小,但这不是什么意思。使用链接的行列表的想法是您一次对文件进行一行操作。您不需要提前阅读任何内容。如果您还没有读取整个文件,请读取一行,将其添加到链接列表末尾的自己的节点,然后移动到下一行。
答案 2 :(得分:0)
关于第一个问题:您可以使用fseek()函数更改正在读取的文件中的位置。
有几种方法可以做到这一点。例如,你可以有一个固定大小的缓冲区,用文件中的字节填充它,从缓冲区复制行到列表,再次填充缓冲区等等。