【问题标题】:C: Sort long list that can't fit into arraysC:对无法放入数组的长列表进行排序
【发布时间】:2017-01-08 14:48:19
【问题描述】:

我在一个文本文件中有一个 80370 长的 30 位数字列表,每个数字都在一个单独的行中。
我想用 C 对它们进行排序。

我的想法是创建一个新文件,然后将第一个数字添加到其中。
然后,每次我们将它与另一个数字进行比较。如果它更小,则附加其他数字。简单。但是,如果它更大,则必须在前面加上新数字。
我尝试像这样添加:

void prepend(char line[], FILE* w, FILE* waux, char filename[], char auxname[]) {
    fprintf(waux, "%s\n", line); //print new number to new file (waux)
    char ch;
    while((ch = fgetc(w)) != EOF) {
        fputc(ch, waux); //read old file (w) and add to new file (waux)
    }
    remove(filename); //delete old file
    rename(auxname, filename); //rename new file to old file's name
}

但后来我尝试读取输出,它充满了 NULL 字符(在 Notepad++ 中)。
在百万个 NULL 字符中,我们可以找到数字,但它们根本没有排序。

【问题讨论】:

  • 为什么要通过将部分输出写入文件来做到这一点?只需读取所有数据,一次排序和写入所有数据。其实你甚至不需要滚动你自己的排序函数,你可以使用<stdlib.h>qsort函数:en.cppreference.com/w/cpp/algorithm/qsort
  • 这比两兆字节多一点(如果你使用指针,也许是 3MB)。分配(使用 malloc())一个可以包含这么多数字的数组并不难。
  • 如上所述:将所有内容读入动态分配的数组中,然后使用qsort对其进行排序。
  • 80370 30 位数字对于现代通用计算机上的数组来说并不算大,即使这些数字表示为数字字符串。
  • 即使您使用的是 32 位版本的 windows,您也至少有 2 GB 的虚拟地址空间。即使您没有足够的物理 RAM,操作系统也可以使用交换空间为您解决此问题。但在你的情况下,现在 2MB 不是瓶颈

标签: c file sorting


【解决方案1】:

虽然我同意 cmets 应该使用 malloc 为所有数据分配内存,对内存中的数据进行排序,然后将数据写入文件,但我也认为你的方法也应该有效。

我猜您的方法不起作用的原因是您在使用时打开了文件的文件句柄

remove(filename); //delete old file
rename(auxname, filename); //rename new file to old file's name

我的建议:

  1. 在函数中打开文件。
  2. 执行读取和附加操作。
  3. 关闭文件。
  4. 然后执行删除和重命名。

void prepend(char line[], char filename[], char auxname[]) {

   FILE* w = fopen(filename, "r");
   if ( w == NULL )
   {
      fprintf(stderr, "Unable to open %s for reading from.\n", filename);
      return;
   }

   FILE* waux = fopen(auxname, "w");
   if ( waux == NULL )
   {
      fprintf(stderr, "Unable to open %s for writing to.\n", auxname);
      fclose(w);
      return;
   }

   fprintf(waux, "%s\n", line); //print new number to new file (waux)
   int ch;
   while((ch = fgetc(w)) != EOF) {
      fputc(ch, waux); //read old file (w) and add to new file (waux)
   }

   fclose(waux);
   fclose(w);

   remove(filename); //delete old file
   rename(auxname, filename); //rename new file to old file's name
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多