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; }
补充注意点
原代码还有几个隐性问题需要修正:
- 缺失
buffer、total、MAX_LINE的定义,必须补充。 - 没有处理文件打开失败的情况,建议增加判断逻辑。
- 原代码未读取PGM文件的前3行(魔数、宽高、最高值),导致
pgm.cols和pgm.lines初始值随机,会引发矩阵越界,必须先正确读取文件头。
内容的提问来源于stack exchange,提问作者SadAutist
相关产品推荐
相关产品推荐

