【发布时间】: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)引起的。