【问题标题】:How do I sort the elements of argv in C?如何在 C 中对 argv 的元素进行排序?
【发布时间】:2011-04-12 01:06:08
【问题描述】:

我正在尝试按字母顺序对 argv 的元素进行排序。

以下代码行给我带来了问题:

qsort(argv[optind], argc - optind, sizeof(argv[optind]), sort);

具体来说,最后一个参数给我带来了麻烦,比较函数,如下所示:

int
sort(const void *a, const void * b)
{    
    return(strcmp( (char*)a, (char*)b ));
}

目前,它编译得很好,但是当我运行它时,我最终遇到了分段错误。

【问题讨论】:

  • 如果我没记错的话,修改 argv 数组会导致未定义的行为。你可能会向给你这个家庭作业的人提到这一点,如果你能在标准中找到引文,甚至可能会获得额外的学分(留给读者作为练习)。
  • 是的,某些平台似乎可以从一些有趣的技巧中受益,因此未定义的行为似乎是合理的。另一方面,手册页示例与数组一起使用的事实可能表明并非如此。或者我们在手册页中发现了一个错误。 :-)
  • 嗯,实际上,任务不是对 argv 数组进行排序。基本上,整个程序应该计算指定文件的字符数、单词数和行数并打印出结果,但按字母顺序排列。我的程序目前可以正确计算所有内容,但我需要找到一种方法使其按字母顺序打印出来,所以我认为对 argv 数组进行排序是一个好主意,因为所有文件名都在那里。无论如何,在按照你们的建议进行一些调整后,我可以将它打印到第一个文件及其计数的位置,但是......继续下面
  • 然后我得到一个分段错误。当我得到分段错误时,我使用 printf 语句检查当前文件名是什么,它表明它是 LANG=en_US.UTF-8 ,我不知道那是什么......为了更清楚,我在命令行中指定文件 test1.txt hello.txt abcd.txt。并且使用 qsort(),我可以将它打印到输出 abcd.txt 的位置(按字母顺序排列)及其计数。但后来我得到一个分段错误并检查正在传递的文件名,我看到它的 LANG
  • ...从上面继续,我看到它的 LANG=en_US.UTF-8 如果我不尝试对其进行排序,它可以完美运行,但会按照输入的顺序打印出来命令行。

标签: c sorting argv


【解决方案1】:

第一个参数应该是argv+optind,因为这是要排序的序列中第一个元素的地址。

【讨论】:

  • 真的吗?请记住,argv 是一个数组或字符串指针,因此 argv[optind] 将指向第一个字符串。
  • 它需要指向列表的开头,而不是在要排序的事物中。 &argv[optind] 可能是一种更直观的方式来看待这一点,这取决于人们的思维方式。
  • 确实如此,然后排序函数需要比较char **
  • 是的。这两件事都包含在 linux.die.net/man/3/qsort 上的 qsort() 手册页中。
【解决方案2】:

qsort(3) 的手册页包含一个示例,它完全符合您的要求。它还解释了原因:

http://linux.die.net/man/3/qsort

总结:您在qsort() 第一个参数上缺少一级引用,并且在sort() 函数中缺少一级取消引用。

【讨论】:

    【解决方案3】:

    问题出在 argv 数组的结构上。

    结构是这样的

    program\0arg1\0argument2\0a3\0\0
    

    qsort 函数假定所有元素的大小相同,但在这种情况下它们不是。您指定 argv[optind] 的大小,但并非所有元素都是该大小。

    编辑: 我弄错了,你传递给qsort的不是字符串长度,而是指针的长度。所以 argv 包含一个指针数组。目标是对指针进行排序。

    这意味着您将指针数组传递给 qsort,并且排序函数应该期待一个指针。像这样:

    int
    sort(const void *a, const void * b)
    {
        return(strcmp( *(char**)a, *(char**)b ));
    }
    
    qsort(argv+optind, argc - optind, sizeof(argv[optind]), sort);
    

    【讨论】:

    • 那么这是否意味着没有办法对argv的元素进行排序?
    • 这个答案不正确。 argv 是一个指针数组。如果这些指针指向的字符串数据恰好是您的答案中的结构,那么它纯粹是 正在使用的操作系统/编译器的实现细节。 argv 不应该被这样访问。
    【解决方案4】:

    这是我对argv进行排序的尝试

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int mycomp(const void *a, const void *b) {
      /* function code removed to prevent homework copy/paste */
    }
    
    int main(int argc, char **argv) {
      int i;
      qsort(argv + 1, argc - 1, sizeof *argv, mycomp);
      for (i = 1; i < argc; i++) printf("i: %d ==> '%s'\n", i, argv[i]);
      return 0;
    }
    

    以及程序的示例运行

    $ ./a.out 一二三四五六七 我:1 ==>'五' i: 2 ==> '四' i: 3 ==> '一' i: 4 ==> '七' 我:5 ==>'六' 我:6 ==>'三' 我:7 ==>'两个'

    【讨论】:

      猜你喜欢
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多