So I have a couple of problems with this assignment and I need a bit of help. The first is Went ever I input the name of a college or university that I know is on the list, it causes an infinite loop and repeats the menu forever. This will only happen if I type the name of a college or university(I could type giberrish and it wouldn't cause an infinite loop to occur). The last problem is how do I stop the program from displaying the two statements such as the "This institution is/isn't the list. I only want the program to display one of these statements whenever the user inputs the name of a college/university; not the whole entire list.

Note1: I need to mention that this menu has to have a vector of strings and array read from a file an into seperate functions.
Note2: If you're wondering why there are empty if/else statements, it's because I'm trying to fix this problem before I advance.
Note3: I've posted 2 txt files for you look to at.

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

void collegesUniversities()
{
    ifstream campuses;
    campuses.open("colleges.txt");

    vector<string> schoolVector;
    string schools;

    cout << "\nEnter the name of your college/university. ";
    cin >> schools;

    if(!campuses)
        cerr << "Error opening file. ";
    else
    {
      while(getline(campuses,schools, '\n'))
       {
         schoolVector.push_back(schools);
       }
    }

    for(size_t i=0; i < schoolVector.size(); i++)
          {
            cout << schoolVector.at(i) << '\n';

           if(schools != schoolVector[i])
             cout << "\nThis institution is on the list. ";
           else
             cout << "\nThis institution isn't on the list. ";
          }

    campuses.close();
}

int main()
{
    int choice;

 cout << "Welcome to my college and university search program.\n";
 cout << "\nPress any button to continue.\n ";
                          system("pause>nul");

  do
{
 cout << "\nPress 1 to enter possible colleges and universities.";
 cout << "\nPress 2 to find out how many colleges and universities";
 cout << " appear in your state.\n";
 cout << "Press 3 to find the total amount of colleges and";
 cout << " universities in our list. ";
 cout << "\nPress 4 to quit. ";
 cin >> choice;

  if(choice == 1)
   {
       collegesUniversities();
   }

   else if(choice == 2)
    {

    }

   else if(choice == 3)
    {

    }

   else if(choice == 4)
   {
      cout << "\nThank you for using my program. ";
      cout << "Have a great day.\n ";
   }

   else
       {
         cerr << "\nError, Invalid input. ";
         cout << "Only integers from 1 through 4 are allowed.\n";
       }
}
  while(choice != 4);
}

Recommended Answers

All 11 Replies

It's almost certainly because you are using a mixture of cin >> and std::getline to get input from the user.

You might want to consider changing line 17 to use getline because cin >> will only take everything up to the first newline or whitespace character. So if the user enters a multiple word college name; because of the spaces, only the first word will be written to the variable. The rest of the characters (and the newline) will remain in the input stream and will end up being consumed by a subsequent call to cin or getline.

Also, in your main menu; after you prompt the user to enter their preferred option and get the value via cin, you might want to consider using cin.ignore afterwards with some appropriate parameters to allow it to disregard any remaining characters/newlines in the buffer.

To discard extraneous characters from the input buffer after a call to cin, many people tend to use things like: cin.ignore(std::numeric_limits<int>::max(), '\n');

Personally, I side-step this issue in my command-line programs by getting all user input as a string via std::getline. Then I parse and validate the user input before converting it to the required type and range-checking it... Might seem a bit overkill and a PITA, but that's just me. All user input should be considered guilty until proven innocent, heh heh!

WRT your program displaying all colleges in the list, try setting up a boolean sentinel flag/variable just before your for loop at line 31 and initialise it to false.
e.g. bool found = false;
Then iterate through the vector of colleges. If any of them match the user-entered string, set the sentinel flag to true and break out of the loop.
After the for loop, check the state of the sentinel and output an appropriate message. If the flag is true, the user entered college is in the list. If it is still false, then it is not... Simple!

thanks for the reply, I'll get right on it.

edit1- This may seem like a stupid question but in regards to using cin.ignore, how would I know how many characters I need to skip so I don't overskip per say. I'm also having a bit difficulty understanding your terminology(Parse?) and I assume you validate the user's input with a loop or maybe cin.clear().

edit2-Also does cin.ignore go after the user input their choice(cin choice) or after the user enters their school of choice(cin schools)?

For the bool aspect of this program, could I extract the for loop and put it into a separate function called bool DoesStringEqualVector to check whether the user's input matches the vector?

So I've place getline(cin, schools) on line 18 and that has definately stopped the infinite loop. Which means problem 1 has been eliminated. Now on to problem 2.

You should be using a different string to read from the file. You are overwriting schools with what is in the file. This:

while(getline(campuses,schools, '\n'))
{
    schoolVector.push_back(schools);
}

Should be

string temp;
while(getline(campuses,temp, '\n'))
{
    schoolVector.push_back(temp);
}

As far as problem 2 goes what you need to do is create a bool variable and set it to false. Then as you are going through the vector if you find the school then you should set the variable to true. After the loop then check the variable and print accordingly.

commented: Nice spot, I missed that! +9

I'm almost there guys. I only have one problem and you'll probably think that it's a simple fix. After careful consideration this what I got.

void collegesUniversities()
{
    ifstream campuses;
    campuses.open("colleges.txt");

    vector<string> schoolVector;
    string schools;
    string temp;
    bool match = false;

    cout << "\nEnter the name of your college/university. ";
    cin >> schools;
    getline(cin, schools);

    if(!campuses)
        cerr << "Error opening file. ";
    else
    {
      while(getline(campuses,temp, '\n'))
       {
         schoolVector.push_back(temp);
       }
    }

    for(size_t i=0; i < schoolVector.size(); i++)
          {
            cout << schoolVector.at(i) << '\n';

           if(temp == schoolVector[i])
             {
               match = true;
               cout << "\n" << temp << " is on the list.\n ";
             }
           else if(match)
             cout << "\nThis institution isn't on the list.\n ";
          }

    campuses.close();
}

The problem with this is that It only says Zion Bible College is on the list(which is it on the list) even If I type Yuba College(which is also on the list). Nathan, I had to put string temp where it's at because the statement temp== schoolvector[i] was not working. why? because it's not within the scope. So, any other considerations?

Change line 29 if(temp == schoolVector[i]) to if(schools == schoolVector[i]) since schools is what you ask the user for. temp is just what was last read from the file.

Ok, I did that but now it doesn't say that the school the user inputs is on the list. It just prints out every school on the list(which is what I want it to do) and at the bottom, it should say that this school is on the list but it doesn't; it's just blank. Last time it was always saying that Zion Bible college was on the list. I'm assuming it's because since this school is the list and it's the last school the program reads, it will always print it out. This is what I think is the problem. Maybe we have to change the for loop?

edit1- I'm also checking to see if the statement "this institution isn't on the list" works and it doesn't. I'm inputting random gibberish and it just comes out blank. So I guess need to fix that too great!

This is how I have it.

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

void collegesUniversities()
{
    ifstream campuses;
    campuses.open("colleges.txt");

    vector<string> schoolVector;
    string schools;
    bool match = false;

    cout << "\nEnter the name of your college/university. ";
    cin >> schools;
    getline(cin, schools);

    if(!campuses)
        cerr << "Error opening file. ";
    else
    {
      string temp;
      while(getline(campuses,temp, '\n'))
       {
         schoolVector.push_back(temp);
       }
    }

    for(size_t i=0; i < schoolVector.size(); i++)
          {
            cout << schoolVector.at(i) << '\n';

           if(schools == schoolVector[i])
             {
               match = true;
               cout << "\n" << schools << " is on the list.\n ";
             }
           else if(match)
             cout << "\nThis institution isn't on the list.\n ";
          }

    campuses.close();
}

int main()
{
    int choice;

 cout << "Welcome to my college and university search program.\n";
 cout << "\nPress any button to continue.\n ";
                          system("pause>nul");

  do
{
 cout << "\nPress 1 to enter possible colleges and universities.";
 cout << "\nPress 2 to find out how many colleges and universities";
 cout << " appear in your state.\n";
 cout << "Press 3 to find the total amount of colleges and";
 cout << " universities in our list. ";
 cout << "\nPress 4 to quit. ";
 cin >> choice;

  if(choice == 1)
   {
       collegesUniversities();
   }

   else if(choice == 2)
    {

    }

   else if(choice == 3)
    {

    }

   else if(choice == 4)
   {
      cout << "\nThank you for using my program. ";
      cout << "Have a great day.\n ";
   }

   else
       {
         cerr << "\nError, Invalid input. ";
         cout << "Only integers from 1 through 4 are allowed.\n";
       }
}
  while(choice != 4);
}

Here is your corrected code. I commented what I changed.

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

void collegesUniversities()
{
    ifstream campuses;
    campuses.open("colleges.txt");

    vector<string> schoolVector;
    string schools;
    bool match = false;

    cout << "\nEnter the name of your college/university. ";
    // cin >> schools; <- dont use this since you are using getline
    getline(cin, schools);

    if (!campuses)
        cerr << "Error opening file. ";
    else
    {
        string temp;
        while (getline(campuses, temp, '\n'))
        {
            schoolVector.push_back(temp);
        }
    }

    for (size_t i = 0; i < schoolVector.size(); i++)
    {
        cout << schoolVector.at(i) << '\n';

        if (schoolVector[i] == schools)
            match = true;
    }

    // moved this outside the loop so it prints at the end of the list
    if (match)
        cout << "\n" << schools << " is on the list.\n ";
    else 
        cout << "\n" << schools << " isn't on the list.\n ";
    campuses.close();
}

int main()
{
    int choice;

    cout << "Welcome to my college and university search program.\n";
    cout << "\nPress any button to continue.\n ";
    system("pause>nul");

    do
    {
        cout << "\nPress 1 to enter possible colleges and universities.";
        cout << "\nPress 2 to find out how many colleges and universities";
        cout << " appear in your state.\n";
        cout << "Press 3 to find the total amount of colleges and";
        cout << " universities in our list. ";
        cout << "\nPress 4 to quit. ";
        cin >> choice;
        cin.get(); // <- added this to eat the newline left after getting the number

        if (choice == 1)
        {
            collegesUniversities();
        }

        else if (choice == 2)
        {

        }

        else if (choice == 3)
        {

        }

        else if (choice == 4)
        {
            cout << "\nThank you for using my program. ";
            cout << "Have a great day.\n ";
        }

        else
        {
            cerr << "\nError, Invalid input. ";
            cout << "Only integers from 1 through 4 are allowed.\n";
        }
    } while (choice != 4);
}

Nathan, if I could give you one thousand upvotes I would. Thanks for the help.
Before you go, refresh my memory. What is the purpose of cin.get() and why there(also what do you mean by "eat")?

When you do:

cout << "enter some information: ";
cin >> choice;

And the users enters 1 then what actually goes into the stream is "1\n" and cin >> choice will read until it hits whitespace (space, tab, newline) and it leaves the whitespace in place. So after you do cin >> choice the stream will contain "\n". This becomes a problem if you use getline(). getline() function as read what is in the stream until you hit the delimeter (default is newline) and then discard the delimeter. So if the stream has "\n" you then do:

cout << "enter some information: ";
getline(cin,info);

And the user enter test then the stream becomes "\ntest\n". Calling getline() it would see the newline and stop reading leaving "test\n" in the buffer.

So if we call cin.get() after cin >> choice get() will read and throw out 1 character in the buffer. Since cin >> choice would leave the buffer with "\n" get() will consume that (eat) and getline will work properly.

JasonHippy has a better way of doing that and it is using cin.ignore(std::numeric_limits<int>::max(), '\n'); but i know get() works in this case so thats why I used it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.