如何修改scanf参数以读取(int float int/int)格式行直至空行?
解决方案
要解决这个问题,我们需要修正scanf的格式串和判断逻辑,同时避免未定义行为,以下是可行的修改方案:
核心问题分析
fflush(stdin)是未定义行为:C标准仅允许对输出流使用fflush,对输入流调用它会导致不可预期的结果,必须移除。- 判断条件错误:原代码仅检查
scanf返回非0,但我们需要确保成功读取4个变量(返回值等于4),否则可能处理部分匹配的无效行。 - 未处理行边界和空行检测:原格式串没有处理行尾的多余字符,也无法准确识别空行。
修改后的代码
listNode *readLine(listNode *prvi){ int min, mesec, dan; float raz; elem tmp; int ret; // 读取目标格式,同时跳过行尾的非换行字符 ret = scanf("%d %f %d/%d%*[^\n]", &min, &raz, &dan, &mesec); if (ret == 4) { // 成功读取完整有效行 tmp.minuti = min; tmp.razdaljina = raz; tmp.dan = dan; tmp.mesec = mesec; enqueue(prvi, tmp); // 吃掉当前行的换行符,避免影响下一次读取 scanf("%*c"); return prvi; } else if (ret == 0) { // 未匹配任何变量,检查是否是空行 char c; // 跳过行首空白,尝试读取换行符 if (scanf("%*[ \t]%c", &c) == 1 && c == '\n') { // 检测到空行,返回NULL终止读取 return NULL; } else { // 无效行,跳过剩余内容后继续读取下一行 scanf("%*[^\n]%*c"); return readLine(prvi); } } else { // 部分匹配或EOF,跳过当前行剩余内容 scanf("%*[^\n]%*c"); // 若到达输入末尾,返回NULL;否则继续读取 return feof(stdin) ? NULL : readLine(prvi); } }
格式串说明
"%d %f %d/%d":精准匹配你需要的(int float int/int)格式。%*[^\n]:跳过当前行中剩余的所有非换行字符(处理行尾可能存在的多余输入),*表示不存储这些字符。%*c:单独调用吃掉换行符,确保下一次scanf从新的一行开始。%*[ \t]:跳过空行中的前导空格或制表符,确保准确识别仅含空白的空行。
关键逻辑
- 仅当
scanf返回4时,才处理有效行,保证所有变量都被正确读取。 - 当
scanf返回0时,进一步检查是否是空行:若读取到换行符则终止,否则跳过无效行继续读取。 - 处理部分匹配或EOF的情况,避免残留输入影响后续读取。
内容的提问来源于stack exchange,提问作者Aleksa Racic
相关产品推荐
相关产品推荐

