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

C语言中同一Struct变量在不同函数打印值不同的问题求助

问题原因与解决方法

核心问题

你遇到的问题完全是局部变量的作用域导致的:

  • getInfo函数里定义的Pgm pgm是栈上的局部变量,函数执行完毕后,这块内存会被系统回收,里面的数据会变成无效的垃圾值。
  • resolveMatrix函数里的Pgm pgm是另一个全新的局部变量,它的内存是重新分配的,初始值都是随机的,自然和getInfo里的结构体数据完全无关。

三种解决办法

方法一:使用全局变量(简单直接,适合小型程序)

把Pgm结构体变量定义在所有函数外部,让两个函数共享同一个实例:

#define MAX_HEIGHT 512
#define MAX_WIDTH 512
#define MAX_LINE 1024
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

typedef struct
{
  int lines;
  int cols;
  int highestValue;
  int matrix[MAX_WIDTH][MAX_HEIGHT];
} Pgm;

// 全局结构体变量,所有函数共享
Pgm pgm;

void getInfo()
{
  FILE *f = fopen("pepper.pgm", "r");
  if (!f) {
      printf("无法打开文件\n");
      return;
  }
  bool keepReading = true;
  int line = 0, countSpaces = 0, i = 0;
  char buffer[MAX_LINE];
  int total = 0;
  
  do
  {
    if (!fgets(buffer, MAX_LINE, f)) {
        keepReading = false;
        break;
    }
    // 补充PGM文件头读取逻辑
    if (line == 0) {
        // 跳过魔数行(比如P2),可加验证逻辑
    } else if (line == 1) {
        sscanf(buffer, "%d %d", &pgm.cols, &pgm.lines);
    } else if (line == 2) {
        sscanf(buffer, "%d", &pgm.highestValue);
    } else if (line >= 3)
    {
      char *values = strtok(buffer, " \n");
      while (values != NULL)
      {
        pgm.matrix[i][countSpaces] = atoi(values);
        countSpaces++;
        if (countSpaces == pgm.cols)
        {
          countSpaces = 0;
          i++;
        }
        if (i >= pgm.lines) break;
        values = strtok(NULL, " \n");
      }
    }
    line++;
  } while (keepReading);
  fclose(f);
  printf("cols: %d, lines: %d, highest: %d, matrix[0][0]: %d\n", pgm.cols, pgm.lines, pgm.highestValue, pgm.matrix[0][0]);
}

void resolveMatrix()
{
  printf("cols: %d, lines: %d, highest: %d\n", pgm.cols, pgm.lines, pgm.highestValue);
}

int main() {
    getInfo();
    resolveMatrix();
    return 0;
}

方法二:动态分配内存(灵活可控,适合大型程序)

在getInfo中用malloc分配结构体内存,返回指针给调用者,再传递给resolveMatrix,手动管理内存生命周期:

#define MAX_HEIGHT 512
#define MAX_WIDTH 512
#define MAX_LINE 1024
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

typedef struct
{
  int lines;
  int cols;
  int highestValue;
  int matrix[MAX_WIDTH][MAX_HEIGHT];
} Pgm;

Pgm* getInfo()
{
  Pgm *pgm = (Pgm*)malloc(sizeof(Pgm));
  if (!pgm) {
      printf("内存分配失败\n");
      return NULL;
  }
  FILE *f = fopen("pepper.pgm", "r");
  if (!f) {
      printf("无法打开文件\n");
      free(pgm);
      return NULL;
  }
  
  bool keepReading = true;
  int line = 0, countSpaces = 0, i = 0;
  char buffer[MAX_LINE];
  
  do
  {
    if (!fgets(buffer, MAX_LINE, f)) {
        keepReading = false;
        break;
    }
    if (line == 0) {
        // 处理魔数行
    } else if (line == 1) {
        sscanf(buffer, "%d %d", &pgm->cols, &pgm->lines);
    } else if (line == 2) {
        sscanf(buffer, "%d", &pgm->highestValue);
    } else if (line >= 3)
    {
      char *values = strtok(buffer, " \n");
      while (values != NULL)
      {
        pgm->matrix[i][countSpaces] = atoi(values);
        countSpaces++;
        if (countSpaces == pgm->cols)
        {
          countSpaces = 0;
          i++;
        }
        if (i >= pgm->lines) break;
        values = strtok(NULL, " \n");
      }
    }
    line++;
  } while (keepReading);
  fclose(f);
  printf("cols: %d, lines: %d, highest: %d, matrix[0][0]: %d\n", pgm->cols, pgm->lines, pgm->highestValue, pgm->matrix[0][0]);
  return pgm;
}

void resolveMatrix(Pgm *pgm)
{
  if (!pgm) return;
  printf("cols: %d, lines: %d, highest: %d\n", pgm->cols, pgm->lines, pgm->highestValue);
}

int main() {
    Pgm *pgm = getInfo();
    if (pgm) {
        resolveMatrix(pgm);
        free(pgm); // 用完必须释放内存,防止泄漏
    }
    return 0;
}

方法三:指针传递结构体(最推荐,无全局变量无内存泄漏)

在主函数定义结构体变量,通过指针传递给两个函数,操作同一个实例:

#define MAX_HEIGHT 512
#define MAX_WIDTH 512
#define MAX_LINE 1024
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

typedef struct
{
  int lines;
  int cols;
  int highestValue;
  int matrix[MAX_WIDTH][MAX_HEIGHT];
} Pgm;

void getInfo(Pgm *pgm)
{
  if (!pgm) return;
  FILE *f = fopen("pepper.pgm", "r");
  if (!f) {
      printf("无法打开文件\n");
      return;
  }
  
  bool keepReading = true;
  int line = 0, countSpaces = 0, i = 0;
  char buffer[MAX_LINE];
  
  do
  {
    if (!fgets(buffer, MAX_LINE, f)) {
        keepReading = false;
        break;
    }
    if (line == 0) {
        // 处理魔数行
    } else if (line == 1) {
        sscanf(buffer, "%d %d", &pgm->cols, &pgm->lines);
    } else if (line == 2) {
        sscanf(buffer, "%d", &pgm->highestValue);
    } else if (line >= 3)
    {
      char *values = strtok(buffer, " \n");
      while (values != NULL)
      {
        pgm->matrix[i][countSpaces] = atoi(values);
        countSpaces++;
        if (countSpaces == pgm->cols)
        {
          countSpaces = 0;
          i++;
        }
        if (i >= pgm->lines) break;
        values = strtok(NULL, " \n");
      }
    }
    line++;
  } while (keepReading);
  fclose(f);
  printf("cols: %d, lines: %d, highest: %d, matrix[0][0]: %d\n", pgm->cols, pgm->lines, pgm->highestValue, pgm->matrix[0][0]);
}

void resolveMatrix(Pgm *pgm)
{
  if (!pgm) return;
  printf("cols: %d, lines: %d, highest: %d\n", pgm->cols, pgm->lines, pgm->highestValue);
}

int main() {
    Pgm pgm;
    getInfo(&pgm);
    resolveMatrix(&pgm);
    return 0;
}

补充注意点

原代码还有几个隐性问题需要修正:

  1. 缺失buffer、total、MAX_LINE的定义,必须补充。
  2. 没有处理文件打开失败的情况,建议增加判断逻辑。
  3. 原代码未读取PGM文件的前3行(魔数、宽高、最高值),导致pgm.cols和pgm.lines初始值随机,会引发矩阵越界,必须先正确读取文件头。

内容的提问来源于stack exchange,提问作者SadAutist

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:10:36