【问题标题】:Is there a function that will quickly sort a file in C? [closed]是否有一个函数可以快速对 C 中的文件进行排序? [关闭]
【发布时间】:2015-02-25 20:10:46
【问题描述】:

对,我正在使用数据库编写一些代码,而我学校的某个人正在谈论一些可以自动获取文件并对其进行排序的特定命令。

我想我已经掌握了如何手动对这个文件进行排序,但是它需要做很多工作,所以我想知道是否有人知道这个功能。

编辑:使用 DEV C++ ,库 #stdio.h 和 #conio.h ,(如果需要,我可以添加额外的库)但是不知道具体的编译器是什么。

【问题讨论】:

  • perl? sort?相对而言,编写 C 程序大量工作。
  • 你用的是什么操作系统?
  • 您是在寻找执行此操作的 shell 命令,还是尝试用 C 编写自己的实现?
  • @mattingly890 不知道shell命令是什么,我正在尝试找到可以做到的默认函数(例如getch();或clrscr();
  • 好的,然后将其放在您的问题中,并附上您要排序的文件的简短示例。我们不介意读者。

标签: c file function sorting


【解决方案1】:

假设你的输入文件是data.txt (Linux),你可以使用系统命令sort:

sort data.txt > output.txt

【讨论】:

  • 如果必须是C语言,那么语法是system("sort data.txt > output.txt")
  • @WhipItOut: sort 是系统或 shell 命令(从命令行执行)。它是一个独立的程序,而不是 C/C++ 函数。
  • 无法访问文件,因为它正被另一个进程使用...
  • @WhipItOut 这意味着你在 windows 上运行,pretemuc 唯一的解决方案是关闭文件
  • @Jasen 所以我不能在 Windows 上使用它?有windows解决方案吗?
【解决方案2】:

正如其他人提到的,Unix 中有 sort 命令:

sort myfile.txt

请参阅man sort 了解更多选项。

Windows 上有SORT 命令:

sort myfile.txt

SORT myfile.txt

如需更多帮助,请参阅:http://www.computerhope.com/sorthlp.htm

这样你就可以编写简单的 C 程序来使用这些命令。

// sort.system.c

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

int main(int argc, char **argv) {
  if (argc != 2) { // expecting one argument, file which we will sort
    fprintf(stderr, "Usage: sort [FILE]\n");
    return EXIT_FAILURE;
  }

  int length = 5 + strlen(argv[1]) + 1; // length of "sort " is 5.
  char *command = (char *) calloc(length, sizeof(char));
  sprintf(command, "sort %s", argv[1]);

  int ret = system(command);

  return ret;
}

这里我们只期望用户输入他想要排序的文件,然后我们正在使用这个文件并将它交给sort 命令。但首先我们需要确保用户实际输入了一些内容。这就是为什么我们在main 函数的开头有if

第二种方法是自己编写sort 命令。乐趣从这里开始。 :D

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

#define MAX_LINE_LENGTH 1000000

// compare function for qsort function
int compare (const void *a, const void *b) {
  const char **s1 = (const char **) a;
  const char **s2 = (const char **) b;
  return strcmp(*s1, *s2);
}

int main(int argc, char **argv) {
  if (argc != 2) { // expecting one argument, file which we will sort
    fprintf(stderr, "Usage: sort [FILE]\n");
    return EXIT_FAILURE;
  }

  char *filename = argv[1]; // name of file to sort
  FILE *file = fopen(filename, "r"); // trying to open that file
  if (file == NULL) {
    fprintf(stderr, "Could not open file %s\n", filename);
    return EXIT_FAILURE;
  }

  int size = 16; // initial size of lines container
  char **lines = (char **) calloc(size, sizeof(char *)); // lines container
  if (lines == NULL) { // safety check
    fprintf(stderr, "Could not allocate the requested block of memory\n");
    return EXIT_FAILURE;
  }

  // buffer where we will store every line before putting it into line container
  char *buffer = (char *) calloc(MAX_LINE_LENGTH + 1, sizeof(char));
  if (buffer == NULL) { // safety check
    fprintf(stderr, "Could not allocate the requested block of memory\n");
    return EXIT_FAILURE;
  }

  int counter = 0; // line counter, counts how many lines we have readed

  // reading whole line into buffer
  while(fgets(buffer, MAX_LINE_LENGTH + 1, file) != NULL) {
    // measuring line length with strlen and adding 1 for '\0'
    int length = strlen(buffer);
    if (buffer[length - 1] == '\n') { // remove '\n' on end of line
      // replace '\n' with '\0', thus '\0' already included into length
      buffer[length - 1] = '\0';
    } else {
      length++; // include '\0'
    }

    // if our lines container is not large enough we will double its size
    if (counter + 1 == size) {
      size *= 2;
      lines = (char **) realloc(lines, size*sizeof(char *));
      if (lines == NULL) { // safety check
        fprintf(stderr, "Could not allocate the requested block of memory\n");
        return EXIT_FAILURE;
      }
    }

    // allocating space for line
    lines[counter] = (char *) malloc(length*sizeof(char));
    strcpy(lines[counter], buffer);

    counter++;
  }

  // using qsort function from stdlib.h
  qsort(lines, counter, sizeof(char *), compare);

  int i;
  for (i = 0; i < counter; i++) {
    puts(lines[i]);
  }

  return EXIT_SUCCESS;
}

想法是有一些初始大小为 16 的动态“行容器”。每次我们发现需要更多空间来存储行时,我们将“行容器”的大小加倍。

此外,我们有一些缓冲区用于存储每一行​​,然后我们将该行复制到下一行容器槽中。

在这里,我将一行的大小限制为 10^6 个字符。但是您也可以使用ftellfseek 函数为缓冲区动态分配空间。我建议你这样做是为了练习。 :)

对于字符串的实际排序,我们使用来自stdlib.hqsort 函数:

http://www.cplusplus.com/reference/cstdlib/qsort/

【讨论】:

  • 注意:如果第一个字符是 '\n'while(fscanf(file, "%[^\n] ", buffer) 不会读取任何内容。因此,如果文件以'\n' 开头,--> 无限循环作为fscanf() 将返回0,并且循环将处理""。建议fgets().
  • @chux 感谢您的评论。我真的没想到。 :)
  • 角落问题仍然存在新的变化:如果最后一行没有以'\n'结尾,那么如果最后一行被排序到另一个地方,它的末尾将没有\n,并且那么它和以下行将显示为一个 - 不清楚如何最好地处理。其他迂腐问题包括嵌入式 '\0' 和变体 EOL 类型。我对你的排序程序印象深刻,但就像婚礼一样,细节让人抓狂。
  • @chux 感谢您指出这一点。我已经删除了每行末尾的“\n”。
  • @WhipItOut 如果有不明白的地方,你应该问:)
猜你喜欢
  • 2010-11-03
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
  • 2014-06-23
  • 2013-05-14
  • 2013-10-25
  • 2020-11-03
  • 2011-05-21
相关资源
最近更新 更多