虽然循环导致无限循环,但我无法弄清楚为什么

时间:2014-09-13 04:33:02

标签: c++ infinite-loop

我正在使用C ++进行一项任务,旨在向我们传授有关对象和OOP的更多信息。以下是我的代码。它的要点是,用户输入一些输入,程序计算元音或辅音的数量(由用户选择),输入的字符总数以及行尾的总数。

我有三个问题:

  1. 我注释掉的代码部分在离开时会导致无限循环。它会导致countChars函数的输出无限打印,以及输出询问用户是否有我想提出更多意见。
  2. countChars功能无法正确计算EOL。我认为这很可能是因为我对EOL不熟悉。我如何在条件声明中表示?如果我想说,"如果它的值为' 0'"我会说,if (variable == 0)。如果某个东西是EOL,我怎么告诉C ++增加?
  3. countChars输出计数的随机,负值。我注意到值的变化取决于我输入的内容(EOL除外),但我不确定为什么我会得到负值。除了使用unsigned int并初始化值之外,我不确定如何修复它。
  4. 另外,我预见到有人告诉我使用getline函数,但我们有非常具体的使用cin.get的说明(毕竟我们应该学习一些东西)所以请避免使用getline的修补程序。

    标题文件:

    /*
    +----------------------------------------+
    |               CountChars               |
    +----------------------------------------+
    | -countVorC : Integer                   |
    | -countEOL : Integer                    |
    | -totalChars : Integer                  |
    | -vowelCount : Boolean                  |
    +----------------------------------------+
    | <<constructor>>                        |
    |   CountChars()                         |
    | +inputChars() :                        |
    | +vowelCheck(characterToCheck : Boolean)|
    | +setVowelCount(VorC : Character)       |
    | +getCountVorC() : Integer              |
    | +getCountEOL() : Integer               |
    | +getTotalChars() : Integer             |
    | +getVowelCount() : Boolean             |
    +----------------------------------------+
    */
    
    using namespace std;
    
    #ifndef COUNTCHARS_H
    #define COUNTCHARS_H
    
    class CountChars
    {
    private:
        unsigned int countVorC;
        unsigned int countEOL;
        unsigned int totalChars;
        bool vowelCount;
    public:
        CountChars();
        void inputChars();
        bool vowelCheck(char characterToCheck);
        void setVowelCount(char VorC);
        int getCountVorC();
        int getCountEOL();
        int getTotalChars();
        bool getVowelCount();
    };
    
    #endif
    

    实施档案:

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <cctype>
    #include <cstdio>
    #include "CountChars.h"
    
    using namespace std;
    
    CountChars::CountChars()
    {
        unsigned int countVorC = 0;
        unsigned int countEOL = 0;
        unsigned int totalChars = 0;
        bool vowelCount = false;
    }
    
    void CountChars::inputChars()
    {
        int letter;
    
        while ((letter = cin.get()) != EOF && letter != EOF){
            if (vowelCount == true && (vowelCheck(letter) == true)) {
                countVorC++;
            }
            else if (vowelCount == false && (vowelCheck(letter) == false)) {
                countVorC++;
            }
    
            if (isalpha(letter)) {
                totalChars++;
            }
    
            if (letter == '\n') {
                countEOL++;
            }
        }
    }
    
    bool CountChars::vowelCheck(char characterToCheck)
    {
        characterToCheck = toupper(characterToCheck);
    
        if ((isalpha(characterToCheck)) &&
           (characterToCheck == 'A' || characterToCheck == 'E' ||
           characterToCheck == 'I' || characterToCheck == 'O' ||
           characterToCheck == 'U')) {
           return true;
        }
        else {
            return false;
        }
    }
    
    void CountChars::setVowelCount(char VorC)
    {
        VorC = toupper(VorC);
    
        if (VorC == 'V') {
            vowelCount = true;
        }
        else {
            vowelCount = false;
        }
    }
    
    int CountChars::getCountVorC()
    {
        return countVorC;
    }
    
    int CountChars::getCountEOL()
    {
        return countEOL;
    }
    
    int CountChars::getTotalChars()
    {
        return totalChars;
    }
    
    bool CountChars::getVowelCount()
    {
        return vowelCount;
    }
    

    主:

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <cctype>
    #include <cstdio>
    #include "CountChars.h"
    
    using namespace std;
    
    void printCounts(CountChars);
    
    int main()
    {
        char VorC;
        char repeat = 'Y';
        CountChars charCounter;
    
        cout << "Welcome to the Character Counter Program!" << endl;
        cout << "\nWould you want to count vowels or consonants?" << endl;
        cout << "Type 'V' for vowels and 'C' for consonants: ";
        cin >> VorC;
        cout << endl;
    
        while (toupper(VorC) != 'V' && toupper(VorC) != 'C') {
            cout << "\nSorry, that was an invalid choice. Please try again: ";
            cin >> VorC;
            cout << endl;
        }
    
    
        do {
            cout << "You may being typing input below.\n" << endl;
    
            charCounter.setVowelCount(VorC);
            charCounter.inputChars();
            cin.clear();
            printCounts(charCounter);
    
            cout << "\nWould you like to enter new input?" << endl;
            cout << "Type 'Y' for yes or 'N' for no: ";
            cin >> repeat;
            cout << endl;
    
            while (toupper(repeat) != 'Y' && toupper(repeat) != 'N') {
                    cout << "\nSorry, that was an invalid choice. Please try again: ";
                    cin >> repeat;
                    cout << endl;
            }
    
        } while (toupper(repeat) == 'Y');
    
        cout << "\nThank you for using the Character Counter Program!\n" << endl;
    
        system("pause");
        return 0;
    }
    
    void printCounts(CountChars charCounter)
    {
    cout << "\nTotal characters: " << charCounter.getTotalChars() << endl;
    
            if (charCounter.getVowelCount() == true) {
                cout << "Total vowels: " << charCounter.getCountVorC() << endl;
            }
            else {
                cout << "Total consonants: " << charCounter.getCountVorC() << endl;
            }
    
            cout << "Total end-of-lines: " << charCounter.getCountEOL() << endl;
    }
    

1 个答案:

答案 0 :(得分:3)

cin.get()返回int

你有:

char letter;

while ((letter = cin.get()) != EOF)

如果普通char是无符号类型,就像在某些机器上一样,那么这将永远不会评估为true,因为值-1(EOF的正常值)被分配给(无符号)char,它被映射到0xFF,当0xFFint(如EOF(仍为-1)进行比较时,答案是假,所以循环继续。

对此的修复是使用int letter而不是char letter。 (请注意,如果char是带符号的类型,则代码存在不同的问题;然后,代码为0xFF的字符 - 通常是ÿ,y umlaut,U + 00FF,LATIN带有DIAERESIS的小写字母 - 被误解作为EOF。修复是相同的;使用int letter;)。

但是,我怀疑这只是麻烦的一部分。


EOF不是EOL

在同一个功能中,你还有:

    if (letter == EOF) {
        countEOL++;
    }

您知道letter不是EOF(因为循环检查了它)。此外,你想要计算EOL,而不是EOF(每个文件只有一个EOF,但如果你继续尝试超过EOF读取,你将重复返回EOF)。你可能需要:

    if (letter == '\n') {
        countEOL++;
    }

或者您可能想要定义EOL并与之比较:

    const int EOL = '\n';
    if (letter == EOL) {
        countEOL++;
    }

cin将换行符留在输入

在代码中:

cout << "Type 'V' for vowels and 'C' for consonants: ";
cin >> char(VorC);
cout << endl;

while (toupper(VorC) != 'V' && toupper(VorC) != 'C') {
    cout << "\nSorry, that was an invalid choice. Please try again: ";
    cin >> char(VorC);
    cout << endl;
}

第一个cin操作会在输入流中保留换行符。如果使用键入'Y',比如说,那么下一个cin操作(在循环内)将读取换行符,并且因为换行符既不是'V'也不是'C',它会再次抱怨(但是然后等待更多输入。)

添加#include <limits>并使用:

cin.ignore(numeric_limits<streamsize>::max(), '\n');

阅读过去换行。

同样,这不是整个问题。


在EOF

之后无法继续阅读cin

最后一部分,我想......

您注释掉的代码是:

/*do {
    cout << "You may being typing input below.\n" << endl;*/

    charCounter.setVowelCount(VorC);
    charCounter.inputChars();

    /*cout << "Would you like to enter new input?";
    cout << "Type 'Y' for yes or 'N' for no: " << endl;
    cin >> char(repeat);
    cout << endl;
        while (toupper(repeat) != 'Y' && toupper(repeat) != 'N') {
            cout << "\nSorry, that was an invalid choice. Please try again: ";
            cin >> char(repeat);
            cout << endl;
        }
} while (toupper(repeat) == 'Y');*/

请注意,在charCounter.inputChars()到达cin之前,EOF的来电不会停止。此时没有任何输入,因此循环中的cin(被注释掉)将每次都失败,从不生成'Y'。您需要清除cin上的错误,以便输入更多数据,例如“更多输入”问题的答案。

我想知道你是否在阅读代码中混淆了EOL和EOF。也许你打算只读到行的末尾而不是文件的末尾。然后你的循环条件(我先提到的那个)应该是:

int letter;

while ((letter = cin.get()) != EOF && letter != '\n')  // Or EOL if you define EOL as before

你应该随时准备好任何输入操作,以便在你没有真正期望的时候返回EOF,就像这里一样。


乐观主义者!上一部分不是最后一部分。

构造函数不构造

  

但我仍然有打印垃圾的问题。例如,它表示总字符数:-85899345。

我尝试编译你的代码:

$ g++ -O3 -g -std=c++11 -Wall -Wextra -Werror -c CountChars.cpp
CountChars.cpp: In constructor ‘CountChars::CountChars()’:
CountChars.cpp:13:18: error: unused variable ‘countVorC’ [-Werror=unused-variable]
     unsigned int countVorC = 0;
                  ^
CountChars.cpp:14:18: error: unused variable ‘countEOL’ [-Werror=unused-variable]
     unsigned int countEOL = 0;
                  ^
CountChars.cpp:15:18: error: unused variable ‘totalChars’ [-Werror=unused-variable]
     unsigned int totalChars = 0;
                  ^
CountChars.cpp:16:10: error: unused variable ‘vowelCount’ [-Werror=unused-variable]
     bool vowelCount = false;
          ^
cc1plus: all warnings being treated as errors
$

您已在构造函数中声明了隐藏类成员的局部变量,因此构造函数实际上并没有实际构造。垃圾数字是因为你从垃圾开始。

cin >> char(VorC)无法在任何地方编译

同样,当我尝试编译Main.cpp时,我遇到错误:

$ g++ -O3 -g -std=c++11 -Wall -Wextra -Werror -c Main.cpp
Main.cpp: In function ‘int main()’:
Main.cpp:18:9: error: ambiguous overload for ‘operator>>’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘char’)
     cin >> char(VorC);
         ^
Main.cpp:18:9: note: candidates are:
In file included from /usr/gcc/v4.9.1/include/c++/4.9.1/iostream:40:0,
                 from Main.cpp:1:
/usr/gcc/v4.9.1/include/c++/4.9.1/istream:120:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__istream_type& (*)(std::basic_istream<_CharT, _Traits>::__istream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>] <near match>
       operator>>(__istream_type& (*__pf)(__istream_type&))
       ^
/usr/gcc/v4.9.1/include/c++/4.9.1/istream:120:7: note:   no known conversion for argument 1 from ‘char’ to ‘std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&) {aka std::basic_istream<char>& (*)(std::basic_istream<char>&)}’
/usr/gcc/v4.9.1/include/c++/4.9.1/istream:124:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__ios_type& (*)(std::basic_istream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>; std::basic_istream<_CharT, _Traits>::__ios_type = std::basic_ios<char>] <near match>
       operator>>(__ios_type& (*__pf)(__ios_type&))
       ^
…
$

这里的问题是:

cin >> char(VorC);

你真的不想在那里演员:

cin >> VorC;

你可以说应该检查输入是否有效:

if (!(cin >> VorC)) …process EOF or error…

同样的问题当然会影响cin >> char(repeat);

我不知道为什么要为你编译;它不应该这样做。有了这个固定,它有点工作。我遇到了'换行中的换行符',所以inputChars()函数在EOL等之前得到了零个字符。现在由你来处理。