如何解决有人可以向我解释如何访问 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 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;
}
---> 正如你所意识到的,我正在尝试做的,至少在这一点上,是访问和删除一个项目(student*
最初将假定为 void*
类型)使用某种注册代码的学生集合(void**
arr)。但是,我遇到了 Segmentation Fault 问题,无法理解为什么以及如何解决这些问题,因此我的问题就在那里。调试代码我发现错误位于:if(ptrCompar((void)key,(void**)*c->arr[i]) == 0)
函数内的 Remove
和 return (int)(key - item->matricula)
内的 Compar1
。
此外,如果您能指出一些文章/文档/任何有助于我理解如何处理此类问题的内容,我将不胜感激。
解决方法
以下是我在 colRemove
中看到的问题:
- (其实不是问题,只是风格问题)虽然函数参数
int compar1(void* a,void* b)
没问题,但使用语法int (*compar1)(void* a,void* b)
更传统。 - (其实不是问题)让
compar1
和ptrCompar
都指向同一个函数是多余的。最好将参数命名为ptrCompar
以避免读者与代码中其他地方定义的compar1
函数混淆。 - 该函数应该是通用的,不应将
student*
用于eleRemoved
变量。也许那只是为了调试?应该是void*
。 - 找到要移除的元素后,剩下的代码全错了:
-
c->num_itens_curr
尚未减少以减少项目数。 - 代码正在访问
c->arr[i]
和c->arr[i + 1]
,而不是c->arr[j]
和c->arr[j + 1]
。 -
c->arr[j + 1]
可能正在访问最后一个元素之外的元素,因为循环终止条件为 1。这可能是因为c->num_itens_curr
没有减少。 - 赋值
c->arr[j + 1] = 0;
并不是真正需要的,因为除了最后一个元素之外的所有元素都将在下一次迭代中被覆盖,而旧的最后一个元素的值并不重要,因为项目的数量应该减少1。
-
- (其实不是问题)函数中没有必要使用类型转换操作(例如将
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;
}
此外,这个来自 colRemove
的 main
调用是不正确的:
studentRemoved = (student*)colRemove(c,&removeEnroll,compar1(&removeEnroll,c->arr[0]));
最后一个参数应该是一个指向 compar1
函数的指针,但代码实际上是将调用的结果传递给 compar1
类型的 int
函数。应该改成这样:
studentRemoved = (student*)colRemove(c,compar1);
或者,删除不必要的 void*
到 student*
的类型转换:
studentRemoved = colRemove(c,compar1);
colInsert
函数也应该是通用的,所以不应该使用这种不合适的类型转换为 student*
:
c->arr[c->num_itens_curr] = (student*)item;
也许这也是出于调试目的,但它应该只是按原样使用 item
:
c->arr[c->num_itens_curr] = item;
正如@chux 在对该问题的评论中所指出的,key - item->enrollCode
的 return
语句中的表达式 compar1
可能会溢出。我建议把它改成这样:
return key < item->enroleCode ? -1 : key > item->enrolCode ? 1 : 0;
或者改变它以使用这个鬼鬼祟祟的技巧:
return (key > item->enroleCode) - (key < item->enroleCode);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。