【问题标题】:Removing structs from array从数组中删除结构
【发布时间】:2018-09-13 12:35:17
【问题描述】:

我正在尝试实现一个函数,该函数循环遍历已排序的结构数组,如果“键”(第一个字段值)有重复项,它将保留该键值对的第一次迭代,并删除之后出现的任何重复项。这是我的代码:

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

struct Map * collect_values(int n, int *arr);
void sort_values(struct Map *ptr, int n);
void print(struct Map *print_struct, int n);
struct Map * remove_duplicates(struct Map *ptr, int n);

struct Map{
    int value, position;
};

int compare(const void *ptr1, const void *ptr2){
    const struct Map *aptr = ptr1;
    const struct Map *bptr = ptr2;

    if(aptr->value == bptr->value){
        return (aptr->position > bptr->position) - 
(aptr->position < bptr->position);
    }
    else{
        return (aptr->value > bptr->value) - (aptr->value < bptr->value);
    }
}

int compare2(const void *aptr, const void *bptr){
    int a = ((struct Map*)aptr)->position, b = ((struct 
Map*)bptr)->position;
    return (a > b) - (a < b);
}

int main(){
    int size, i;
    scanf("%d", &size);
    int *arr = (int*) malloc(size*sizeof(int));
    struct Map *p = collect_values(size,arr);
    printf("Struct before sorting:\n");
    print(p,size);
    qsort(p,size,sizeof(struct Map),compare);
    printf("Struct after sorting\n");
    print(p,size);
    struct Map *p2 = remove_duplicates(p,size);
    printf("\nStruct after removing in the main\n");

    for(i = 0; i < sizeof(*p2); i++){
         printf("%d : %d\n", p2[i].value, p2[i].position);
    }
    free(p);
    free(arr);
    free(p2);
    return 0;
 }

struct Map * collect_values(int n, int *arr){
    int i, position = 0;
    struct Map *array = calloc(n,sizeof(*array));
    for(i = 0; i < n; i++){
        scanf("%d",&arr[i]);
        array[i].value = arr[i];
        array[i].position = position;
        position++;
    }
    return array;

}

void print(struct Map * print_struct, int n){
    int i;
    for (i = 0; i < n; i++){
        printf("%d : %d\n", print_struct[i].value, print_struct[i].position);
    }
}

struct Map * remove_duplicates(struct Map *ptr, int n){
    int i, j = 0, newsize;
    struct Map *new_struct = calloc(n,sizeof(*new_struct));
    new_struct[0] = ptr[0];
    for(i = 1; i < n; i++){
        if(ptr[j].value != ptr[i].value){
            j++;
            new_struct[j].value = ptr[i].value;
            new_struct[j].position = ptr[i].position;
        }
    }
    newsize = j+1;
    //new_struct = realloc(new_struct, newsize);

    printf("\nSorting in the function:\n");
    for(i = 0; i < newsize; i++){
        printf("%d : %d\n", new_struct[i].value, new_struct[i].position);
    }
    return new_struct;
}

在 remove_duplicates() 函数中,我希望这是我的结果:

-3 : 3
1 : 9
3 : 2
4 : 1
5 : 4
7 : 6
25 : 0
88 : 7

但是,我得到了一个额外的键值 5:5,它没有被删除:

-3 : 3
1 : 9
3 : 2
4 : 1
5 : 4
5 : 5
7 : 6
25 : 0
88 : 7

我试图手动遍历它,我认为我在使用 j++ 时犯了一个错误,因为它似乎当条件为假时(即有重复),我在 j 留在后面时迭代,我认为这可能就是为什么我要删除重复的 4 而不是重复的 5。

我哪里错了?我也觉得硬编码索引 0 处的值很奇怪,但显然第一个值不是我想要删除的值(只有重复的后续值需要删除),并且由于 i 从 1 开始,它不会没有比较。

最后,remove_duplicate() 函数返回一个 struct * 类型。当我从主打印时,我得到以下输出:

-3 : 3
1 : 9
3 : 2
4 : 1
5 : 4
5 : 5
7 : 6
25 : 0

由于某种原因没有指向最后一个值。我希望我的删除函数可以从主函数访问,因为我想将指针 p2 传递给另一个按键值对中的值排序的函数。我的上一个值发生了什么变化?

使用输入和预期输出进行编辑

输入是一个 int 值数组,我将其转换为一个值结构体 position。所以例如输入是[25,4,3,-3,5,5,7,88,4,1],创建的结构是:

 25 : 0
 4 : 1
 3 : 2
-3 : 3
 5 : 4
 5 : 5
 7 : 6
88 : 7
 4 : 8
 1 : 9

我的代码按结构的值字段对值进行排序,然后删除任何重复的键值对。所以预期的结果是:

-3 : 3
 1 : 9
 3 : 2
 4 : 1
 5 : 4
 7 : 6
25 : 0
88 : 7

删除重复对 (4,8) 和 (5,5) 的位置。

【问题讨论】:

  • “删除”到底是什么意思?您能否提供一个输入示例和您的预期输出?
  • 使用输入和预期输出编辑帖子。
  • 问题出在:if(ptr[j].value != ptr[i].value)。只需使用较小的集合(例如 4 4 5 5)逐步完成它,您就会很快看到发生了什么。修复很简单,所以我会留给你。
  • 您可能想阅读以下内容:How to debug small programs
  • 如果你想知道为什么程序的最终输出总是8行,那是由sizeof(*p2)引起的。

标签: c struct


【解决方案1】:

这是你的预期输出吗

Struct before sorting:
25 : 0
4 : 1
3 : 2
-3 : 3
5 : 4
5 : 5
7 : 6
88 : 7
4 : 8
1 : 9
Struct after sorting
-3 : 3
1 : 9
3 : 2
4 : 1
4 : 8
5 : 4
5 : 5
7 : 6
25 : 0
88 : 7

Sorting in the function:
-3 : 3
1 : 9
3 : 2
4 : 1
5 : 4
7 : 6
25 : 0
88 : 7

Struct after removing in the main
-3 : 3
1 : 9
3 : 2
4 : 1
5 : 4
7 : 6
25 : 0
88 : 7

只需在 remove_duplicate() 中将 if 条件从 if(ptr[j].value != ptr[i].value) 更改为 if(new_struct[j].value != ptr[i].value)。

【讨论】:

  • 这正是我想要的。我试图指出,它不仅在 remove_duplicate() 函数中没有正确删除,而且在主函数中工作不正常并且工作方式不同(不打印最后一个结构)。它在这两个功能中的工作方式应该相同。我需要将该指针正确返回给 main,以便稍后将其传递给不同的函数。
  • 请问,这如何回答这个问题?
  • 只需将 if 条件从 if(ptr[j].value != ptr[i].value) 更改为 if(new_struct[j].value != ptr[i].value) in remove_duplicate().
  • 没关系。我不知道我在说什么。那行得通。
猜你喜欢
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2021-09-07
  • 1970-01-01
  • 2012-11-21
  • 2020-09-04
  • 2018-06-29
  • 1970-01-01
相关资源
最近更新 更多