如何在 C 中对 argv 的元素进行排序?

Posted

技术标签:

【中文标题】如何在 C 中对 argv 的元素进行排序?【英文标题】:How do I sort the elements of argv in C? 【发布时间】: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 如果我不尝试对其进行排序,它可以完美运行,但会按照输入的顺序打印出来命令行。 【参考方案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 ==>'两个'

【讨论】:

以上是关于如何在 C 中对 argv 的元素进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RecyclerView 中对字符串元素进行排序?

如何在 D3 中对绑定到不同数据(与 forcesimulatoin 一起使用)的元素进行分组,以便对它们进行排序

如何在 Bash 中对数组进行排序

如何像 EXCEL 一样在 Oracle 中对带有“_”的文本进行排序?

如何在 Swift 5 中对数组的数组进行排序 [关闭]

在C中对链表进行排序[关闭]