-2

Ok, so for my school project we are basically making a menu with 20 max people to enter information and change if need be. Everything was working fine. However, our assignment has us check input for zip code and Account Balance for integer values. I used a do-while loop for ZipCode validation until a positive number and a digit was entered. However, I get an infinite loop that I can't seem to fix. Here is my code. The error lies on lines 57-68 if you put into a compiler. Every time I enter a letter instead of a integer, I get an infinite loop. But I can't figure out why. Thanks!

#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>

using namespace std;

struct Account //Structure to be used throughout
{
     string CustomerName; 
     string CustomerAddress;
     string City;
     string State;
     int ZIPCode;
     string Telephone;
     int AccountBalance;
     string DateOfLastPayment;

};



//function prototypes 
void valueChangeFunc(string, Account[], int);//This function will be used in option 2 for editing a certain customer information



int main()
{
    Account array[20]; //Array to hold up to 20 customers 
    int choice;  //this will hold which option the user decides to make 1-4
    bool flagZip = false; //This will be used later on as a flag for a do-while loop
    bool flag = false; //This will be used as a flag for the do-while loop right now
    int index = 0; //Index for our customers. This tells how many customers have been entered
    do //This do while loop will continue to ask the user what option to do until array fills up with 20 people and 4 is not entered
    {
    cout << "1. Enter new account information \n" <<endl 
     << "2. Change account information \n" << endl
     << "3. Display all account information\n" <<endl
     << "4. Exit the program \n" <<endl;
     cin >> choice; 
if (choice > 4 || choice <= 0)//If user enters a number bigger than 4 or less then or equal to 0. Error! 
cout << "Please enter a number between 1 and 4" << endl;

else if(choice == 1)
{
cout << "CustomerName: ";
        cin.ignore();
    getline(cin, array[index].CustomerName);
    cout << "CustomerAddress ";
    getline(cin, array[index].CustomerAddress);
    cout << "City: ";
    getline(cin, array[index].City);
    cout << "State: ";
    getline(cin, array[index].State);

    do
    {
    cout << "Zip Code: ";
    cin >> array[index].ZIPCode;
    cin.ignore();
    if (!isdigit(array[index].ZIPCode) && array[index].ZIPCode <= 0)
    cout << "Please enter a valid entry " << endl;

    else 
    flagZip = true;

    }while(flagZip == false);

    cout << "Telephone: ";
    getline(cin, array[index].Telephone);

    flagZip = false;

    do 
    {
    cout << "AccountBalance: ";
    cin >> array[index].AccountBalance;
    cin.ignore();
    if (array[index].AccountBalance <= 0)
    cout << "Please enter a valid entry " << endl;

    else
    flagZip = true;
    }while(flagZip == false); 

    cout << "DateOfLastPayment: ";
    getline(cin, array[index].DateOfLastPayment);


    cout << "\n\nCustomerName: " << array[index].CustomerName << endl;
    cout << "CustomerAddress " << array[index].CustomerAddress <<endl;
    cout << "City: " << array[index].City << endl;
    cout << "State: " << array[index].State << endl;
    cout << "Zip Code: " << array[index].ZIPCode << endl;
    cout << "Telephone: " << array[index].Telephone <<endl;
    cout << "AccountBalance: " << array[index].AccountBalance << endl;
    cout << "DateOfLastPayment: " << array[index].DateOfLastPayment << endl;
    cout << "You have entered information for customer number " << index << endl << endl;

    index++;
}
else if(choice == 2 && index != 0)
{
int num;
string valueChange;
do
{
cout << "  Customer number: ";
cin >> num;

if (num > (index-1) || num < 0)
cout << " There is no customer with that number " << endl;

}while (num > (index-1));
    cout << "\n\nCustomer Name: " << array[num].CustomerName << endl;
    cout << "Customer Address " << array[num].CustomerAddress <<endl;
    cout << "City: " << array[num].City << endl;
    cout << "State: " << array[num].State << endl;
    cout << "ZIPCode: " << array[num].ZIPCode << endl;
    cout << "Telephone: " << array[num].Telephone <<endl;
    cout << "Account Balance: " << array[num].AccountBalance << endl;
    cout << "Date of last payment: " << array[num].DateOfLastPayment << endl;
    cout << "You have requested information for customer number " << num << endl << endl;

    cout << "What value do you want to change? (press 4 to change 'Date of last payment') \n"; 
    cin.ignore();
    getline(cin,valueChange);

    valueChangeFunc(valueChange, array, num);

    cout << "\nHere is the new value you entered for " << valueChange << endl;

    cout << "\n\nCustomer Name: " << array[num].CustomerName << endl;
    cout << "Customer Address " << array[num].CustomerAddress <<endl;
    cout << "City: " << array[num].City << endl;
    cout << "State: " << array[num].State << endl;
    cout << "ZIPCode: " << array[num].ZIPCode << endl;
    cout << "Telephone: " << array[num].Telephone <<endl;
    cout << "Account Balance: " << array[num].AccountBalance << endl;
    cout << "Date of last payment: " << array[num].DateOfLastPayment << endl << endl;

}

else if(choice == 3 && index != 0)
{
    int num2;
do
{
    cout << "Enter the Customer Number to display information regarding that customer" << endl;
    cin >> num2; 
if (num2 > (index-1) || num2 < 0)
cout << "That Customer does not exist " <<endl; 
}
while(num2 > (index-1));


    cout << "\n\nCustomerName: " << array[num2].CustomerName << endl;
    cout << "CustomerAddress " << array[num2].CustomerAddress <<endl;
    cout << "City: " << array[num2].City << endl;
    cout << "State: " << array[num2].State << endl;
    cout << "Zip Code: " << array[num2].ZIPCode << endl;
    cout << "Telephone: " << array[num2].Telephone <<endl;
    cout << "AccountBalance: " << array[num2].AccountBalance << endl;
    cout << "DateOfLastPayment: " << array[num2].DateOfLastPayment << endl;
    cout << "You have entered information for customer number " << index << endl << endl;

}

else 
flag = true;

}while (flag == false);

    return 0;
}

void valueChangeFunc(string valueChange2, Account array[], int num)
{
    if (valueChange2 == "Customer Name" || valueChange2 == "Customer name" || valueChange2 == "customer Name" || valueChange2 == "customer name")
    {
    cout << "\nEnter new value for Customer Name: " <<endl;
    getline(cin, array[num].CustomerName);

    }

    if (valueChange2 == "Customer Address" || valueChange2 == "Customer address" || valueChange2 == "customer Address" || valueChange2 == "customer address")
    {
    cout << "\nEnter new value for Customer Address: " <<endl;
    getline(cin, array[num].CustomerAddress);

    }
    else if(valueChange2 == "city" || valueChange2 == "City")
    {
        cout << "\nEnter new value for City: " << endl;
        getline(cin, array[num].City);

    }
    else if(valueChange2 == "state" || valueChange2 == "State")
    {
        cout << "Enter a value for State: " << endl;
        getline(cin,array[num].State);

    }

    else if(valueChange2 == "Zip Code" || valueChange2 == "zip Code" || valueChange2 == "Zip code" || valueChange2 == "zip code")
    {
        cout << "\nEnter a value for Zip Code: " << endl;
        cin >> array[num].ZIPCode;

    } 

    else if(valueChange2 == "telephone" || valueChange2 == "Telephone")
    {
        cout << "\nEnter a value for Telephone: " << endl;
        getline(cin, array[num].Telephone);

    }

    else if(valueChange2 == "Account Balance" || valueChange2 == "Account balance" || valueChange2 == "account Balance" || valueChange2 == "account balance")
    {
        cout << "\nEnter a value for account balance: " << endl;
        cin >> array[num].AccountBalance;

    }
    else if(valueChange2 == "4")
    {
        cout << "\nEnter the value for Date of last payment: " << endl;
        getline(cin, array[num].DateOfLastPayment);

    }

    else 
    cout << "Not entered correctly. Please enter a valid entry to edit " << endl;

}

Again everything worked until I started to use a loop to check for digit value of ZipCode. The loop only goes infinite when I enter a letter. It works for a negative number and positive number.

  • A debugger can find this for you within seconds. Worth the time spent learning to use it. – user4581301 Mar 06 '16 at 04:23
  • gcc 5.3 compiled this code without any errors. If you do not understand the compiler's error message, in addition to posting the code you should also include the actual errors from the compiler. – Sam Varshavchik Mar 06 '16 at 04:24
  • 1
    There is no error in the compiler. Just an infinite loop when I enter a letter in the ZipCode section. – Carter Hunt Mar 06 '16 at 04:26
  • 1
    Welcome to Stack Overflow! Please read [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) and edit your question to reflect your changes. You've got a lot of code there, and I'm willing to bet it isn't all applicable. – johnnyRose Mar 06 '16 at 04:35
  • Interesting fun fact about iostreams. When you try to make them do something stupid, like read a word where a number should have been, they go into an error state and refuse to come out until cleared with `clear`, not `ignore`. – user4581301 Mar 06 '16 at 04:36
  • 1
    Evil twin question: http://stackoverflow.com/questions/5864540/infinite-loop-with-cin I can't flag at as a dupe because I already voted to close over a lack of MCVE. Here is a closer one: http://stackoverflow.com/questions/19521320/why-do-i-get-an-infinite-loop-if-i-enter-a-letter-rather-than-a-number – user4581301 Mar 06 '16 at 04:37
  • user4581301 thank you! This might be my problem! I'll try it. Thanks! – Carter Hunt Mar 06 '16 at 04:46
  • I just tried it! It works! Man, I've spent hours trying to fix it. Thanks! Appreciate the help everyone! – Carter Hunt Mar 06 '16 at 04:53

1 Answers1

0

Short answer can be found in cplusplus.com (read the third paragraph)

Long answer:

This error isn't about ZipCode only, you can generate the same error when you input a letter instead of a number at the very first cin call.

cin is not type-safe so using a wrong type as an input results in an undefined behaviour (like the infinite loop you were experiencing) and that is why cin is a bit prone to errors. Also, cin gets the input value, however it doesn't remove newline, reading to a bit dirtier input from what you'd get with other methods.

Speaking of other methods, as explained in the link, try to use getline() whenever it is possible. You can use that function to get what cin buffer contains as a string and do additional type-check if necessary. Bug-free programs are more important than shorter programs.

As a personal note: try to use while loops instead of do..while ones when you can. That is not a general rule of programming but it looks more readable and is easier to understand in general (IMHO).

Also, try to use functions to split your program into parts. For example, the cout blocks where you are just printing the information stored to the screen can be turned into a function. You're using the same cout structure (it would shorten your code by 4 * 9 lines).

Finally, if you're using an integer as a key value to separate algorithms, try to use switch...case instead of if-else blocks. (Again, just my opinion).

gamiseta
  • 85
  • 7
  • 1
    Thanks! Lots of great advice! I'm a Java programmer, so I'm just starting C++. I'm unfamiliar with 'cin' input errors, because of using Java. So thank you! I see your point on making a function to out 'cout'. The reason I didn't do this is because my teacher made restrictions. But again, I see your point. Thank you for the advice! – Carter Hunt Mar 06 '16 at 15:25