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

typedef struct student{
            int grade;
            int enrollCode;
}student;

typedef struct colVoidStar{
            int capacity;
            int num_itens_curr;
            void **arr;
            int current_pos;
}colVoidStar;

colVoidStar *colCreate(int capacity){
    if(capacity > 0){
        colVoidStar *c = malloc(sizeof(colVoidStar));
        if(c != NULL){
            c->arr = (void**)malloc(sizeof(void*)*capacity);
            if( c->arr != NULL){
                c->num_itens_curr = 0;
                c->capacity = capacity;
                return c;
            }
            free(c->arr);
        }
        free(c);
    }
    return NULL;
}


int colInsert(colVoidStar *c, void *item){
    if(c != NULL){
        if(c->num_itens_curr < c->capacity){
            c->arr[c->num_itens_curr] = (student*)item;
            c->num_itens_curr++;
            return 1;
        }
    }
    return 0;
}


void *colRemove(colVoidStar *c, void *key, int compar1(void* a, void* b)){
    int(*ptrCompar)(void*, void*) = compar1;
    student* eleRemoved;
    if(c != NULL){
        if(c->num_itens_curr > 0){
            int i = 0;
            for(i; i < c->num_itens_curr; i++){
                if(ptrCompar((void*)key, (void*)c->arr[i]) == 0){
                   eleRemoved = (student*)c->arr[i];
                   for(int j = i; j < c->num_itens_curr; j++){
                        c->arr[i] = c->arr[i + 1];
                        c->arr[i + 1] = 0;
                    }
                   return (void*)eleRemoved;
                }
                return NULL;
            }
        }
    }
    return NULL;
}

int compar1(void *a, void*b){
    int key;
    student *item;
    key = *(int*)a;
    item = (student*)b;
    return (int)(key - item->enrollCode);
}


int main(){
int finishProgram = 0, choose, capacity, returnInsert, removeEnroll;
colVoidStar *c;
student *a, *studentRemoved;
while(finishProgram != 9){
    printf("-----------------panel-----------------------\n");
    printf("Type: \n");
    printf("[1] to create a collection;\n");
    printf("[2] to insert a student;\n");
    printf("[3] to remove some student of collection;\n");
    printf("--------------------------------------------------------\n");
    scanf("%d", &choose);
    switch(choose){
        case 1:
            printf("Type the maximum of students the collection will have: \n");
            scanf("%d", &capacity);
            c = (colVoidStar*)colCreate(capacity);
            if(c == NULL){
                printf("Error in create collection!\n");
            }
            break;
        case 2:
            if(c->num_itens_curr < capacity){
                a = (student*)malloc(sizeof(student));
                printf("%d student:(type the Grade and the Enroll code, back-to-back)\n", c->num_itens_curr + 1);
                scanf("%d %d", &a->grade, &a->enrollCode);
                returnInsert = colInsert(c, (void*)a);
                if(returnInsert == 1){
                    for(int i = 0; i < c->num_itens_curr; i++){
                        printf("The student added has grade = %d e enrollCode = %d \n", (((student*)c->arr[i])->grade), ((student*)c->arr[i])->enrollCode);
                    }

                }else{
                    printf("the student wasn't added in the collection\n");
                }
            }else{
                printf("it's not possible to add more students to the colletion, since the limit of elements was reached!");
            }
            break;
        case 3:
            printf("Type an enrollcode to remove the student attached to it:\n");
            scanf("%d", &removeEnroll);
            studentRemoved = (student*)colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));
            if(studentRemoved != NULL)
                printf("the student removed has grade = %d and enrollcode %d.", studentRemoved->grade, studentRemoved->enrollCode);
            else
                printf("the number typed wasn't found");
            break;

    }
}
 return 0;
}

---> 正如您所意识到的,至少在这一点上,我正在尝试做的是使用某种注册代码访问和删除学生集合( arr)的项目(student*最初将假定一种类型) . 但是,我遇到了分段错误问题,无法理解为什么以及如何解决它们,因此我的问题就在那里。调试代码我发现错误在于:函数内部和. 此外,如果您能指出一些文章/文档/任何有助于我理解如何处理此类问题的内容,我将不胜感激。void*void**if(ptrCompar((void)key, (void**)*c->arr[i]) == 0)Removereturn (int)(key - item->matricula)Compar1

4

1 回答 1

0

以下是我看到的问题colRemove

  1. (其实不是问题,只是风格问题)虽然函数参数int compar1(void* a, void* b)还可以,但使用语法更常规int (*compar1)(void* a, void* b)
  2. (不是真正的问题)同时拥有compar1ptrCompar指向相同的功能是多余的。最好命名参数以避免读者与代码中其他地方定义的函数ptrCompar混淆。compar1
  3. 该函数应该是通用的,不应该student*用于eleRemoved变量。也许那只是为了调试?应该是void*
  4. 找到要移除的元素后,剩下的代码都是错误的:
    • c->num_itens_curr没有被递减以减少项目的数量。
    • 代码正在访问c->arr[i]andc->arr[i + 1]而不是c->arr[j]and c->arr[j + 1]
    • c->arr[j + 1]可能正在访问超出最后一个元素,因为循环终止条件关闭 1。这可能是因为c->num_itens_curr没有递减。
    • 分配c->arr[j + 1] = 0;并不是真正需要的,因为除了最后一个元素之外的所有元素都将在下一次迭代中被覆盖,并且旧的最后一个元素的值无关紧要,因为项目的数量应该减少 1。
  5. (不是真正的问题)函数中没有必要使用类型转换操作(例如转换void *void *)。

这是该函数的更正且可能改进的版本(使用更少的变量):

void *colRemove(colVoidStar *c, void *key, int (*ptrCompar)(void* a, void* b)){
    void* eleRemoved = NULL;
    if(c != NULL){
        int i;
        /* Look for item to be removed. */
        for(i = 0; i < c->num_itens_curr; i++){
            if(ptrCompar(key, c->arr[i]) == 0){
                /* Found it. */
                eleRemoved = c->arr[i];
                c->num_itens_curr--;    /* There is now one less item. */
                break;
            }
        }
        /* Close the gap. */
        for(; i < c->num_itens_curr; i++){
            c->arr[i] = c->arr[i + 1];
        }
    }
    return eleRemoved;
}

另外,这个colRemovefrom调用main是不正确的:

            studentRemoved = (student*)colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));

最后一个参数应该是指向compar1函数的指针,但代码实际上是将调用的结果传递给compar1类型为 的函数int。应该改成这样:

            studentRemoved = (student*)colRemove(c, &removeEnroll, compar1);

或者,删除 to 的不必要的类型void*转换student*

            studentRemoved = colRemove(c, &removeEnroll, compar1);

colInsert函数也应该是通用的,因此不应使用这种不适当的类型转换student*

            c->arr[c->num_itens_curr] = (student*)item;

也许这也是出于调试目的,但它应该按item原样使用:

            c->arr[c->num_itens_curr] = item;

正如@chux在对问题的评论中指出的那样,语句中key - item->enrollCode的表达式可能会溢出。我建议将其更改为以下内容:returncompar1

   return key < item->enroleCode ? -1 : key > item->enrolCode ? 1 : 0;

或更改它以使用这个鬼鬼祟祟的技巧:

   return (key > item->enroleCode) - (key < item->enroleCode);
于 2021-07-07T13:50:57.790 回答