求助:使用putchar(toupper())时出现意外输出大写字符的问题
问题描述
我正在编写一个考试答题程序,要求用户输入字符作为答案。为便于将用户答案与标准答案比对,我使用putchar(toupper(questionAnswer))将用户输入转为大写,但发现每次调用putchar()时,即使没有cout语句,转换后的大写字符也会被输出。程序代码如下:
#include <iostream> #include <ctype.h> using namespace std; int main() { const string CLEAR = "\033[2J\033[1;1H"; string testAnswers; int status, newKey; char newAnswer, choice, keyChoice, endProgram, questionAnswer, answers[20] = {'B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C', 'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A'}; do{ //starting prompt cout << CLEAR; cout << "Teacher or Student:\n1.Teacher\n2.Student\n"; cin >> status; while(status > 2 || status < 1){ cout << "Enter valid input\n"; cin >> status; } //teacher section if(status == 1){ cout << "Do you want to change the test key? Y/N\n"; cin >> keyChoice; if(keyChoice == 'Y' || keyChoice == 'y'){ //loops through all questions so the user can input new answers for(int question = 1; question <= 20; question++){ cout << "What is the new answer to question " << question << ":\t"; cin >> newAnswer; while(newAnswer != 'a' && newAnswer != 'A' && newAnswer != 'b' && newAnswer != 'B' && newAnswer != 'c' && newAnswer != 'C' && newAnswer != 'd' && newAnswer != 'D'){ cout << "Input valid answer\n"; cin >> newAnswer; } answers[question-1] = putchar(toupper(newAnswer)); cout << endl; } //output new key cout << "The new key is:\n"; for(int i = 0; i < 20; i++){ cout << "Question " << i << ": " << answers[i+1] << endl; } } //student section }else{ do{ cout << CLEAR; //start test for(int question = 1; question <= 20; question++){ cout << "What is the answer to question " << question << ":\t"; cin >> questionAnswer; while(questionAnswer != 'a' && questionAnswer != 'A' && questionAnswer != 'b' && questionAnswer != 'B' && questionAnswer != 'c' && questionAnswer != 'C' && questionAnswer != 'd' && questionAnswer!= 'D'){ cout << "Input valid answer to question " << question << endl; cin >> questionAnswer; } testAnswers += putchar(toupper(questionAnswer)); cout << endl; } //grades test int rightAnswers = 0; for(int i = 0; i < 20; i++){ if(testAnswers[i] == answers[i]){ rightAnswers += 1; }else{ cout << "You got question " << i + 1 << " wrong\n"; } } //output the users score and if they passed or not cout << "You got " << rightAnswers << " questions right and " << (rightAnswers - 20) * -1 << " questions wrong\n"; if(rightAnswers >= 15){ cout << "You have passed the exam\n"; }else{ cout << "You have failed the exam\n"; } cout << "Would you like to take the exam again? Y/N\n"; cin >> choice; }while(choice == 'y' || choice == 'Y'); } cout << "Are you done with the driver exam? Y/N\n"; cin >> endProgram; }while(endProgram == 'n' || endProgram == 'N'); cout << CLEAR; cout << "Goodbye"; }
问题原因
putchar()的核心功能就是将字符输出到标准输出流(stdout),它的返回值是成功输出的字符(失败则返回EOF)。你用它转换大写并赋值时,会先执行输出操作,再把返回的字符存入变量,这就是自动输出大写字符的根本原因。
解决方案
直接使用toupper()转换字符即可,无需借助putchar()。注意toupper()要求传入unsigned char类型(避免处理负数时的未定义行为),所以需要做类型转换:
关键代码修改
- 教师修改答案部分:
// 替换原putchar调用 answers[question-1] = static_cast<char>(toupper(static_cast<unsigned char>(newAnswer)));
- 学生答题部分:
// 替换原putchar调用 testAnswers += static_cast<char>(toupper(static_cast<unsigned char>(questionAnswer)));
额外代码修正
程序还有两处小问题需要修复:
- 输出新答案时存在数组越界:
answers[i+1]会访问到数组外的内存,应改为answers[i],同时问题编号要加1:
cout << "Question " << i+1 << ": " << answers[i] << endl;
- 学生重新考试时,需要清空
testAnswers,否则多次考试的答案会累加:
do{ cout << CLEAR; testAnswers.clear(); // 新增:清空之前的答案记录 //start test for(int question = 1; question <= 20; question++){ // ... 原有代码 } // ... 原有代码 }while(choice == 'y' || choice == 'Y');
完整修正后的代码
#include <iostream> #include <ctype.h> #include <string> using namespace std; int main() { const string CLEAR = "\033[2J\033[1;1H"; string testAnswers; int status; char newAnswer, choice, keyChoice, endProgram, questionAnswer, answers[20] = {'B', 'D', 'A', 'A', 'C', 'A', 'B', 'A', 'C', 'D', 'B', 'C', 'D', 'A', 'D', 'C', 'C', 'B', 'D', 'A'}; do{ //starting prompt cout << CLEAR; cout << "Teacher or Student:\n1.Teacher\n2.Student\n"; cin >> status; while(status > 2 || status < 1){ cout << "Enter valid input\n"; cin >> status; } //teacher section if(status == 1){ cout << "Do you want to change the test key? Y/N\n"; cin >> keyChoice; if(keyChoice == 'Y' || keyChoice == 'y'){ //loops through all questions so the user can input new answers for(int question = 1; question <= 20; question++){ cout << "What is the new answer to question " << question << ":\t"; cin >> newAnswer; while(newAnswer != 'a' && newAnswer != 'A' && newAnswer != 'b' && newAnswer != 'B' && newAnswer != 'c' && newAnswer != 'C' && newAnswer != 'd' && newAnswer != 'D'){ cout << "Input valid answer\n"; cin >> newAnswer; } answers[question-1] = static_cast<char>(toupper(static_cast<unsigned char>(newAnswer))); cout << endl; } //output new key cout << "The new key is:\n"; for(int i = 0; i < 20; i++){ cout << "Question " << i+1 << ": " << answers[i] << endl; } } //student section }else{ do{ cout << CLEAR; testAnswers.clear(); //start test for(int question = 1; question <= 20; question++){ cout << "What is the answer to question " << question << ":\t"; cin >> questionAnswer; while(questionAnswer != 'a' && questionAnswer != 'A' && questionAnswer != 'b' && questionAnswer != 'B' && questionAnswer != 'c' && questionAnswer != 'C' && questionAnswer != 'd' && questionAnswer!= 'D'){ cout << "Input valid answer to question " << question << endl; cin >> questionAnswer; } testAnswers += static_cast<char>(toupper(static_cast<unsigned char>(questionAnswer))); cout << endl; } //grades test int rightAnswers = 0; for(int i = 0; i < 20; i++){ if(testAnswers[i] == answers[i]){ rightAnswers += 1; }else{ cout << "You got question " << i + 1 << " wrong\n"; } } //output the users score and if they passed or not cout << "You got " << rightAnswers << " questions right and " << 20 - rightAnswers << " questions wrong\n"; if(rightAnswers >= 15){ cout << "You have passed the exam\n"; }else{ cout << "You have failed the exam\n"; } cout << "Would you like to take the exam again? Y/N\n"; cin >> choice; }while(choice == 'y' || choice == 'Y'); } cout << "Are you done with the driver exam? Y/N\n"; cin >> endProgram; }while(endProgram == 'n' || endProgram == 'N'); cout << CLEAR; cout << "Goodbye"; return 0; }
内容的提问来源于stack exchange,提问作者Lucas Sintim
相关产品推荐
相关产品推荐

