C语言中如何实现函数间结构体数组的数据共享?
C语言结构体数组跨函数数据共享问题解决
问题描述
在C语言编程中,编写了两个函数:AddProjet用于录入项目信息并存储在局部结构体数组TabProj中;AffEtudiant用于为指定项目分配两名学生。但调用AffEtudiant时,无法读取AddProjet中录入的项目主题、难度数据,显示垃圾值——尽管两个函数都定义了同名的结构体数组TabProj,但实际上它们是互相独立的局部变量,无法共享数据。
现有代码
typedef struct Projet { char theme[20]; int diff; char etudiant1[4]; // 分配给项目的学生1学号 char etudiant2[4]; // 分配给项目的学生2学号 }Projet; /****---录入项目信息的函数---****/ int AddProjet(int nmbProjet){ int rows; Projet TabProj[nmbProjet]; // 存储项目的数组 /* --循环录入项目信息-- */ for ( rows = 0; rows < nmbProjet; rows++) { printf("\t--> 项目%d主题 : ",rows+1); scanf(" %s",TabProj[rows].theme); printf("\t--> 难度[1-10] : "); scanf(" %i",&TabProj[rows].diff); printf("\n"); } } /*****************************************/ /****---为项目分配两名学生的函数---****/ int AffEtudiant(int nmbPrjAff){ int choix_prj_aff; Projet TabProj[nmbPrjAff];// 项目数组 puts("--> 选择一个项目:"); /***--循环列出用户已添加的所有项目--***/ for (int i = 0; i < nmbPrjAff; i++) { printf("\t%d- 项目%d :\n",i+1,i+1); printf("\t -> %s\n",TabProj[i].theme); printf("\t -> %d\n\n",TabProj[i].diff); } printf("--> 你的选择是: "); scanf("%d",&choix_prj_aff); printf("\n<------------------------->\n\n"); printf("--> 输入学生1的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant1); printf("--> 输入学生2的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant2); printf("\n<------------------------->\n\n"); } /*****************************************************/
问题根源
两个函数中的TabProj都是局部变量,存储在栈内存中。当AddProjet函数执行完毕后,它的TabProj数组会被销毁,内存被释放;而AffEtudiant里的TabProj是全新的未初始化数组,自然会读取到垃圾值。同名变量在不同函数的作用域中是完全独立的,无法自动共享数据。
解决方法
方法1:使用全局结构体数组
将TabProj定义在所有函数外部,作为全局变量,这样两个函数都能直接访问同一块内存区域。
修改示例:
#include <stdio.h> typedef struct Projet { char theme[20]; int diff; char etudiant1[4]; char etudiant2[4]; }Projet; // 定义全局数组,假设最多支持100个项目 Projet TabProj[100]; int totalProjets; // 记录实际项目数量 /****---录入项目信息的函数---****/ int AddProjet(int nmbProjet){ totalProjets = nmbProjet; int rows; for ( rows = 0; rows < nmbProjet; rows++) { printf("\t--> 项目%d主题 : ",rows+1); scanf(" %s",TabProj[rows].theme); printf("\t--> 难度[1-10] : "); scanf(" %i",&TabProj[rows].diff); printf("\n"); } return 0; } /****---为项目分配两名学生的函数---****/ int AffEtudiant(){ int choix_prj_aff; puts("--> 选择一个项目:"); for (int i = 0; i < totalProjets; i++) { printf("\t%d- 项目%d :\n",i+1,i+1); printf("\t -> %s\n",TabProj[i].theme); printf("\t -> %d\n\n",TabProj[i].diff); } printf("--> 你的选择是: "); scanf("%d",&choix_prj_aff); printf("\n<------------------------->\n\n"); printf("--> 输入学生1的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant1); printf("--> 输入学生2的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant2); printf("\n<------------------------->\n\n"); return 0; }
注意:全局变量会持续占用内存,且可能引发命名冲突,适合小型程序使用。
方法2:动态分配内存并传递指针
在主函数(或调用处)动态分配结构体数组的内存,然后将数组指针传递给两个函数,数据存储在堆内存中,不会随函数结束而销毁。
修改示例:
#include <stdio.h> #include <stdlib.h> typedef struct Projet { char theme[20]; int diff; char etudiant1[4]; char etudiant2[4]; }Projet; /****---录入项目信息的函数---****/ int AddProjet(Projet *TabProj, int nmbProjet){ int rows; for ( rows = 0; rows < nmbProjet; rows++) { printf("\t--> 项目%d主题 : ",rows+1); scanf(" %s",TabProj[rows].theme); printf("\t--> 难度[1-10] : "); scanf(" %i",&TabProj[rows].diff); printf("\n"); } return 0; } /****---为项目分配两名学生的函数---****/ int AffEtudiant(Projet *TabProj, int nmbPrjAff){ int choix_prj_aff; puts("--> 选择一个项目:"); for (int i = 0; i < nmbPrjAff; i++) { printf("\t%d- 项目%d :\n",i+1,i+1); printf("\t -> %s\n",TabProj[i].theme); printf("\t -> %d\n\n",TabProj[i].diff); } printf("--> 你的选择是: "); scanf("%d",&choix_prj_aff); printf("\n<------------------------->\n\n"); printf("--> 输入学生1的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant1); printf("--> 输入学生2的学号: "); scanf("%s",TabProj[choix_prj_aff-1].etudiant2); printf("\n<------------------------->\n\n"); return 0; } // 主函数示例 int main(){ int n; printf("输入项目数量: "); scanf("%d", &n); // 动态分配内存 Projet *projArray = (Projet*)malloc(n * sizeof(Projet)); if(projArray == NULL){ printf("内存分配失败\n"); return 1; } AddProjet(projArray, n); AffEtudiant(projArray, n); // 使用完毕后释放内存 free(projArray); return 0; }
这种方式更灵活,适合项目数量不确定的场景,且符合内存管理规范,避免全局变量的弊端。
方法3:将数组作为函数参数传递(变长数组)
如果编译器支持C99及以上标准,可以直接将变长数组作为参数传递,但需注意数组的生命周期要覆盖两个函数的调用。
示例:
// 主函数中定义数组,然后传递给两个函数 int main(){ int n; printf("输入项目数量: "); scanf("%d", &n); Projet TabProj[n]; // 变长数组 AddProjet(TabProj, n); AffEtudiant(TabProj, n); return 0; } // 修改AddProjet函数参数 int AddProjet(Projet TabProj[], int nmbProjet){ // 原逻辑不变,直接操作传入的数组 } // 修改AffEtudiant函数参数 int AffEtudiant(Projet TabProj[], int nmbPrjAff){ // 原逻辑不变,直接操作传入的数组 }
注意:变长数组存储在栈上,如果项目数量过大可能导致栈溢出,因此不适合大量数据的场景。
内容的提问来源于stack exchange,提问作者Yoshikage
相关产品推荐
相关产品推荐

