c-有人能向我解释一下,考虑到void**属于结构,我如何访问void**数组中的void*项吗


#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 collectionn");
}
}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;
}

--->正如你所意识到的,至少在这一点上,我试图做的是使用某种注册代码访问和删除学生收藏(void**-arr(的一个项目(student*,最初假设为void*类型(。然而,我在Segmentation Fault方面遇到了问题,无法理解为什么以及如何解决这些问题,因此我提出了这个问题。调试代码时,我发现错误位于:Remove函数内的if(ptrCompar((void)key, (void**)*c->arr[i]) == 0)Compar1函数内的return (int)(key - item->matricula)。此外,如果你能给我指出一些文章/文档/任何有助于我理解如何处理这样的问题的东西,我将不胜感激。

以下是我在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]c->arr[i + 1],而不是c->arr[j]c->arr[j + 1]
    • CCD_ 23可能在最后一个元素之后进行访问。这可能是因为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;
}

此外,maincolRemove的调用不正确:

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

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

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

或者,删除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在对该问题的评论中所指出的,compar1return语句中的表达式key - item->enrollCode可能溢出。我建议把它改成这样:

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

或者将其更改为使用这种狡猾的伎俩:

return (key > item->enroleCode) - (key < item->enroleCode);

最新更新