You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言bool类型do-while循环异常:仅执行两次退出问题排查

问题描述

需要实现一个do-while循环:仅当输入4位数字时终止循环;输入纯字母、5位及以上数字,或混合内容时,循环持续运行并提示错误。当前代码无论输入是否符合条件,仅执行两次就退出,不符合预期。

原代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>


int main(int argc, char* argv[])
{
    ssize_t num;
    char guess[5], *red_alert="Wrong Input\n";
    int numb;
    
    bool is_valid_input=false; // we will start with an assumption that its wrong
    
    do{
        num=read(0, guess, sizeof(guess)); // read in the value from input;
        numb=atoi(guess); // converts our input to a number
        
        if (num == 0){// if num = 0, it means End-Of-File (EOF)
            break;
        }
        if (numb == 0 || numb > 9999){ /* if numb equals 0, then it means only alphabets were entered as  input and if the value of numb is greater 9999, then a 5-digit number was entered as input.
        */
            write(1,red_alert,strlen(red_alert)); /* will send wrong input message to stdout and retain the 
            value assigned to "is_valid_input".
            */
        }
        if (numb>= 1000 && numb <= 9999){// this means that a 4 digit input was entered.
            is_valid_input=true; /*This should be the only reason why the loop should end
            */
        }
    }
    while(is_valid_input == false);
    
    return 0;
}

问题排查

  1. 缺少字符串终止符:read()读取原始字节不会自动添加'\0',atoi()处理无终止符的数组会触发未定义行为,可能得到意外数值,导致错误设置is_valid_input=true,提前退出循环。
  2. 未重置状态标记:is_valid_input仅在初始化时设为false,若某次循环意外将其设为true,后续循环无法重置,直接退出。
  3. 输入缓冲区残留数据:当输入内容超过guess数组长度时,剩余数据会留在缓冲区,下一次read()直接读取残留数据,导致逻辑异常。
  4. 判断逻辑不完整:混合数字和字母的输入(如"123a")会被atoi()转换为123,既不满足错误条件也不满足终止条件,不会输出提示,不符合预期。
  5. 未处理读取错误:read()返回-1表示读取错误,未处理会导致后续逻辑混乱。

正确实现方案

修正后的代码解决了上述问题:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>

#define BUFFER_SIZE 6  // 预留空间存储输入内容+换行符+终止符

int main(int argc, char* argv[])
{
    ssize_t num;
    char guess[BUFFER_SIZE];
    const char* red_alert = "Wrong Input\n";
    
    do{
        bool is_valid_input = false; // 每次循环重置状态
        memset(guess, 0, sizeof(guess)); // 清空缓冲区
        
        // 留1个字节位置存储终止符,避免越界
        num = read(STDIN_FILENO, guess, sizeof(guess) - 1);
        
        // 处理EOF或读取错误
        if (num <= 0){
            break;
        }
        
        // 移除换行符并处理超长输入
        if (guess[num - 1] == '\n'){
            guess[num - 1] = '\0';
        } else {
            // 清空缓冲区剩余数据,避免影响下一次输入
            char c;
            while (read(STDIN_FILENO, &c, 1) > 0 && c != '\n');
            guess[sizeof(guess)-1] = '\0';
        }
        
        // 验证是否为纯数字
        bool is_all_digits = true;
        for (int i = 0; guess[i] != '\0'; i++){
            if (!isdigit(guess[i])){
                is_all_digits = false;
                break;
            }
        }
        
        // 判断是否为4位纯数字
        int numb = atoi(guess);
        if (is_all_digits && numb >= 1000 && numb <= 9999){
            is_valid_input = true;
        } else {
            write(STDOUT_FILENO, red_alert, strlen(red_alert));
        }
        
    } while(!is_valid_input);
    
    return 0;
}

关键修正点

  • 循环内重置is_valid_input,确保每次循环从初始状态开始。
  • read()时预留字节存储终止符,避免atoi()的未定义行为。
  • 处理超长输入,清空缓冲区残留数据,避免干扰后续循环。
  • 新增纯数字验证逻辑,严格判断输入格式,避免混合内容误判。
  • 处理read()返回的EOF和错误情况,增强鲁棒性。

内容的提问来源于stack exchange,提问作者Ajekwe Moses

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:45:38