C语言特定格式输入问题排查及代码优化咨询
C语言读取{1,2,3}格式输入的问题与优化建议
问题描述
需要实现读取{1,2,3,4}格式的输入(数字被花括号包裹、逗号分隔),编写的代码在格式正确时运行正常,但输入{2并回车后,程序误判为遇到}而退出循环,代码如下:
znamky = (int*) malloc (n * sizeof(int)); // I allocate memory here if (znamky == NULL) return EXIT_FAILURE; printf("Pocty bodu:\n"); scanf("%c",&overeni[0]); // here I check if the first character is {; if not I exit program if (overeni[0]!=zavorka[0]) { printf("Nespravny vstup.\n"); return EXIT_FAILURE; } while (scanf("%d",&znamky[count])!=EOF) //here I continue loading numbers, and char fight { //if the character after number is "," i load another if (scanf("%c",&znaminko[0])==1) //number, if it is "}"I exit the while cycle { // else I exit the program if (znaminko[0]==carka[0]) // if equals "," { printf("sdf\n"); count++; if (count==n) // if I run out of memory I allocate more { n = n*2; znamky = (int*) realloc (znamky, n * sizeof(int) + 4); } continue; } if (znaminko[0]==zavorka2[0]) // if equals "}" count++; printf("utikam\n"); break; } else { printf("Nespravny vstup\n"); return EXIT_FAILURE; } } printf("%d ",count); //here I just print length of my array printArray(znamky,count); free(znamky); return 0;
问题原因
- 语法错误导致无条件退出:判断右花括号的
if语句没有用{}包裹多语句,只有count++;属于if块,后面的printf("utikam\n"); break;是无条件执行的——不管读取到的字符是不是},都会直接break退出循环。 - 未处理空白字符:输入
{2并回车后,scanf("%d", ...)读取完数字2,后续的scanf("%c", ...)会读取到换行符(\n),而代码没有处理这种空白字符,导致进入后续逻辑后触发了无条件break。
优化建议
- 修复语法错误:所有包含多语句的
if必须用{}包裹,比如判断右花括号的部分要修改为:if (znaminko[0]==zavorka2[0]) { count++; printf("utikam\n"); break; } - 跳过空白字符:
scanf读取%c时不会自动跳过空白(空格、换行、制表符),要在%c前加空格,让它自动跳过空白,避免读取到干扰字符:scanf(" %c",&znaminko[0]) - 安全处理内存分配:
realloc的内存计算不需要额外加4,直接用n * sizeof(int)即可,避免内存计算错误;realloc可能失败,要先保存原指针,防止内存泄漏:int *temp = realloc(znamky, n * sizeof(int)); if (temp == NULL) { free(znamky); printf("Chyba alokace pameti\n"); return EXIT_FAILURE; } znamky = temp;
- 变量简化与初始化:
- 单个字符变量不需要用数组,比如
overeni[0]、znaminko[0]可以换成单个char变量,代码更简洁; - 确保
count初始化为0,zavorka、carka、zavorka2正确赋值(比如char zavorka = '{'),避免未定义行为。
- 单个字符变量不需要用数组,比如
- 严格输入校验:
- 读取整数时,判断
scanf的返回值是否为1(成功读取一个整数),而不是判断是否不等于EOF——如果输入格式错误(比如字母),scanf会返回0,此时要触发错误处理; - 读取完右花括号后,检查是否还有多余输入,避免格式错误被忽略。
- 读取整数时,判断
- 简化逻辑结构:可以用更清晰的循环逻辑,先读取
{,然后循环读取「数字+逗号」,最后读取},示例:// 读取开头的{,跳过可能的空白 char start; scanf(" %c", &start); if (start != '{') { printf("Nespravny vstup.\n"); return EXIT_FAILURE; } int count = 0; int n = 4; // 初始容量 int *znamky = malloc(n * sizeof(int)); if (!znamky) { /* 内存错误处理 */ } // 读取第一个数字 if (scanf(" %d", &znamky[count]) != 1) { printf("Nespravny vstup.\n"); free(znamky); return EXIT_FAILURE; } count++; while (1) { char sep; scanf(" %c", &sep); if (sep == '}') break; if (sep != ',') { printf("Nespravny vstup.\n"); free(znamky); return EXIT_FAILURE; } // 扩容检查 if (count >= n) { n *= 2; int *temp = realloc(znamky, n * sizeof(int)); if (!temp) { /* 错误处理 */ } znamky = temp; } // 读取下一个数字 if (scanf(" %d", &znamky[count]) != 1) { printf("Nespravny vstup.\n"); free(znamky); return EXIT_FAILURE; } count++; }
内容的提问来源于stack exchange,提问作者Matouš Kovář
相关产品推荐
相关产品推荐

