You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:00:56