Flushing Data in Loop? -- Keep Entering Empty Space

Click For Summary
SUMMARY

The discussion centers on a C++ programming issue where the user experiences an unexpected blank output after processing a menu option for entering cell phone minutes. The problem arises in the segment where user input is collected, specifically after the "if (menuOptionStrInt == '1')" condition. The user suspects that the program does not properly flush the input buffer, leading to an empty line being printed before returning to the main menu. The solution involves ensuring that the input buffer is cleared after reading integer values.

PREREQUISITES
  • Understanding of C++ syntax and structure
  • Familiarity with input/output operations in C++
  • Knowledge of data types and variable handling in C++
  • Basic debugging techniques in programming
NEXT STEPS
  • Research C++ input buffer management techniques
  • Learn about the use of cin.ignore() to clear input buffers
  • Explore error handling in user input for C++ applications
  • Investigate best practices for structuring C++ console applications
USEFUL FOR

Beginner C++ programmers, educators teaching programming fundamentals, and developers troubleshooting input/output issues in console applications.

vr0nvr0n
Messages
20
Reaction score
0
Hello,

I am in my first class for C++, so I apologize in advance if this question is amateurish. To be clear, this project is already finished, and what I am trying to do already counted points off against me; I am not interested in cheating, I just want to know what the answer to my issue is.

My code is below surrounded by ---'s (there is a part asking for a text file involved only in the project, please ignore). The issue is under the "if (menuOptionStrInt == "1"){" segment.

Effectively, this part of the code is meant to prompt the user to enter their information and to enter an amount of cell phone minutes used. The program then returns the amount owed per cell minutes used, which the user is asked to pay in pennies (e.g., if $10.00 is owed, and you wanted to pay off the full amount: when prompted, you would enter 1000 to represent the amount of pennies paid). You may enter an insufficient amount; however, the program simply returns you to the main menu with a simple error message in this case.

My problem is that, when I go through menu option 1, no matter what I do, once I reach the end, the program returns to the main menu, enters a blank space, then returns to the menu again (resulting in two main menu screens with no options entered). Constructively, this does not cause any issues, as it eventually returns the user to the main menu where you should be returned to anyway. I just do not know why it is doing this, or how to prevent it. My suspicion, based on a few quick web searches, is that my program does not flush the data entry made for "minutesUsed" (it collects the "enter" if I understand this correctly?).

Thank you so much in advance. Feel free to tell me that I need to reformat this differently for ease of reference.

Here is the code:

---------------------------------------------------------------------------------------------------------------------------------

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <fstream>

using namespace std;

int main(){
//Set main variables
string customerName, address, city, state, zip, menuOptionStrInt, menuOptionStrChar;
int minutesUsed, amountOwedInteger, customerAmount, changeDollars, changeQuarters, changeDimes, changeNickels, changePennies, i;
double amountOwed;
const double PER_MINUTES_CONSTANT = 0.20, BASE_CHARGE_CONSTANT = 10.00;
ifstream inputfile;
//begin the do/while loop to keep the user in the program unless they select to quit
do{
//prompt the user with a menu presenting the options
count << endl << "Welcome to the Cellular Telephone System" << endl;
count << endl;
count << "1 - Process Telephone Bill" << endl;
count << "2 - Translate Phone Word" << endl;
count << "3 - Process a Data File" << endl;
count << "4 - Quit" << endl;
count << endl;
count << "Enter your choice: ";
getline(cin, menuOptionStrInt);
count << endl;
//begin the options from the menu. The first is for the customer to enter data
if (menuOptionStrInt == "1"){
count << "Enter the name of the customer: ";
getline(cin, customerName);
count << "Enter street address: ";
getline(cin, address);
count << "Enter city: ";
getline(cin, city);
count << "Enter state: ";
getline(cin, state);
count << "Enter zip code: ";
getline(cin, zip);
count << "Enter the number of minutes used: ";
cin >> minutesUsed;
count << endl;
//Calculate the amount owed
if (minutesUsed <= 50){
amountOwed = BASE_CHARGE_CONSTANT;
}
else{
amountOwed = ((minutesUsed - 50) * PER_MINUTES_CONSTANT) + BASE_CHARGE_CONSTANT;
}
//Return all of the previously entered information and the amount owed
count << endl;
count << customerName << endl;
count << address << endl;
count << city << ", " << state << " " << zip << endl;
count << "Amount Owed: $" << setprecision(2) << fixed << amountOwed << endl;
//Prompt the user to enter the amount received from the customer in pennies
count << endl;
count << "Enter the amount received from the customer: ";
cin >> customerAmount;
count << endl;
//Calculate the variables for change
amountOwedInteger = amountOwed * 100;

if (customerAmount < amountOwedInteger){
count << "The amount paid is not enough to cover the cost of the bill." << endl;
count << "You must pay " << amountOwedInteger - customerAmount << " more pennies to pay off the bill." << endl;
}
else{
customerAmount = customerAmount - amountOwedInteger;
changeDollars = customerAmount/100;
customerAmount %= 100;
changeQuarters = customerAmount/25;
customerAmount %= 25;
changeDimes = customerAmount/10;
customerAmount %= 10;
changeNickels = customerAmount/5;
customerAmount %= 5;
changePennies = customerAmount;
//Output the change in a formatted table
count << endl;
count << "Denomination" << setw(11) << "Number" << endl;
count << "----------" << setw(15) << "----------" << endl;
count << "Dollars " << setw(12) << changeDollars << endl;
count << "Quarters " << setw(11) << changeQuarters << endl;
count << "Dimes " << setw(14) << changeDimes << endl;
count << "Nickels " << setw(12) << changeNickels << endl;
count << "Pennies " << setw(12) << changePennies << endl;
}
}
else if (menuOptionStrInt == "2"){
count << "Enter the phone word: ";
getline(cin, menuOptionStrChar);
if (menuOptionStrChar.length() != 8){
count << endl << "You must enter a value in the following format\n\n`XXX-XXXX`\n\nwhere `X` is a letter and the `-`\nis a simple dash." << endl;
continue;
}
else if (menuOptionStrChar.at(3) != '-'){
count << endl << "You must enter a value in the following format\n\n`XXX-XXXX`\n\nwhere `X` is a letter and the`-`\nis a simple dash." << endl;
continue;
}
count << endl << menuOptionStrChar << " translates to ";
for(i = 0; i < menuOptionStrChar.length(); i++){
int number;
if ((menuOptionStrChar.at(i) >= 'A' && menuOptionStrChar.at(i) <= 'Z') || (menuOptionStrChar.at(i) >= 'a' && menuOptionStrChar.at(i) <= 'z') || (menuOptionStrChar.at(i) == '-')){
switch (menuOptionStrChar.at(i)){
case '-':
count << "-";
continue;
break;

case 'A':
case 'a':
case 'B':
case 'b':
case 'C':
case 'c':
number = 2;
break;

case 'D':
case 'd':
case 'E':
case 'e':
case 'F':
case 'f':
number = 3;
break;

case 'G':
case 'g':
case 'H':
case 'h':
case 'I':
case 'i':
number = 4;
break;

case 'J':
case 'j':
case 'K':
case 'k':
case 'L':
case 'l':
number = 5;
break;

case 'M':
case 'm':
case 'N':
case 'n':
case 'O':
case 'o':
number = 6;
break;

case 'P':
case 'p':
case 'Q':
case 'q':
case 'R':
case 'r':
case 'S':
case 's':
number = 7;
break;

case 'T':
case 't':
case 'U':
case 'u':
case 'V':
case 'v':
number = 8;
break;

case 'W':
case 'w':
case 'X':
case 'x':
case 'Y':
case 'y':
case 'Z':
case 'z':
number = 9;
break;
}
count << number;
}
//This line spits out a '*' whenever a non valid, but correctly formatted, letter is entered
else{
count << "*";
}
}
count << endl;
}
//option 3 is for reading a data file containing information from option 1
else if (menuOptionStrInt == "3"){
//string variable for spitting out data
string customerData;
double numberData;
//open file
inputfile.open("TelephoneData.txt");
//create loop to read data per entry based on the expected format
while ((inputfile >> customerData) || (inputfile >> numberData)){
//first name output
count << customerData;
//move to last name
inputfile >> customerData;
//space and the last name output and endline
count << " " << customerData << endl;
//move to numeric part of address
inputfile >> customerData;
//output numeric part of address and add space
count << customerData;
//grab text part of address
getline(inputfile, customerData);
//output text part of address and end line
count << customerData << endl;
//collect city
inputfile >> customerData;
//out put city with no space, but add comma
count << customerData << ", ";
//collect state
inputfile >> customerData;
//output state with space
count << customerData << " ";
//collect zip
inputfile >> customerData;
//output city state and zip
count << customerData << endl;
//collect amount owed
inputfile >> numberData;
numberData = numberData / 100;
count << "Amount owed: $" << setprecision(2) << fixed << numberData << endl << endl;
}
//close the file
inputfile.close();
}
else if (menuOptionStrInt == "4"){
count << "Thank you. Closing program";
}
else{
count << menuOptionStrInt << " is not a valid choice. \n" << endl;
}
}while (menuOptionStrInt != "4");
return 0;
}

---------------------------------------------------------------------------------------------------------------------------------

Thanks again
 
Technology news on Phys.org
Code:
#include <stdio.h>

void main()
{
  printf("Please use the [cоde][/cоde] tags\n");
}
 
vr0nvr0n said:
My problem is that, when I go through menu option 1, no matter what I do, once I reach the end, the program returns to the main menu, enters a blank space, then returns to the menu again (resulting in two main menu screens with no options entered). Constructively, this does not cause any issues, as it eventually returns the user to the main menu where you should be returned to anyway. I just do not know why it is doing this, or how to prevent it. My suspicion, based on a few quick web searches, is that my program does not flush the data entry made for "minutesUsed" (it collects the "enter" if I understand this correctly?).
The last input you do is for minutesUsed, an integer quantity. The << operator converts a string of digit characters ('0', '1', '2', etc.) into an integer value, stopping when it encounters whitespace (space, tab, newline). If you type '3' '2' [Return], minutesUsed will be set to 32, but the input buffer will still contain the value for the Return key. If the next input you do is for a string, that character will be read into the string. The fix for this is the flush the input buffer after you have read all the values in that iteration of your loop.

vr0nvr0n said:
Feel free to tell me that I need to reformat this differently for ease of reference.
Please use code tags, as Borek mentioned. Doing so will preserve your indentation, which I hope you used. This makes your code much easier to read.

Also, your code is monolithic, with everything happening in the main() function. Have you learned about how to write functions yet? A rough rule of thumb is that the code for a function, including main() shouldn't be more than would fit on a computer screen.
 
Mark44 said:
Also, your code is monolithic, with everything happening in the main() function. Have you learned about how to write functions yet? A rough rule of thumb is that the code for a function, including main() shouldn't be more than would fit on a computer screen.

Yes. So, the way this class is set up, when doing these challenges we are only able to use the concepts covered in certain chapters. As such, this project did not allow for the use of functions, though we have learned them.

Mark44 said:
The last input you do is for minutesUsed, an integer quantity. The << operator converts a string of digit characters ('0', '1', '2', etc.) into an integer value, stopping when it encounters whitespace (space, tab, newline). If you type '3' '2' [Return], minutesUsed will be set to 32, but the input buffer will still contain the value for the Return key. If the next input you do is for a string, that character will be read into the string. The fix for this is the flush the input buffer after you have read all the values in that iteration of your loop.

Thank you for your response. I had thought that adding the "count << endl;" would have cleaned up everything I needed after minutesUsed. Is there a way to flush the input buffer without using getline()?

edit: I replied with the reformatted code, as I was unable to edit my original post.
 
Code:
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <fstream>

using namespace std;

int main(){
    //Set main variables
    string customerName, address, city, state, zip, menuOptionStrInt, menuOptionStrChar;
    int minutesUsed, amountOwedInteger, customerAmount, changeDollars, changeQuarters, changeDimes, changeNickels, changePennies, i;
    double amountOwed;
    const double PER_MINUTES_CONSTANT = 0.20, BASE_CHARGE_CONSTANT = 10.00;
    ifstream inputfile;
    //begin the do/while loop to keep the user in the program unless they select to quit
    do{
        //prompt the user with a menu presenting the options
        cout << endl << "Welcome to the Cellular Telephone System" << endl;
        cout << endl;
        cout << "1 - Process Telephone Bill" << endl;
        cout << "2 - Translate Phone Word" << endl;
        cout << "3 - Process a Data File" << endl;
        cout << "4 - Quit" << endl;
        cout << endl;
        cout << "Enter your choice: ";
        getline(cin, menuOptionStrInt);
        cout << endl;
        //begin the options from the menu. The first is for the customer to enter data
        if (menuOptionStrInt == "1"){
            cout << "Enter the name of the customer: ";
            getline(cin, customerName);
            cout << "Enter street address: ";
            getline(cin, address);
            cout << "Enter city: ";
            getline(cin, city);
            cout << "Enter state: ";
            getline(cin, state);
            cout << "Enter zip code: ";
            getline(cin, zip);
            cout << "Enter the number of minutes used: ";
            cin >> minutesUsed;
            cout << endl;
            //Calculate the amount owed
            if (minutesUsed <= 50){
                amountOwed = BASE_CHARGE_CONSTANT;
            }
            else{
                amountOwed = ((minutesUsed - 50) * PER_MINUTES_CONSTANT) + BASE_CHARGE_CONSTANT;
            }
            //Return all of the previously entered information and the amount owed
            cout << endl;
            cout << customerName << endl;
            cout << address << endl;
            cout << city << ", " << state << " " << zip << endl;
            cout << "Amount Owed: $" << setprecision(2) << fixed << amountOwed << endl;
            //Prompt the user to enter the amount received from the customer in pennies
            cout << endl;
            cout << "Enter the amount received from the customer: ";
            cin >> customerAmount;
            cout << endl;
            //Calculate the variables for change
            amountOwedInteger = amountOwed * 100;
 
            if (customerAmount < amountOwedInteger){
                cout << "The amount paid is not enough to cover the cost of the bill." << endl;
                cout << "You must pay " << amountOwedInteger - customerAmount << " more pennies to pay off the bill." << endl;
            }
            else{
                customerAmount = customerAmount - amountOwedInteger;
                changeDollars = customerAmount/100;
                customerAmount %= 100;
                changeQuarters = customerAmount/25;
                customerAmount %= 25;
                changeDimes = customerAmount/10;
                customerAmount %= 10;
                changeNickels = customerAmount/5;
                customerAmount %= 5;
                changePennies = customerAmount;
                //Output the change in a formatted table
                cout << endl;
                cout << "Denomination" << setw(11) << "Number" << endl;
                cout << "----------" << setw(15) << "----------" << endl;
                cout << "Dollars " << setw(12) << changeDollars << endl;
                cout << "Quarters " << setw(11) << changeQuarters << endl;
                cout << "Dimes " << setw(14) << changeDimes << endl;
                cout << "Nickels " << setw(12) << changeNickels << endl;
                cout << "Pennies " << setw(12) << changePennies << endl;
            }
        }
        else if (menuOptionStrInt == "2"){
            cout << "Enter the phone word: ";
            getline(cin, menuOptionStrChar);
            if (menuOptionStrChar.length() != 8){
                cout << endl << "You must enter a value in the following format\n\n`XXX-XXXX`\n\nwhere `X` is a letter and the `-`\nis a simple dash." << endl;
                continue;
            }
            else if (menuOptionStrChar.at(3) != '-'){
                cout << endl << "You must enter a value in the following format\n\n`XXX-XXXX`\n\nwhere `X` is a letter and the`-`\nis a simple dash." << endl;
                continue;
            }
            cout << endl << menuOptionStrChar << " translates to ";
            for(i = 0; i < menuOptionStrChar.length(); i++){
                int number;
                if ((menuOptionStrChar.at(i) >= 'A' && menuOptionStrChar.at(i) <= 'Z') || (menuOptionStrChar.at(i) >= 'a' && menuOptionStrChar.at(i) <= 'z') || (menuOptionStrChar.at(i) == '-')){
                    switch (menuOptionStrChar.at(i)){
                        case '-':
                        cout << "-";
                        continue;
                        break;
                       
                        case 'A':
                        case 'a':
                       case 'B':
                        case 'b':
                       case 'C':
                        case 'c':
                      number = 2;
                        break;
                   
                        case 'D':
                        case 'd':
                       case 'E':
                        case 'e':
                       case 'F':
                        case 'f':
                      number = 3;
                        break;
                   
                        case 'G':
                        case 'g':
                       case 'H':
                        case 'h':
                       case 'I':
                        case 'i':
                      number = 4;
                        break;
                   
                          case 'J':
                        case 'j':
                       case 'K':
                        case 'k':
                       case 'L':
                        case 'l':
                      number = 5;
                        break;
                   
                        case 'M':
                        case 'm':
                       case 'N':
                        case 'n':
                       case 'O':
                        case 'o':
                      number = 6;
                        break;
                   
                        case 'P':
                        case 'p':
                       case 'Q':
                        case 'q':
                       case 'R':
                        case 'r':
                        case 'S':
                        case 's':
                      number = 7;
                        break;
                   
                        case 'T':
                        case 't':
                       case 'U':
                        case 'u':
                       case 'V':
                        case 'v':
                      number = 8;
                        break;
                   
                        case 'W':
                        case 'w':
                       case 'X':
                        case 'x':
                       case 'Y':
                        case 'y':
                        case 'Z':
                        case 'z':
                      number = 9;
                        break;
                      }
                    cout << number;
                }
                //This line spits out a '*' whenever a non valid, but correctly formatted, letter is entered
                else{
                    cout << "*";
                }
            }
            cout << endl;
        }
        //option 3 is for reading a data file containing information from option 1
        else if (menuOptionStrInt == "3"){
            //string variable for spitting out data
            string customerData;
            double numberData;
            //open file
            inputfile.open("TelephoneData.txt");
            //create loop to read data per entry based on the expected format
            while ((inputfile >> customerData) || (inputfile >> numberData)){
                //first name output
                cout << customerData;
                //move to last name
                inputfile >> customerData;
                //space and the last name output and endline
                cout << " " << customerData << endl;
                //move to numeric part of address
                inputfile >> customerData;
                //output numeric part of address and add space
                cout << customerData;
                //grab text part of address
                getline(inputfile, customerData);
                //output text part of address and end line
                cout << customerData << endl;
                //collect city
                inputfile >> customerData;
                //out put city with no space, but add comma
                cout << customerData << ", ";
                //collect state
                inputfile >> customerData;
                //output state with space
                cout << customerData << " ";
                //collect zip
                inputfile >> customerData;
                //output city state and zip
                cout << customerData << endl;
                //collect amount owed
                inputfile >> numberData;
                numberData = numberData / 100;
                cout << "Amount owed: $" << setprecision(2) << fixed << numberData << endl << endl;
                }
            //close the file
            inputfile.close();
            }
        else if (menuOptionStrInt == "4"){
            cout << "Thank you. Closing program";
        }
        else{
            cout << menuOptionStrInt << " is not a valid choice. \n" << endl;
        }
    }while (menuOptionStrInt != "4");
    return 0;
}
 
vr0nvr0n said:
I had thought that adding the "count << endl;" would have cleaned up everything I needed after minutesUsed. Is there a way to flush the input buffer without using getline()?
What you did with count has nothing to do with the input buffer. The C standard library has a function named fflush(), but I don't see a C++ counterpart. You could do this:
C:
char ch;
cin >> ch;
That should get rid of any character remaining in the input buffer.
 
vr0nvr0n said:
Is there a way to flush the input buffer without using getline()?
You can use the ignore() member function of istream (including cin):

cin.ignore(80, '\n');

tells cin to read and discard 80 characters, or until it reaches a '\n' (newline), whichever comes first. You can change 80 to some other number according to your taste or requirements (I usually use 80 because that's the traditional line length on old-fashioned text terminals), and you can use any other character as the terminator. (' ' (space) is a common choice for certain applications). That terminating character is discarded, so the next input begins at the following character.
 

Similar threads

  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 5 ·
Replies
5
Views
2K