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

求助:使用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类型(避免处理负数时的未定义行为),所以需要做类型转换:

关键代码修改

  1. 教师修改答案部分:
// 替换原putchar调用
answers[question-1] = static_cast<char>(toupper(static_cast<unsigned char>(newAnswer)));
  1. 学生答题部分:
// 替换原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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:48:31