我无法弄清楚为什么我会得到这个无限循环

时间:2013-11-19 07:02:01

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

这是我正在编写的一个更大的程序,由于某种原因,它给了我一个无限循环。它的行为与“Roundup”和“What is 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;
}

1 个答案:

答案 0 :(得分:1)

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