【问题标题】:struct - sorting a c-string with qsortstruct - 使用 qsort 对 c 字符串进行排序
【发布时间】:2010-12-20 20:42:47
【问题描述】:

我正在对一堆 IP 进行排序,但由于某种原因,它们的顺序错误。我不太确定问题出在哪里。

66.249.71.3      
190.148.164.245  
207.46.232.182   
190.148.164.245  
190.148.164.245  
202.154.114.253
190.148.164.245  
190.148.164.245  
66.249.71.3      
190.148.164.245  
202.154.114.253

这是我对它们进行排序的方式。

typedef struct {
    char *ip;
} mystruct;

/* qsort */
int struct_cmp(const void *a, const void *b)
{
    mystruct *ia = (mystruct *)a;
    mystruct *ib = (mystruct *)b;
    return strcmp(ia->ip, ib->ip);
} 
...
qsort(a_struct, 11, sizeof(mystruct*), struct_cmp);
for(..){
    printf("%s\n",a_struct[i]->ip);
}

任何帮助将不胜感激。谢谢

【问题讨论】:

  • 你给出的是输入还是输出的样本?

标签: c sorting struct


【解决方案1】:

您有一个指向mystructs 的指针数组,但qsort 使用此比较函数会期望一个简单的mystructs 数组。要对mystruct* 的数组进行排序,您需要向比较函数添加另一层间接:

int struct_cmp(const void *a, const void *b) {
    mystruct *ia = *(mystruct **)a;
    mystruct *ib = *(mystruct **)b;
    return strcmp(ia->ip, ib->ip);
}

【讨论】:

  • 实际上这可以完成这项工作。谢谢!
  • Josh,如果您尝试在调试器中运行您的代码,或者在您的 struct_cmp() 函数中添加对 printf() 的调用,您会注意到当您拥有指针时 IP 地址是垃圾错误的。所以,一个很好的调试技术:当事情变得奇怪时,确保你的指针指向你认为它们指向的地方! :-)
  • Nitpick:你在这里不是 const 正确的,因为你正在抛弃 constness。应该是mystruct *ia = *(mystruct * const *)a 等,尽管在这种情况下不会造成任何伤害。
【解决方案2】:

您将 IP 地址排序为字符串。如果它们被规范化,这实际上会起作用:如果你想让它起作用,你应该使用 066.249.071.003 而不是 66.249.71.3

我认为最好的办法是使用一个函数,将点分 IP 地址转换为 32 位整数,然后使用生成的整数作为排序键对它们进行排序。

您应该可以使用inet_addr() 进行此转换。将此添加到您的程序中:

#include <arpa/inet.h>

文档here

【讨论】:

  • 我同意我错过了主要问题。但是一旦他使用了某事的答案,他会因为这个问题而看到排序很奇怪,所以实际上两个答案放在一起是最好的解决方案。
【解决方案3】:

至少有两种方法可以修复排序代码。一种是修改比较器函数以匹配对 qsort() 的调用;另一种是修复对 qsort() 的调用以匹配比较器。正确的解决方法取决于数组的定义——但最简单的声明是结构数组(不是结构指针)。因此,这个工作代码 - 它使用原始比较器但对 qsort() 的不同调用:

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

typedef struct {
    char *ip;
} mystruct;

static mystruct a_struct[] =
{
    "66.249.71.3",
    "190.148.164.245",
    "207.46.232.182",
    "190.148.164.245",
    "190.148.164.245",
    "202.154.114.253",
    "190.148.164.245",
    "190.148.164.245",
    "66.249.71.3",
    "190.148.164.245",
    "202.154.114.253",
};

/* qsort */
static int struct_cmp(const void *a, const void *b)
{
    mystruct *ia = (mystruct *)a;
    mystruct *ib = (mystruct *)b;
    return strcmp(ia->ip, ib->ip);
}

static void print_list(mystruct *list, int n)
{
    int i;
    for (i = 0; i < n; i++)
        printf("%2d: %s\n", i, list[i].ip);
}

#define DIM(x)  (sizeof(x)/sizeof(*(x)))

int main(void)
{
    print_list(a_struct, DIM(a_struct));
    qsort(a_struct, DIM(a_struct), sizeof(mystruct), struct_cmp);
    print_list(a_struct, DIM(a_struct));
}

这只是给我们留下了一个按字母数字排序的值数组,所有“190.xyz”地址都出现在其他地址之前,等等。解决这个问题需要一个更复杂的比较器 - steveha 在他的回答中描述了一个解决方案.

【讨论】:

    猜你喜欢
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2011-07-19
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多