有人可以向我解释如何访问 void** 数组内的 void* 项目,考虑到 void** 属于结构

如何解决有人可以向我解释如何访问 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) 函数内的 Removereturn (int)(key - item->matricula) 内的 Compar1。 此外,如果您能指出一些文章/文档/任何有助于我理解如何处理此类问题的内容,我将不胜感激。

解决方法

以下是我在 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]
    • 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;
}

此外,这个来自 colRemovemain 调用是不正确的:

            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->enrollCodereturn 语句中的表达式 compar1 可能会溢出。我建议把它改成这样:

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res