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; }
异常原因分析
输入缓冲区残留与混合输入冲突
程序同时用getchar()和cin >> input处理输入:cin读取温度数字后,输入缓冲区会残留用户按下的换行符。后续循环中的getchar()会直接读取这个换行符,而非新输入的指令,导致switch无法匹配有效case,触发default分支。变量类型混淆
input被定义为int类型:处理字符指令时存储的是字符ASCII值(比如'i'对应105),但用cin读取温度后存储的是数字实际值(比如输入25就存25)。这会导致input != 'q'的循环判断逻辑失效('q'的ASCII是113,温度数字永远不等于该值)。case分支写法错误
代码中case 'i '、case 't '这类多字符常量不符合C++语法,属于无效分支,无法被正确触发。多余的
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
相关产品推荐
相关产品推荐

