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

C++控制台温控程序输入异常:设置温度后需按回车恢复操作

控制台温控程序输入异常问题解析

问题描述

我是C++新手,正在开发课程用的控制台温控程序,支持以下操作:

  • i - 查看信息
  • t - 设置温度
  • q - 退出
      • 温度加1
      • 温度减1

除t功能外,其他操作均正常。按下t输入温度并确认后,后续任何输入都会触发switch语句的default分支,提示输入错误,直到按下回车后才能再次正常操作。

问题代码

#include <iostream>
#include <string>

using namespace std;

int input;
int temp = 20;
int oldTemp = 20;
string relay = "vypnute";

int main() {
    printf("Regulator teploty Turbo 3000 \nAktualna teplota: %d stupnov celzia, rele je %s. \nStlacte tladiclo 'i' pre informacie: ", temp, relay.c_str());
    while(input != 'q'){
        input = getchar();
        getchar();
        switch(input){
            case 'i': case 'i ':
                if(temp != 20){
                    relay = "zapnute";
                }
                printf("Aktualne je nastavena teplota na %d stupnov celzia, rele je %s. \n", temp, relay.c_str());
                printf(" i Info \n\ t Zadanie teploty od 10 do 35 stupnov \n\ + Zvysenie teploty o 1 stupen \n\ - Znizenie teploty o 1 stupen \n\ q Koniec programu \n");
                break;
            case 't': case 't ':
                printf("Zadajte pozadovanu teplotu: ");
                cin >> input;
                if(input > 35 || input < 10){
                  printf("Zadajte teplotu v rozmedzi od 10 do 35 stupnov. \nStlacte 't' pre zadanie novej teploty. ");
                  break;
                }
                if(input == temp){
                    relay = "vypnute";
                }
                else{
                    relay = "zapnute";
                }
                printf("Teplota bude nastavena z povodnych %d na pozadovanych %d stupnov, rele je %s.",temp, input, relay.c_str());
                temp = input;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            case '+': case '+ ':
                if(temp+1 > 35){
                    printf("Teplota nemoze byt vyssia ako 35 stupnov. ");
                    break;
                }
                relay = "zapnute";
                printf("Teplota bola zvysena z povodnych %d na pozadovanych %d stupnov, rele je %s. ",temp, temp+1, relay.c_str());
                temp++;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            case '-': case '- ':
                if(temp-1 < 10){
                    printf("Teplota nemoze byt mensia ako 10 stupnov. ");
                    break;
                }
                relay = "zapnute";
                printf("Teplota bola znizena z povodnych %d na pozadovanych %d stupnov, rele je %s. ",temp, temp-1, relay.c_str());
                temp--;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            case 'q': case 'q ':
                break;
            default:
                printf("Zly vstup. Stlacte tlacidlo 'i' pre viac informacii. ");
                break;
        }
    }
    if(temp == oldTemp){
        relay = "vypnute";
    }
    else{
        relay = "zapnute";
    }
    printf("Dakujeme za pouzivanie Regulatora Turbo 3000. \nTeplota je po novom nastavena na %d stupnov celzia a rele je %s. ", temp, relay.c_str());
    printf("Stlacte 'enter' pre ukoncenie aplikacie.");
    getchar();
    return 0;
}

异常原因分析

  1. 输入缓冲区残留与混合输入冲突
    程序同时用getchar()和cin >> input处理输入:cin读取温度数字后,输入缓冲区会残留用户按下的换行符。后续循环中的getchar()会直接读取这个换行符,而非新输入的指令,导致switch无法匹配有效case,触发default分支。

  2. 变量类型混淆
    input被定义为int类型:处理字符指令时存储的是字符ASCII值(比如'i'对应105),但用cin读取温度后存储的是数字实际值(比如输入25就存25)。这会导致input != 'q'的循环判断逻辑失效('q'的ASCII是113,温度数字永远不等于该值)。

  3. case分支写法错误
    代码中case 'i '、case 't '这类多字符常量不符合C++语法,属于无效分支,无法被正确触发。

  4. 多余的getchar()调用
    循环开头的第二个getchar()用于吃掉回车,但这种方式脆弱:若用户输入指令后未按回车或输入多字符,都会导致输入处理混乱。

修复方案

1. 分离指令与温度变量

用不同变量存储指令和温度,避免类型混淆:

char cmdInput; // 存储操作指令
int tempInput; // 存储输入的温度
int temp = 20;

2. 清理输入缓冲区

在cin读取温度后,手动清理缓冲区残留的换行符:

case 't':
    printf("Zadajte pozadovanu teplotu: ");
    cin >> tempInput;
    // 清理缓冲区所有字符直到换行
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    // 后续用tempInput处理温度逻辑,不修改cmdInput
    if(tempInput > 35 || tempInput < 10){
        printf("Zadajte teplotu v rozmedzi od 10 do 35 stupnov. \nStlacte 't' pre zadanie novej teploty. ");
        break;
    }
    // ... 温度设置逻辑不变

3. 修正case分支写法

删除带空格的无效case,只保留单字符case:

case 'i':
    // ... 逻辑不变
    break;
case 't':
    // ... 逻辑不变
    break;

4. 优化循环输入逻辑

跳过空白字符,避免多余的getchar():

while(cmdInput != 'q'){
    cmdInput = getchar();
    // 跳过空格、换行等空白字符
    if(isspace(cmdInput)){
        continue;
    }
    switch(cmdInput){
        // ... 各case逻辑
    }
}

完整修复核心代码片段

#include <iostream>
#include <string>
#include <limits> // 用于cin.ignore的numeric_limits

using namespace std;

char cmdInput;
int temp = 20;
int oldTemp = 20;
string relay = "vypnute";

int main() {
    printf("Regulator teploty Turbo 3000 \nAktualna teplota: %d stupnov celzia, rele je %s. \nStlacte tladiclo 'i' pre informacie: ", temp, relay.c_str());
    while(cmdInput != 'q'){
        cmdInput = getchar();
        if(isspace(cmdInput)){
            continue;
        }
        switch(cmdInput){
            case 'i':
                if(temp != 20){
                    relay = "zapnute";
                }
                printf("Aktualne je nastavena teplota na %d stupnov celzia, rele je %s. \n", temp, relay.c_str());
                printf(" i Info \n t Zadanie teploty od 10 do 35 stupnov \n + Zvysenie teploty o 1 stupen \n - Znizenie teploty o 1 stupen \n q Koniec programu \n");
                break;
            case 't':{
                int tempInput;
                printf("Zadajte pozadovanu teplotu: ");
                cin >> tempInput;
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                if(tempInput > 35 || tempInput < 10){
                  printf("Zadajte teplotu v rozmedzi od 10 do 35 stupnov. \nStlacte 't' pre zadanie novej teploty. ");
                  break;
                }
                if(tempInput == temp){
                    relay = "vypnute";
                }
                else{
                    relay = "zapnute";
                }
                printf("Teplota bude nastavena z povodnych %d na pozadovanych %d stupnov, rele je %s.",temp, tempInput, relay.c_str());
                temp = tempInput;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            }
            case '+':
                if(temp+1 > 35){
                    printf("Teplota nemoze byt vyssia ako 35 stupnov. ");
                    break;
                }
                relay = "zapnute";
                printf("Teplota bola zvysena z povodnych %d na pozadovanych %d stupnov, rele je %s. ",temp, temp+1, relay.c_str());
                temp++;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            case '-':
                if(temp-1 < 10){
                    printf("Teplota nemoze byt mensia ako 10 stupnov. ");
                    break;
                }
                relay = "zapnute";
                printf("Teplota bola znizena z povodnych %d na pozadovanych %d stupnov, rele je %s. ",temp, temp-1, relay.c_str());
                temp--;
                printf("\nAk chcete ukoncit regulator, stlacte 'q', inak pokracujte v nastavovani teploty. ");
                break;
            case 'q':
                break;
            default:
                printf("Zly vstup. Stlacte tlacidlo 'i' pre viac informacii. ");
                break;
        }
    }
    if(temp == oldTemp){
        relay = "vypnute";
    }
    else{
        relay = "zapnute";
    }
    printf("Dakujeme za pouzivanie Regulatora Turbo 3000. \nTeplota je po novom nastavena na %d stupnov celzia a rele je %s. ", temp, relay.c_str());
    printf("Stlacte 'enter' pre ukoncenie aplikacie.");
    getchar();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:10:18