从带有 strtok + qsort 问题的行中读取

Reading from lines with strtok + qsort problem

我想创建的是一个从 {key: value} 形式的外部文件中获取行的程序。例如,我们有文件 t.dat:

{myName: Mario}
{name2: Asdadas}
{someOtherData: _D123}

我的程序应该根据 key 的长度(在我们的例子中,myNamename2someOtherData 的长度以递减的方式对这些数据进行排序) 如果找到两个长度相同的键,则应根据 value.

按字典顺序对它们进行排序

我通过使用 struct array 来完成此操作,它将保留文档中每一行的数据:

typedef struct Line{
    char key[50];
    char value[50];
}Line;

并尝试使用 fgets(获取每一行)和 strtok.

从文件中取出数据

这是我的全部代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 512

typedef struct Line{
    char key[50];
    char value[50];
}Line;

int comp(const void* a, const void* b)
{
    const Line *aa = a;
    const Line *bb = b;
    puts(bb->key);
    if (strlen(aa->key) == strlen(bb->key)) {
        return strcmp(aa->key, bb->key);
    }
    return  strlen(bb->value)-strlen(aa->value);
}

int main(int argc, char** argv)
{
    if (argc != 2)
    {
        printf("Invalid number of args.\n");
        return -1;
    }
    FILE *f = fopen(argv[1], "rb");
    if (!f)
    {
        printf("Unable to open the specified file.\n");
        return -2;
    }
    
    Line* ln;

    char buff[MAX];
    int lineNumber = 0;
    int isSet = 0;
    int i = 0;
    while (fgets(buff, MAX, f))
    {
        char *p = strtok(buff, " {}:\n\r\t");
        while (p)
        {
            char word[MAX] = "";
            if (isSet == 0)
            {
                ln = malloc(1*sizeof(ln));
                isSet = 1;
            }
            else if (i == 0) ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));
            word[0] = '[=12=]';
            if (i == 0) {
                strcpy(word, p);
                strcpy(ln[lineNumber].key, word);
                i = 1;
            }
            else if (i == 1) {
                strcpy(word, p);
                strcpy(ln[lineNumber].value, word);
                lineNumber++;
                i = 0;
            }
            p = strtok(NULL, " {}:\n\r\t");
        }

    }

    qsort(ln, lineNumber, sizeof(ln), comp);
    puts("\n");
    for (int i = 0; i<lineNumber; i++)
    {
        printf("%s\n", ln[i].key);
    }
    return 0;
}

问题是,第一行的数据读取不正确(我指的是 value - "Mario"。它包含来自 key 的元素,但是当然不是 Mario 这个词)。认为这可能来自 strtok,但没有找到解决方案。

此外,使用提供的 comp 函数,数据排序不正确。它根本没有订购。输出与下单前一样。

我能做什么?谢谢你。如果需要更多详细信息,请告诉我,我会确保 post。

问题是

ln = (Line*)realloc(ln, (lineNumber+1)*sizeof(ln));

你想为 n 个元素保留空间,而不是为 n 个指向元素的指针保留空间,切换到

ln = realloc(ln, (lineNumber+1)*sizeof(*ln)); // Don't cast

另外,always use a temporary variablerealloc:

Line *temp = realloc(ln, (lineNumber+1)*sizeof(*ln));

if (temp == NULL)
{
    // raise error
}
ln = temp;

这里也一样

qsort(ln, lineNumber, sizeof(ln), comp);

每个元素占sizeof(*ln),不是sizeof(ln),转为

qsort(ln, lineNumber, sizeof(*ln), comp);