【问题标题】:Sorting a 2 dimensional array of strings by a specific field按特定字段对二维字符串数组进行排序
【发布时间】:2012-11-15 17:58:04
【问题描述】:

给定一个二维数组,如下所示:

char * Arr[4] = 
{
    {"124 -346  DATA...."},
    {"39479 -32 MOREDATA...."},
    {"12 -1 DATA2...."},
    {"100 -45 DATA4...."}
};

我正在尝试使用qsort() 根据 SECOND 字段对该函数进行排序,这意味着字符串将根据最低的第二个值(-1、-32、-45 ,-346)。如果每个值只有一个数字,我知道如何实现此功能,但程序中的数字可以任意长。这是我所拥有的,但是程序崩溃了,如果有更有效的方法来对这些数据进行排序,我很乐意在这里(我知道我的方法效率不高)。

排序函数(qsort() 调用):

inline void GetStr(char *ix, char* Result)  //call to get second number in function
{
    char *spacing;              //iterator to traverse
    spacing = ix;               //iterator = pos of ix
    int LEN = 0;                //length and offset
    int Offset = 0;

    while(*spacing != ' ')      //while not at end of first num
    {
        Offset++;               //offset is more
        spacing++;
    }
    spacing++;                  //go one ahead of the space
    Offset++;

    while(*spacing != ' ')      //while not end of second number
    {
        spacing++;
        Offset++;
        LEN++;                  //length of number
    }
    strncpy(Result, ix + (Offset - LEN),LEN);
}

int sort(const void* a, const void* b)
{
    char *ia = *(char**)a;
    char *ib = *(char**)b;

    char * Str;
    char * Str2;
    GetStr(ia, Str);                                    //getting some strange errors....... program just crashes
    GetStr(ib, Str2);
    printf("Str: %s Str2: %s", Str, Str2);
    int n1 = atoi(Str);
    int n2 = atoi(Str2);
    return (n1 > n2);
}

【问题讨论】:

  • 根据这个问题和上一个问题,看来你对qsort有误解。库函数qsort 不会直接对文件进行排序。它对您传递的数组进行排序。您可能只需在 Google 上搜索“qsort 示例”并更好地了解它的工作原理。
  • 我阅读了stackoverflow.com/questions/3707051/… 并认为我可以,我错了吗?
  • 不 - 它不会对文件进行排序。在那个例子中,OP(我相信)实际上是在尝试对 argv 数组进行排序(对传递给程序的实际参数进行排序)。我认为您错过了@BenJackson 对您上一个问题的回答中重要的第一步。您需要读入文件的内容(这意味着编写代码... fopen、fread 或您使用的任何 I/O 函数集)。
  • 感谢您的解释,这是否意味着我不需要 agrv 的副本,只需将 const argv[1] 写入数组?
  • 我不确定我是否理解了您想要实现的目标。但是,如果您只想独立于参数的顺序,请考虑使用GNU Getopt

标签: c arrays sorting multidimensional-array qsort


【解决方案1】:

我相信你这里至少有一个问题:

strncpy(Result, ix + (Offset - LEN),LEN);

如果您查看documentation for strncpy,您会发现如果您达到字符限制,它不会自动以空值终止复制的字符串。因此,您的 Result 字符串不是以空值结尾的。

尝试改成这样:

strncpy(Result, ix + (Offset - LEN),LEN);
Result[LEN] = '\0';

当然,您仍然需要为 Result 字符串提供内存。目前您正在将未初始化的指针传递给GetStr()

char * Str;
char * Str2;

由于这些是相当小的整数,您可以像这样使用静态分配的存储:

#define MAX_RESULT_LEN 64

/* ... */

char Str[MAX_RESULT_LEN]
char Str2[MAX_RESULT_LEN]

/* ... */

if (LEN > MAX_RESULT_LEN - 1) {
    LEN = MAX_RESULT_LEN - 1;
}

strncpy(Result, ix + (Offset - LEN),LEN);
Result[LEN] = '\0';

最后,您的sort() 函数存在一些问题。如果您查看qsort() documentaton,您可以看到返回值应该是“如果第一个参数分别被认为小于、等于或大于第二”。实现这一点的最简单方法是使用逻辑 n1 - n2 而不是 n1 < n2

我还认为您的 char ** 类型的参数也很奇怪,但经过进一步思考,我意识到它们是正确的。来自 qsort 文档:“指向被比较对象的两个参数”。所以实际上它们将是指向 C 字符串或 char ** 的指针。

所以这是最终版本:

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

#define MAX_RESULT_LEN 64

void GetStr(char *ix, char* Result)  //call to get second number in function
{
    char *spacing;              //iterator to traverse
    spacing = ix;               //iterator = pos of ix
    int LEN = 0;                //length and offset
    int Offset = 0;

    while(*spacing != ' ')      //while not at end of first num
    {
        Offset++;               //offset is more
        spacing++;
    }
    spacing++;                  //go one ahead of the space
    Offset++;

    while(*spacing != ' ')      //while not end of second number
    {
        spacing++;
        Offset++;
        LEN++;                  //length of number
    }

    if (LEN > MAX_RESULT_LEN - 1) {
        LEN = MAX_RESULT_LEN - 1;
    }

    strncpy(Result, ix + (Offset - LEN),LEN);
    Result[LEN] = '\0';
}

int sort(const void* a, const void* b)
{
    char *ia = *(char **)a;
    char *ib = *(char **)b;

    char Str[MAX_RESULT_LEN];
    char Str2[MAX_RESULT_LEN];

    GetStr(ia, Str);
    GetStr(ib, Str2);

    printf("Str: %s Str2: %s", Str, Str2);
    int n1 = atoi(Str);
    int n2 = atoi(Str2);
    return (n1 - n2);
}

int main(void) {
    char * Arr[4] = 
    {
        {"124 -346  DATA...."},
        {"39479 -32 MOREDATA...."},
        {"12 -1 DATA2...."},
        {"100 -45 DATA4...."}
    };

    qsort(Arr, 4, sizeof(char *), sort);
}

【讨论】:

  • 非常感谢这篇文章,你一定会得到这个代表的。如果我们可以聊天,我只是有几个关于代码的问题
  • 很高兴在这里回答 cmets 的问题,或者随时发送电子邮件至 ben@wanderview.com。
  • 我将发送一封电子邮件,再次感谢!我必须等待 14 小时才能奖励我的赏金,这样你很快就会得到代表。
【解决方案2】:

你可以从这样的事情开始,你需要在某个地方实际调用 sort。还需要考虑文件很大时会发生什么:

#include <stdio.h>

int
Sort(const void *a, const void *b)
{
    int *aa = a, *bb = b;
    return (aa[1] < bb[1]); //i need to sort by field, not a simple comparison. HOW?
}

int main(int argc, char **argv) {
  FILE *f = fopen(argv[1]);
  if (f) {
    char buffer[1024];
    int *v;
    int data[1024][5];
    int cnt = 0;
    while (fgets(buffer, sizeof(buffer), f)) {
        v = data[cnt++];
        sscanf(buffer, "%d %d %d %d %d", v, v+1, v+2, v+3, v+4);
    }
    fclose(f);
  }
  return 0;
}

【讨论】:

    猜你喜欢
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2021-02-23
    • 2013-10-22
    相关资源
    最近更新 更多