【问题标题】:I can't figure out why I'm getting this infinite loop我不知道为什么我会得到这个无限循环
【发布时间】:2013-11-19 07:02:01
【问题描述】:

这是我正在编写的一个更大程序的一部分,出于某种原因,它给了我一个无限循环。对于“Roundup”和“what's up”等输入,它的行为与预期一致。这些告诉用户选择的单词应该是正确的长度并且只包含小写字母。然而,像“round-up”和“round up”这样的输入会产生无限重复的消息,告诉用户选择正确长度和格式的单词。有人可以帮我找出问题所在吗?我真的很感激。谢谢!

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <ctime>   
#include <algorithm>
#include <iomanip>
#include <string>

using namespace std;

const int MINWORDLENGTH = 4;
const int MAXWORDLENGTH = 6;
const int NUMWORDS = 9000;


const char WORDFILENAME[] = "C:/Users/Paul/Desktop/words.txt";

int randInt(int lowest, int highest)
{

    if (highest < lowest)
        swap(highest, lowest);
    return lowest + (std::rand() % (highest - lowest + 1));
}

int loadWords(char words[][MAXWORDLENGTH+1], int maxWords)
{
    ifstream wordfile(WORDFILENAME);
    if ( ! wordfile)
    {
        cout << "Cannot open " << WORDFILENAME << endl;
        return -1;
    }
    const int LINELIMIT = 10000;
    char line[LINELIMIT];
    int numWords = 0;
    while (wordfile.getline(line, LINELIMIT))
    {
        if (numWords == maxWords)
        {
            cout << "Using only the first " << numWords
                 << " words from " << WORDFILENAME << endl;
            break;
        }
        int k;
        for (k = 0; islower(line[k]); k++)



        if (line[k] == '\r')
                line[k] = '\0';

        if (line[k] == '\0'  &&  k >= MINWORDLENGTH  &&  k <= MAXWORDLENGTH)
        {
            strcpy(words[numWords], line);
            numWords++;
        }
    }
    return numWords;
}
bool found(char characters[], int length, char target)  //seaches for the target character and returns true if it is found. Otherwise returns false.
{
        for (int i= 0; i<length; i++)
            if (characters[i] == target )
                return true;


    return false;



bool wordFound(const char allWords[][7], char targetWord[], int numWords)  //searches the array of loaded words for the target word. Returns true if it is found, otherwise returns false.
{
for(int j=0; j<numWords; j++)
    if (!strcmp(targetWord,allWords[j]) )
        return true;

return false;
}
bool properFormat(char guess[],int size)  //checks that words are of the proper length and contain only lowercase letters
{
if (( guess[0] == '\0')||strlen(guess) > MAXWORDLENGTH || strlen(guess) < MINWORDLENGTH)
    return false;
for (int i = 0; i < strlen(guess) ; i++)
    if ( !islower(guess[i]) )  //return false if a nonlowercase letter, punctuation or a space is found
        return false;

return true;
}

int manageOneRound(char words[][7],int num, int numwords)
{
    int x=num;
    int y=numwords;

    cout<<"The hidden word is "<<strlen(words[y])<<" letters long"<<endl;
    cerr<<words[y]<<endl;
    int tries =0;
    char guess[7];

    int appearances[MAXWORDLENGTH];
    char characters[MAXWORDLENGTH]="";

    int k=0;
    for ( int j = 0; j < strlen(words[y]); j++)
        if ( !found(characters,strlen(words[y]),words[y][j]) )  //put characters that make up word into an array. Each character appears only once.
        {
            characters[k] = words[y][j];
            k++;
        }

            while ( strcmp(guess,words[y]) )  //while the guessed word is not the correct word
    {

        cout<<"Trial word: ";

        cin.getline(guess, MAXWORDLENGTH+1,'\n');
        if ( !properFormat(guess,strlen(guess)) )   
            cout<<"Your trial word must be a word of "<<MINWORDLENGTH<<" to "<<MAXWORDLENGTH<<" lower case letters"<<endl;
        else if (!wordFound(words,guess,x) && guess[0] != '\0')  //determine if trial word is known
            cout<<"I don't know that word"<<endl;
        else
        {

        int guessAppearances[MAXWORDLENGTH];
        char guessCharacters[MAXWORDLENGTH]="";

        int l=0;
        for ( int j = 0; j < strlen(guess); j++)
        {
            if ( !found(guessCharacters,strlen(guess),guess[j]) ) //Store characters that make up trial word in an array
            {
                guessCharacters[l] = guess[j];
                l++;
            }
        }

        alphabetize(characters,k);
        alphabetize(guessCharacters,l);  //alphabetize the word characters and the guess word characters



        for ( int j = 0; j < k; j++ )
            appearances[j]=countAppearances( words[y], strlen(words[y]), characters[j] );
        for ( int j = 0; j < l; j++ )
            guessAppearances[j]=countAppearances( guess, strlen(guess), guessCharacters[j] );
        //count the number of appearnces of the characters in the word and the guess word.


        int comp[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        int n=0;

    for (int i=0 ;i<k;i++)
        for(int j=0; j<l; j++)
        {
            if (characters[i]==guessCharacters[j] && appearances[i]==guessAppearances[j]) //if the characters match, and the number of its appearances matches, the current position of comp is set to the number of appearances
            {   
                comp[n]=appearances[i];
                n++;
            }
            else if (characters[i]==guessCharacters[j] && appearances[i] > guessAppearances[j])//if the characters match, and the number of appearances of the letter is less than the correct number, the current position of comp is set to the number of its appearances in the guess word.
            {   
                comp[n]=guessAppearances[j];
                n++;
            }
            else if (characters[i]==guessCharacters[j] && appearances[i] < guessAppearances[j])//if the characters match, and the number of appearances of the letter is greater than the correct number, the current position of comp is set to the number of its appearances in the correct word.
            {   
                comp[n]=appearances[i];
                n++;
            }
        }

        int correctSum=0;
        for (int w=0; w <n; w++)  //the number of correct letters is the sum of the elements in comp
            correctSum+= comp[w];
        if (strcmp(guess,words[y]))
            cout<<correctSum<<endl;
        }
        tries++;

}
            return tries;
}
int main()
{
int numRounds;

int max=0;
int min=10000;

cout<<"How many rounds do you want to play? ";
cin>>numRounds;
cin.ignore(10000, '\n');
if (numRounds < 1)
{
    cout<<"The number of rounds must be positive"<<endl;
    return 0;
}
char words[NUMWORDS][MAXWORDLENGTH + 1];

int x = loadWords(words, 10000);

srand(time(0));
int sum = 0;
for (int round=1; round <= numRounds; round++)
{

    cout<<"Round "<<round<<endl;
    int y= randInt(0, x);


    int tries = manageOneRound(words,x,y);


sum+=tries;
    //cerr<<sum<<endl;
cout<<"You got it in "<<tries<<" tries"<<endl;
if (tries < min)
    min = tries;
if (tries > max )
    max = tries;
double average= sum/round;
cout<<"Average: "<<setprecision(2)<<fixed<<average<<setprecision(1)<<fixed<<", minimum: "<<min<<", maximum: "<<max<<endl<<endl;

 }
return 0;
}

【问题讨论】:

  • 如果在调试器中单步执行代码会发生什么?
  • 我看不出这里引用的代码是如何产生重复打印指令的。代码的cout 部分不在任何循环内。您确定您引用了程序的正确部分吗?
  • 请提供完整的代码示例来重现您看到的行为。问题中包含的代码不会编译,也不会导致无限循环。
  • 我已经编辑了代码以包含一个可能相关的循环。但是,当我的输入包含“-”或“”后跟更多字符时,我只会得到一个无限循环。例如,'round-' 会产生一次错误消息,但 'round-up' 或 'round up' 会导致错误无限重复。
  • 但它每次都要求在循环中输入?

标签: c++ loops char infinite-loop cstring


【解决方案1】:

你的代码的问题是你的缓冲区有 MAXWORDLENGTH = 6 +1 = 7 ,所以当你输入四舍五入时,“四舍五入”的长度是 8 所以你的缓冲区的内容会被猜测 = {r, o,u,n,d,u,\0} 并且当输入的长度大于 6 时,这将导致下一个 getline 语句获取未在此缓冲区中获取的 '\n' 并且这会连续执行导致无限而环形。如果输入的长度小于 6,例如“round”,这将正常工作。您正在尝试读取超过其容量的缓冲区,从而导致内存损坏和未定义的行为。

【讨论】:

    猜你喜欢
    • 2020-07-13
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多