在 c 中使用 qsort 对结构进行排序时解决边界错误

address boundary error while sorting struct with qsort in c

我有一个结构,我想按 ID 对其进行排序,然后删除具有 NULL ID 的条目。但是我收到地址边界错误。不太确定是什么问题。

typedef struct data_id
{
char* id;
int marker;
int key;
} data_id;

我的比较功能:

int cmp(const void *p1, const void *p2)
{
const data_id *v1 = (data_id *)p1;
const data_id *v2 = (data_id *)p2;
if (v1->id < v2->id)
    return -1;
else if (v1->id > v2->id)
    return +1;
else
    return 0;
}

我在主函数中调用 qsort 时使用:

qsort(nodeList, num_id, sizeof(nodeList),cmp);

num_id 是条目的 number

But anyway you need to show a minimal reproducible example

我正在从标准输入读取数据并创建列表。

void create_list(input){
nodeList  = realloc(nodeList, sizeof *nodeList * 10000);
if (input == 65) // A
{
    stop_flag = true;
    s_flag = true;
}
else if (input == 73) // I
{
    moves_flag = true;
}
else if (s_flag == true && (islower(input) || isdigit(input)))
{
    start_node = input;
    s_flag = false;
}
else if (moves_flag == true && isdigit(input))
{
    num_moves = (char)input - '0';
    moves_flag = false;
}
else if ((islower(input) || isdigit(input)) && !stop_flag )
{
    if (m_flag == true && isdigit(input))
    {
        nodeList[tmp_id].marker = digitconcat(nodeList[tmp_id].marker,input);
    }
    else if (m_flag == false && (isdigit(input)||islower(input)))
    {
        buffer[0] = (char)input;
        if (buffer_size == 0)
        {
            nodeList[num_id].id = strconcat(1, buffer);
            buffer_size++;
        }
        else
            nodeList[num_id].id = strconcat(2, nodeList[num_id].id, buffer);
        m_flag = false;
    }
}
else if (input == '-' && !stop_flag)
{
    m_flag = true;
}
else if (input == '\n' && !stop_flag)
{
    tmp_id++;
    num_id++;
    buffer_size = 0;
    nodeList[tmp_id].marker = 0;
    nodeList[num_id].key = num_id;
    m_flag = false;
}
else if ((input == ',' || input == ':') && !stop_flag)
{
    buffer_size = 0;
    num_id++;
    nodeList[tmp_id].marker = 0;
    nodeList[num_id].key = num_id;
    m_flag = false;
} 
}

字符串和数字的连接函数是:

unsigned digitconcat(unsigned x, unsigned y)
{
y = (char)y - '0';
unsigned pow = 10;
while (y >= pow)
    pow *= 10; 
return x * pow + y;
}

char *strconcat(int count, ...)
{
va_list ap;
int i;

// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for (i = 0; i < count; i++)
    len += strlen(va_arg(ap, char *));
va_end(ap);

// Allocate memory to concat strings
char *merged = calloc(sizeof(char), len);
int null_pos = 0;

// Actually concatenate strings
va_start(ap, count);
for (i = 0; i < count; i++)
{
    char *s = va_arg(ap, char*);
    strcpy(merged + null_pos, s);
    null_pos += strlen(s);
}
va_end(ap);
return merged;
}

示例输入可以是:

aqwe:b66,g
b66:g,l-23452
asfag:l
l:-2424
A:g
I:5

:,LF 分隔的字符串是 IDs。在 - 之后跟随标记。最后两行不需要保存在列表中。

我也不知道为什么我的列表的最后一个条目被添加到它,因为我专门设置了 stop_flag,停止添加 IDKeyMarker 到达倒数第二行的 A 之后。

What is nodeList?

数据应该表示图表。 nodes:,LF 分隔。 weight(marker) 是破折号后面的数字,它属于它所在行的第一个节点。此外,我给每个节点一个特定的 'key'。哦,同一条线上的每个节点都已连接。所以 nodeList 是存储图中每个节点信息的数组。

但我只是认为也许数组不是存储数据的最佳数据结构,因为它更难去除重复项。

所以我最终没有使用 qsort,而是在一些帮助下自己写了一个:

void sort()
{
    data_id tmp;
    for (int i = 0; i < num_id; ++i)
    {
        for (int j = i + 1; j < num_id; ++j)
        {
            // swapping strings if they are not in the lexicographical order
            if (strcmp(nodeList[i].id, nodeList[j].id) > 0)
            {
                tmp = nodeList[i];
                nodeList[i] = nodeList[j];
                nodeList[j] = tmp;
            }
        }
    }
}

读取所有内容后调用该函数。