文本文件到普通c中的字符串数组?

时间:2010-07-09 00:53:36

标签: c linux arrays file file-io

我想将一个txt文件加载到像php()中的file()那样的数组中。我希望能够访问不同的行,如数组[N](应该包含文件中的整行N),然后我需要删除每个数组元素后使用它将减小大小,直到达到0和程序将完成。我知道如何读取文件,但我不知道如何填充字符串数组,就像我说的那样。我正在使用gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5)进行编译。

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:2)

建议的算法:

  1. 使用fseekftellfseek寻求结束,确定文件长度,然后重新开始。
  2. malloc一个足够大的缓冲区,用于整个文件加上空终止。
  3. 使用fread将整个文件读入缓冲区,然后在末尾写入0字节。
  4. 逐字循环遍历缓冲区并计算换行符。
  5. 使用malloc分配该数字+ 1 char *指针。
  6. 再次循环缓冲区,指定第一个指针指向缓冲区的开头,连续指针指向换行符后的字节。用过程中的0(null)字节替换换行字节本身。
  7. 一个优化:如果您不需要随机访问这些行(按行号索引它们),请取消指针数组,只需用0字节替换所有换行符。然后s+=strlen(s)+1;前进到下一行。您需要添加一些检查以确保您不会超过缓冲区的结束(或者如果您正在反向执行此操作,则开始)。

    无论哪种方式,这种方法非常有效(没有内存碎片)但有一些缺点:

    • 你不能单独释放线路;一旦完成,你只能释放整个缓冲区。
    • 您必须覆盖换行符。有些人喜欢将它们保存在内存结构中。
    • 如果文件以换行符结束,则指针数组中的最后一行将为零长度。 IMO这是对文本文件的理解,但有些人更喜欢在最后一行换行后考虑空字符串非行,并考虑最后一行“不完整”,如果它不以换行结束。

答案 1 :(得分:1)

我建议您将文件读入一个指向字符串的指针数组,这样您就可以按照指定的方式索引和删除这些行。使用这种方法需要考虑效率权衡,以便在读取每一行时是提前计算行数还是分配/扩展数组。我会选择前者。

  1. 阅读文件,计算您看到的行终结符的数量(以太\n\r\n
  2. 分配一个大小为<* li>的char *数组
  3. 逐行重新读取文件,使用malloc()为每个文件分配缓冲区并由下一个数组索引指向
  4. 对于您的运营:

    • 索引仅为array[N]
    • 删除只是释放array[N]索引的缓冲区并将array[N]条目设置为NULL

    更新:

    @r .. @ marc-van-kempen 建议的内存效率更高的方法是优于malloc()每行的优化时间,即将文件粘贴到单个缓冲区中并用'\0'替换所有行终止符

    假设你已经完成了这个并且你有一个大的缓冲区char *filebuf并且行数是int num_lines那么你可以分配你的索引数组:

    char *lines[] = (char **)malloc(num_lines + 1); // Allocates array of pointers to strings
    lines[num_lines] = NULL; // Terminate the array as another way to stop you running off the end
    
    char *p = filebuf; // I'm assuming the first char of the file is the start of the first line
    int n;
    for (n = 0; n < num_lines; n++) {
      lines[i] = p;
      while (*p++ != '\0') ; // Seek to the end of this line
      if (n < num_lines - 1) {
        while (*p++ == '\0')  ; // Seek to the start the next line (if there is one)
      }
    }
    

    使用单个缓冲区方法“删除”一行只是将lines[n]设置为NULL的情况。有没有 free()

答案 2 :(得分:1)

两种略有不同的实现方式,一种是内存友好,另一种更友好。

我记忆中的友好

  1. 打开文件并获取其大小(使用fstat()和朋友)==&gt;大小
  2. 分配该大小的缓冲区==&gt; char buf [size];
  3. 扫描计数'\ n'的缓冲区(或'\ n \ r'== DOS或'\ r'== MAC)==&gt; Ñ
  4. 分配数组:char * lines [N]
  5. 再次扫描缓冲区并将行[0]指向&amp; buf [0],扫描第一个'\ n'或'\ r'并将其设置为'\ 0'(分隔字符串),设置第一个字符后面的行[1]不是'\ n'或'\ r'等等。
  6. II cpu friendly

    1. 创建链接列表结构(如果你不知道如何做或不想做,请看看'glib'(不是glibc!),gtk的实用工具。
    2. 打开文件并开始使用fgets()读取行,逐步对每行进行malloc。
    3. 保留一个链接列表==&gt;列出并计算总行数
    4. 分配数组:char * lines [N];
    5. 浏览链表并将指向每个元素的指针分配给相应的数组元素
    6. 释放链表(不是其元素!)