【问题标题】:Copy into a struct the values of an array of char pointers将 char 指针数组的值复制到结构中
【发布时间】:2020-01-04 09:12:01
【问题描述】:

我目前正在开发一个简单的 DMBS 作为大学项目。在 qsort 函数发生后,我在重建列表时遇到了一些问题。

typedef struct S_Column{
    char field[32];
    struct S_Column *next;
} column;

void sort(column *head, int table_size){
    char *array[table_size];
    int array_counter=0;

    column *sort_cursor;
    sort_cursor=head;

    //build the array of pointers
    while(sort_cursor->next!=NULL){
        array[array_counter] = sort_cursor->field;
        sort_cursor=sort_cursor->next;
        array_counter++;
    }

    //sorting
    qsort(array, array_counter, sizeof(char*), stringCompare);
    sort_cursor=head;

    //rebuild the list
    for(int i = 0; i<array_counter; i++){
        printf("SORTED elem %d: %s\n", i, array[i]);
        strcpy(sort_cursor->field, array[i]);
        sort_cursor=sort_cursor->next;
    }


    free(sort_cursor);
}
static int stringCompare(const void* str1, const void* str2){
    return strcmp(*(const char**)str1, *(const char**)str2); 
}

在排序函数中,我在将array[i] 的值复制到结构字段sort_cursor-&gt;field 时遇到问题。

特别是在//rebuild the list 部分,当我从array[i] 变量或sort_cursor-&gt;field 变量中打印出值时,输出包含复制值。

我注意到,如果我删除该部分中的 strcpy 函数,它会正确打印出所有内容。

我的目标是拥有一个column 类型的列表,其中包含正确排序的值。

【问题讨论】:

  • 我在这里遗漏了一些东西:您已经描述的删除 strcpy 调用不是您正在寻找的解决方案,这是怎么回事?
  • 我想从指针数组array 中获取值并使用这些值构建结构。

标签: c sorting pointers


【解决方案1】:

也许您应该使用一个数组来存储field 的字符串值,而不是指针。

因为当你在rebuild the list 部分做strcpy(sort_cursor-&gt;field, array[i]); 时,实际上sort_cursor-&gt;field 必须等于array[x] 的一个指针,你在build the array of pointers 部分做分配array[array_counter] = sort_cursor-&gt;field;

假设head->字段等于array[5],所以当你做strcpy时,你实际上把array[0]放到array[5],然后i++,array[1]放到array[ 2]等。

这就是重复值的原因。

【讨论】:

  • 非常感谢先生!我已将//build the array of pointers 更改为:array[array_counter] = strdup(sort_cursor-&gt;field); 现在它可以完美运行!
【解决方案2】:

总体问题似乎是用字符数组值对链表进行排序,这些值似乎被假定包含字符串。提供的代码尝试通过形成一个指向字符串的指针数组、使用qsort() 对该数组进行排序、然后使用strcpy 将值复制到它们的排序位置来实现这一点。

在考虑为什么这不起作用时,应该考虑加载数组和卸载数组之间的不对称性。您通过复制指针来加载数组,并通过复制它们指向的数据来读出结果。这本质上不是问题,但在您的特定情况下,您将复制出的结果存储在其他指针指向的位置。这类似于尝试在没有临时的情况下执行交换:

// not a viable swap implementation:
int a = 1, b = 2;
a = b;  // The original value of a is lost here, so
b = a;  // this does not have the effect that was naively intended

如果您的链表元素包含指针而不是数组本身,那么您的排序函数中的array 数组和由qsort 管理的存储将充分充当临时角色。然后,您可以通过赋值将指针复制回来,与复制它们的方式对称(没有strcpy)。

如果不能改变结构,但可以改变sort()函数的签名,那么可以考虑直接对链表进行排序,适当重写链接。因为这可能会改变哪个节点是列表头,但是您需要该函数返回新头或接受双指针,以便它可以直接更新调用者的列表头指针。合并排序速度快,可扩展性好,并且易于为链表实现。您不需要任何复制输入/复制输出操作。

如果您必须使用qsort() 并且您不能修改函数签名,那么您最好的选择可能是对实际数组值进行排序,而不是对它们的指针进行排序。像这样的:

// Dynamic allocation is wisest if table_size is not sure to be small
char (*array)[32] = malloc(table_size * sizeof(*array));

int array_counter;
column *sort_cursor;

// populate the array of values
array_counter = 0;
for (sort_cursor = head; sort_cursor; xort_cursor = sort_cursor->next) {
    strcpy(array[array_counter++], sort_cursor->field);
}

// sort the array with qsort
qsort(array, array_counter, sizeof(*array), arrayCompare);

// copy the values back out
array_counter = 0;
for (sort_cursor = head; sort_cursor; xort_cursor = sort_cursor->next) {
    strcpy(sort_cursor->field, array[array_counter++]);
}

// Mustn't forget to free the array
free(array);

依赖于

static int arrayCompare(const void* str1, const void* str2) {
    return strcmp(*(const char (*)[32])str1, *(const char (*)[32])str2); 
}

【讨论】:

    猜你喜欢
    • 2013-05-15
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 2023-03-08
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多