C语言银行客户结构体程序printf打印表格仅最后姓名输出异常问题
问题原因
- 结构体柔性数组使用错误:C 语言中不指定长度的末尾数组成员(柔性数组)不占用结构体本身的内存空间,无法直接用于声明结构体数组。原代码中
struct CustomerData n[2]的每个元素的name字段都没有分配合法的内存空间,输入姓名时会发生越界写操作,前面客户的姓名数据会被后续输入覆盖,因此只有最后一名客户的姓名数据保留正常。 - 输出逻辑错误:
puts()函数的作用是直接输出字符串并自动换行,返回值为int类型(输出成功返回非负整数,失败返回EOF)。原代码将puts(n[i].name)的返回值作为printf("%c")的参数输出,本质是把整数转成字符打印,完全不符合打印姓名的逻辑,是输出乱码的直接原因。 - 额外的未定义/不安全用法:
fflush(stdin)是C标准未定义的行为,不同编译器实现逻辑不一致,无法可靠清空输入缓冲区;gets()函数已被C标准废弃,没有边界检查,极易触发缓冲区溢出漏洞。
修复方案
- 修改结构体定义,给姓名字段指定固定长度(例如设置为50个字符足够存储普通姓名),替换柔性数组用法。
- 调整输出逻辑,使用
printf("%s")直接输出姓名字符串,不要混用puts和printf的参数。 - 替换不安全的输入处理逻辑:用
scanf(" %[^\n]")(前面加空格吃掉之前遗留的换行符)替代fflush(stdin)+gets()的组合,避免未定义行为。 - 可以将结构体数组的长度定义为宏,方便后续修改为题目要求的200个客户上限。
修复后完整代码
#include <stdio.h> // 定义客户上限和姓名最大长度 #define MAX_CUSTOMER 200 #define NAME_MAX_LEN 50 struct CustomerData { int acNum; float balance; char name[NAME_MAX_LEN + 1]; // 多留1位存字符串结束符'\0' } n[MAX_CUSTOMER]; int main() { int test_cnt = 2; // 测试2个客户,可改为MAX_CUSTOMER适配业务需求 for(int i = 0; i < test_cnt; i++) { printf("give Ac. no. of %d customer\n", i+1); scanf("%d", &n[i].acNum); printf("balance of customer %d\n", i+1); scanf("%f", &n[i].balance); printf("Name of customer %d\n", i+1); // 格式符前加空格吃掉之前输入留在缓冲区的换行符 scanf(" %[^\n]", n[i].name); } // 左对齐输出,表格更规整 printf("%-10s %-10s %s\n", "Name", "Acc. no", "Balance"); for(int i = 0; i < test_cnt; i++) { printf("%-10s %-10d %.2f\n", n[i].name, n[i].acNum, n[i].balance); } return 0; }
内容的提问来源于stack exchange,提问作者Sahil Dadhwal
相关产品推荐
相关产品推荐

