按特定字段对字符串的二维数组进行排序

时间:2012-11-28 00:20:58

标签: c arrays sorting multidimensional-array qsort

给定下面的二维数组:

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);
}

2 个答案:

答案 0 :(得分:3)

你可以从这样的事情开始,你需要在某个地方实际调用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;
}

答案 1 :(得分:3)

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

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,如果第一个参数被认为分别小于,等于或大于0,则可以看到返回值应为“小于,等于或大于零的整数”比第二个“。实现此目的的最简单方法是使用逻辑n1 - n2而不是n1 < n2

我还认为你类型char **的类型参数也很奇怪,但经过进一步的反思,我发现它们是正确的。来自qsort docs:“两个指向被比较对象的参数”。所以他们确实会指向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);
}