C++循环-流错误

C++ Loops - Flow bug?

本文关键字:错误 循环 C++      更新时间:2023-10-16

在我的编程课上,我们的任务是编写一个程序,将单词或短语转换为电话号码,评估每个字符并将其转换为相应的数字。

这是迄今为止的代码:

#include <iostream>
#include <string>
using namespace std;
int main()
{
    char letter;
    int noOfLetters;
    char response;
    cout << "Enter Y/y to convert a telephone number " 
         << "form letters to digits.n"
         << "Enter any other letter to terminate the program: ";
    cin >> response;
    cout << endl;
    while (response == 'Y' || response == 'y')
    {
        cout << "Enter a telephone number using letters: ";
        cin >> letter;
        noOfLetters = 0;
        cout << "The corresponding telephone number is: ";
        while (noOfLetters != 7)
        {
            //cout << "[" << noOfLetters << "]";
            noOfLetters++;
            switch (toupper(letter))
            {
            case 'A':
            case 'B':
            case 'C':
                cout << 2;
                break;
            case 'D':
            case 'E':
            case 'F':
                cout << 3;
                break;
            case 'G':
            case 'H':
            case 'I':
                cout << 4;
                break;
            case 'J':
            case 'K':
            case 'L':
                cout << 5;
                break;
            case 'M':
            case 'N':
            case 'O':
                cout << 6;
                break;
            case 'P':
            case 'Q':
            case 'R':
            case 'S':
                cout << 7;
                break;
            case 'T':
            case 'U':
            case 'V':
                cout << 8;
                break;
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':
                cout << 9;
                break;
            default:
                cout << "[invalid]";
            }
            if (noOfLetters == 3)
            {
                cout << '-';
            }
            else if (noOfLetters > 7)
            {
                cin.ignore();
            }
            cin >> letter;
            //noOfLetters++;
        }
        cout << endl;
        cin.ignore(100, 'n');
        cout << "nTo process another telephone number, enter Y/y n"
             << "Enter any other letter to terminate the program: ";
        cin >> response;
       }
}

只要我打字超过7个字符,一切都很好。问题是,如果我只键入7个字符,它就会把自己搞砸。

假设我键入"honk-honk"(不包括空格,共8个字符)并运行该程序。输出如下:

输入Y/Y将电话号码从字母转换为数字。进来终止程序的任何其他信件:y

使用字母输入电话号码:honk honk对应的电话号码:466-5466

要处理另一个电话号码,请输入Y/Y输入任何其他字母要终止程序:n按任意键继续。

所以,这很好。但是,如果我输入"七十"(正好是7个字符),程序会强制我在继续之前输入另一个字符(不包括空格和换行符),就像这样:

输入Y/Y将电话号码从字母转换为数字。进来终止程序的任何其他信件:y

用字母输入电话号码:70对应的电话号码:738-3689小时

要处理另一个电话号码,请输入Y/Y输入任何其他字母要终止程序:n按任意键继续。

我想修改程序,这样我就可以在程序中输入一个7个字符的短语,并使其正确运行而不会出现任何错误,例如当我输入任何8个字符或更多的字符时。

我已经尽力了,但没有成功。有人能给我一个建议来帮我修复这个bug吗?

您的逻辑流有点混乱。请注意,当noOfLetters为7时,您仍然会在while循环的末尾要求另一个字母。考虑在循环的顶部阅读。如果这更容易,请缓冲循环中的输出。

cout << "Enter a telephone number using letters: " << flush;
// Flush may be necessary if output is line-buffered  ^
noOfLetters = 0;
// This is a buffer where we will be storing the output phone number so that we
// don't have to deal with mixing input with output.
//
// You will need to "#include <sstream>".
stringstream phoneNumber;
// Reading becomes part of the loop condition; if the end of the input is reached,
// we want the loop to terminate.  "cin >> letter" will evaluate to false in
// boolean context if reading failed.
//
// Note that && short-circuits; if the left side is false then the right side is
// not even evaluated.  So when noOfLetters == 7, the loop terminates without
// reading another character.
while (noOfLetters != 7 && cin >> letter) {
    ++noOfLetters;
    // Your switch block goes here. Replace "cout" with "phoneNumber".
    if (noOfLetters == 3) phoneNumber << '-';
}
cout << "The corresponding telephone number is: " << phoneNumber.rdbuf() << endl;

我应用了以下补丁(目的是最小化):

***************
*** 83,91 ****
              {
                  cout << '-';
              }
!             else if (noOfLetters > 7)
              {
!                 cin.ignore();
              }
              cin >> letter;
--- 83,91 ----
              {
                  cout << '-';
              }
!             else if (noOfLetters == 7)
              {
!                 break;
              }
              cin >> letter;

您可能没有意识到输入是缓冲的:直到您按下Enter键,程序才看到任何内容。它挂在循环外的第一个cin >> letter,直到您按下enter。循环中的后续cin >> letter从缓冲区读取,因此缓冲区总是包含一个换行符作为最后一个字符。

然而,读取缓冲区的方式是跳过空白(默认情况下),因此永远看不到换行符。

在循环之后,您有一个cin.ignore(100, 'n');,它忽略所有(剩余的)上行和包括换行符的内容(请注意,此函数并没有跳过空白:100个字符包括空白字符)。因此,最简单的方法就是在处理完7个字符后立即退出循环。

对于原始代码,当您精确键入7个字符时,所有字符都会被读取和处理,此时noOfLetters==7,不大于7。因此,您尝试再读取一个挂起的字符,因为剩余的新行被跳过为空白,并且没有其他内容可读取:您必须键入至少一个非空白字符(待处理),然后按Enter键,才能从cin >> letter;返回。