views:

411

answers:

3

I get an infinite loop when I use the following code in C++ and I don't understand why. I suspect the problem is within the input_words() function. Here is the code:

#include<iostream>
using namespace std;

string input_words(int maxWords) {
    int nWord = 0;
    string words[maxWords];
    string aWord = "";
    while (aWord != "Quit" && nWord < maxWords) {
        cout << "Enter a number ('Quit' to stop): ";
        getline (cin, aWord);
        words[nWord] = aWord;
        nWord++;
    }
    return *words;
}

int num_words (string words[], int maxWords) {
    int numWords = 0;
    for (int i=0; i<maxWords; i++) {
        if (words[i] == "Quit") {
            break;
        }
        numWords++;
    }
    return numWords;
}

int main() {

    const int MAX_WORDS = 100;
    string words[MAX_WORDS] = input_words(MAX_WORDS);

    int lenWords = num_words(words, MAX_WORDS);
    cout << "\nThere are " << lenWords << " words:\n";

    for (int i=0; i<MAX_WORDS; i++) {
        if (words[i] == "Quit") {
            break;
        }
        cout << words[i] << "\n";
    }
    return 0;
}

More specifically, I can't exit even when I type 'Quit' when prompted for a word. How could I solve this? I know this is noob code :) I'm just starting on C++

A: 

I tried the following test program, it works:

{0,506}$> cat testcin.cpp && make testcin && ./testcin.exe
#include <iostream>
using namespace std;

int main()
{
    const int maxWords = 5;
    int nWord = 0;
    string words[maxWords];
    string aWord = "";
    while (aWord != "Quit" && nWord < maxWords) {
        cout << "Enter a number ('Quit' to stop): ";
        getline (cin, aWord);
        words[nWord] = aWord;
        nWord++;
    }    
}

make: `testcin' is up to date.
Enter a number ('Quit' to stop): test
Enter a number ('Quit' to stop): Quit

[Vlad@rabbit] [20:53:53] [~/c++]
{0,507}$> 
Vlad
A: 

The problem, I think is in your main where you return the result of input_words() which is a string to initialize words in main() which is of type string[]. It's definitely this problem.

Rewritten to use vector:

#include<iostream>
#include<vector>
#include<string>
using namespace std;

vector<string> input_words(int maxWords) {
    int nWord = 0;
    vector<string> words;
    string aWord = "";
    while (aWord != "Quit" && nWord < maxWords) {
        cout << "Enter a number ('Quit' to stop): ";
        getline (cin, aWord);
        words.push_back(aWord);
        nWord++;
    }
    return words;
}

int num_words (vector<string> words) {
    // return words.size();

    int numWords = 0;
    vector<string>::iterator it = words.begin();
    for (; it != words.end(); it++) {
        if (*it == "Quit") {
            break;
        }
        numWords++;
    }
    return numWords;
}

int main() {

    const int MAX_WORDS = 100;
    vector<string> words = input_words(MAX_WORDS);

    int lenWords = num_words(words);
    cout << "\nThere are " << lenWords << " words:\n";

    vector<string>::iterator it = words.begin();
    for (; it != words.end(); it++) {
        if (*it == "Quit") {
            break;
        }
        cout << *it << endl;
    }
    return 0;
}

Forget the following, the C++ getline() strips the '\n' automatically.

Have you checked to see if your getline() words have newlines at the end of them? That is, "Quit" != "Quit\n".

Harvey
I had a working implementation of this in a while loop which worked perfectly (a bit like Vlad's answer). I then tried to make a function out of it and got stuck in the infinite loop. I'm editing the question to add the full code, not just the function.
Morlock
[Documentation](http://www.cplusplus.com/reference/string/getline/) says: If the delimiter is found, it is extracted and discarded, i.e. it is not stored and the next input operation will begin after it.
Vlad
@Vlad: yeah I was looking at the C getline by mistake.
Harvey
+2  A: 

I modified the function in such a way:

string input_words(int maxWords) {
    cout << "started" << endl;
    int nWord = 0;
    string words[maxWords];
    string aWord = "";
    while (aWord != "Quit" && nWord < maxWords) {
        cout << "Enter a number ('Quit' to stop): ";
        getline (cin, aWord);
        words[nWord] = aWord;
        nWord++;
    }
    cout << "finished" << endl;
    return *words;
}

After inputting Quit, it prints "finished", and then "started" again. Your code is calling the function several times.

The problem is that the function returns only one string. so the line

string words[MAX_WORDS] = input_words(MAX_WORDS);

seems to call the function input_words MAX_WORDS times.

A good way would be to switch to vector<string>:

vector<string> input_words(int maxWords) {
    vector<string> words;
    string aWord;
    while (aWord != "Quit" && nWord < maxWords) {
        cout << "Enter a number ('Quit' to stop): ";
        getline (cin, aWord);
        words.push_back(aWord);
    }
    return words;
}

...
vector<string> words = input_words(MAX_WORDS);
Vlad
Good catch that it calls input_words() MAX_WORDS times.
Harvey
@Vlad Indeed, and you suggested it even BEFORE I put the entire code, including the words[MAX_WORDS] bit :) Thanks a lot for the vector implementation, this is exactly where I was headed to, but I find it difficult for a beginner to get information about what C++ methods exits. (I'm coming from Python, where the help() is always ready to be used). Any suggestion of a favorite site where to find this kind of stuff? I just came across http://www.cppreference.com/wiki/ but if there are better or alternative ones, I'm all open!
Morlock
@Morlock: for a quick start, I used http://www.icce.rug.nl/documents/cplusplus/ several years ago. http://stackoverflow.com is actually very good, too! :-)
Vlad
@Vlad: I DO believe stackoverflow.com to be great. Up to now, without it, I wouldn't be able to learn C++ ! Thanks for your link, I'll use it. Any other source you use for day to day help?
Morlock
@Morlock: I use http://www.sgi.com/tech/stl/table_of_contents.html quite often; however it's more a reference than a tutorial.
Vlad
Boost libraries (http://www.boost.org/) must be of good use, too. However, for the most of my tasks the more simple STL is enough.
Vlad
@Harvey: thanks!
Vlad
@Vlad: I was looking for a reference, I already went through a 150 pages tutorial and I am now going through Stourstrup's 1000-page book. Last year, I learned Python, now this is my C++ year :)
Morlock
@Morlock: Good luck with C++! Python is an interesting, elegant and powerful language, too, you are certainly going to miss some of its features (in particular, built-in regexp support).
Vlad
Again, neither the attempt to create a "variable size array" as `words[maxWords]` nor the attmpt to initialize the array with a single value as in `words[maxWords] = input_words(MAX_WORDS)` is C++. You must be using some rather "creative" compiler.
AndreyT
@AndreyT: creating an array of fixed size which is unknown at the compilation time is a well-known extension supported by e.g. gcc. (It makes a kind of `alloca` inside.)
Vlad
@AndreyT: and yes, my example above worked on gcc, so the multiple calls for the initialization seem to be a gcc extension, too
Vlad