C语言二维数组输出异常求助:学生信息存储后打印结果不符
问题根源与修复方案
嘿,你的问题出在指针数组没有分配有效内存,加上一些小的参数和循环错误,导致内存越界和乱码输出。咱们一步步拆解:
核心错误分析
- 野指针问题:你定义的
char *Grades[1][6]是一个指针数组,但里面的每个指针都是「野指针」——它们没有指向任何可以存储字符串的内存空间。当你用scanf(" %s",&Grades[line][column]);时,实际上是把输入的字符串直接写到了指针本身的内存位置(而不是指针应该指向的缓冲区),这会覆盖相邻指针的内容,导致打印出拼接的乱码(比如BigFirstBigLastN18就是名字字符串覆盖了后面的指针内存)。 - scanf参数错误:
%s格式符需要接收一个char*类型的参数,但你传了&Grades[line][column],这是char**类型,类型不匹配,而且直接操作指针的内存本身就是危险行为。 - 循环越界:你只存储了6个元素,但循环写了
p<7,会访问不存在的第7个元素,导致未定义行为。
修复方案1:使用固定大小的二维字符数组(简单直接)
这种方式适合提前知道字符串最大长度的场景,直接为每个元素分配足够的缓冲区:
#include <stdio.h> // 定义二维字符数组:1行6列,每个元素最多存50个字符(含结束符'\0') char Grades[1][6][50]; int line = 0; int column = 0; int main(void) { printf("Input Firstname \n"); // 用%49s限制输入长度,防止缓冲区溢出(留1位给结束符) scanf(" %49s", Grades[line][column]); column += 1; printf("Input Lastname \n"); scanf(" %49s", Grades[line][column]); column += 1; printf("Input age "); scanf(" %49s", Grades[line][column]); column += 1; printf("Input Math Grade \n"); scanf(" %49s", Grades[line][column]); column += 1; printf("Input Physics Grade \n"); scanf(" %49s", Grades[line][column]); column += 1; printf("Input Average Between the two \n"); scanf(" %49s", Grades[line][column]); column += 1; // 循环次数改为6,匹配存储的元素数量 int p; for (p = 0; p < 6; p++) { printf("%s\n", Grades[0][p]); } return 0; }
修改点说明:
- 把指针数组改成
char Grades[1][6][50],每个元素都是现成的字符缓冲区 - 去掉scanf参数里的
&,直接传Grades[line][column](它本身就是char*类型) - 用
%49s限制输入长度,避免缓冲区溢出 - 循环次数从7改为6,防止越界访问
修复方案2:动态分配内存(灵活适配任意字符串长度)
如果不确定输入字符串的长度,可以用动态内存分配,避免浪费空间:
#include <stdio.h> #include <stdlib.h> #include <string.h> char *Grades[1][6]; int line = 0; int column = 0; int main(void) { char buffer[100]; // 临时缓冲区存输入内容 printf("Input Firstname \n"); scanf(" %99s", buffer); // 按输入字符串的实际长度分配内存(+1是为了存储结束符'\0') Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; printf("Input Lastname \n"); scanf(" %99s", buffer); Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; printf("Input age "); scanf(" %99s", buffer); Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; printf("Input Math Grade \n"); scanf(" %99s", buffer); Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; printf("Input Physics Grade \n"); scanf(" %99s", buffer); Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; printf("Input Average Between the two \n"); scanf(" %99s", buffer); Grades[line][column] = malloc(strlen(buffer) + 1); if (Grades[line][column] == NULL) { perror("Failed to allocate memory"); return 1; } strcpy(Grades[line][column], buffer); column += 1; // 打印并释放内存(避免内存泄漏) int p; for (p = 0; p < 6; p++) { printf("%s\n", Grades[0][p]); free(Grades[0][p]); } return 0; }
修改点说明:
- 用临时缓冲区
buffer先接收输入,再根据实际长度动态分配内存 - 每次
malloc后检查是否成功,避免空指针错误 - 用
strcpy把缓冲区内容复制到分配的内存中 - 最后记得用
free释放内存,防止内存泄漏
额外优化:用结构体存储学生信息(更符合逻辑)
其实年龄、成绩都是数值类型,用字符串存储不太合理,建议用结构体把不同类型的学生信息组织起来,代码更清晰:
#include <stdio.h> // 定义学生结构体,包含所有需要的字段 typedef struct { char firstname[50]; char lastname[50]; int age; int math_grade; int physics_grade; float average; } Student; Student students[1]; // 存储1个学生的信息 int main(void) { printf("Input Firstname \n"); scanf(" %49s", students[0].firstname); printf("Input Lastname \n"); scanf(" %49s", students[0].lastname); printf("Input age "); scanf(" %d", &students[0].age); printf("Input Math Grade \n"); scanf(" %d", &students[0].math_grade); printf("Input Physics Grade \n"); scanf(" %d", &students[0].physics_grade); printf("Input Average Between the two \n"); scanf(" %f", &students[0].average); // 打印学生信息 printf("%s\n", students[0].firstname); printf("%s\n", students[0].lastname); printf("%d\n", students[0].age); printf("%d\n", students[0].math_grade); printf("%d\n", students[0].physics_grade); printf("%.2f\n", students[0].average); return 0; }
这个方案不仅解决了你的乱码问题,还让代码的逻辑更清晰,后续扩展功能(比如存储多个学生)也更方便。
内容的提问来源于stack exchange,提问作者FNS21
相关产品推荐
相关产品推荐

