Trouble with while loop C++ [duplicate] - c++

This question already has answers here:
Using getline(cin, s) after cin [duplicate]
(13 answers)
Closed 7 years ago.
I'm relatively new to C++, but not to programming, and I'm confused as to why I am having this very strange issue with a while loop in my C++ program.
while (runUserInputLoop)
{
displayMenu();
cout << "Enter the number that corresponds with your choice from the menu: ";
getline(cin, menuLoopChoice);
if (menuLoopChoice == "1")
{
cout << "Enter mean: ";
cin >> mean;
cout << "Enter z-score: ";
cin >> z;
cout << "Enter standard deviation: ";
cin >> stDev;
cout << "Enter sample size: ";
cin >> n;
oneSampZInt(mean, z, stDev, n);
}
else if (menuLoopChoice == "2")
{
cout << "Enter mean: ";
cin >> mean;
cout << "Enter t-score: ";
cin >> t;
cout << "Enter standard deviation: ";
cin >> stDev;
cout << "Enter sample size: ";
cin >> n;
oneSampTInt(mean, t, stDev, n);
}
else if (menuLoopChoice == "3")
{
cout << "Enter mean for first sample: ";
cin >> mean1;
cout << "Enter mean for second sample: ";
cin >> mean2;
cout << "Enter standard deviation for first sample: ";
cin >> stDev1;
cout << "Enter standard deviation for second sample: ";
cin >> stDev2;
cout << "Enter z-score: ";
cin >> z;
cout << "Enter size of first sample: ";
cin >> n1;
cout << "Enter size of second sample: ";
cin >> n2;
indepMeansZInt(mean1, mean2, stDev2, stDev1, n1, n2, z);
}
else if (menuLoopChoice == "4")
{
cout << "Enter mean for first sample: ";
cin >> mean1;
cout << "Enter mean for second sample: ";
cin >> mean2;
cout << "Enter standard deviation for first sample: ";
cin >> stDev1;
cout << "Enter standard deviation for second sample: ";
cin >> stDev2;
cout << "Enter t-score: ";
cin >> t;
cout << "Enter size of first sample: ";
cin >> n1;
cout << "Enter size of second sample: ";
cin >> n2;
indepMeansTInt(mean1, mean2, stDev2, stDev1, n1, n2, t);
}
else if (menuLoopChoice == "5")
{
cout << "Enter sample proportion: ";
cin >> p;
cout << "Enter sample size: ";
cin >> n;
cout << "Enter z-score";
cin >> z;
onePropZInt(p, n, z);
}
else if (menuLoopChoice == "6")
{
cout << "Enter proportion from sample one: ";
cin >> p1;
cout << "Enter proportion from sample two: ";
cin >> p2;
cout << "Enter size of sample one: ";
cin >> n1;
cout << "Enter size of sample two: ";
cin >> n2;
cout << "Enter z-score";
cin >> z;
twoPropZInt(p1, p2, n1, n2, z);
}
else if (menuLoopChoice == "7")
{
cout << "Enter chi-sqaured right value: ";
cin >> chiSqrdRight;
cout << "Enter chi-sqaured left value: ";
cin >> chiSqrdLeft;
cout << "Enter sample variance: ";
cin >> variance;
cout << "Enter sample size: ";
cin >> n;
chiSqrdInt(chiSqrdRight, chiSqrdLeft, variance, n);
}
else if (menuLoopChoice == "8")
{
cout << "Enter mean of differences: ";
cin >> DBar;
cout << "Enter standard deviation of differences: ";
cin >> SD;
cout << "Enter number of matched pairs: ";
cin >> n;
cout << "Enter t-score: ";
cin >> t;
matchedPairsTInt(DBar, SD, n, t);
}
else if (menuLoopChoice == "A" || menuLoopChoice == "a")
{
cout << "Enter population mean: ";
cin >> mean1;
cout << "Enter sample mean: ";
cin >> mean2;
cout << "Enter population standard deviation: ";
cin >> stDev;
cout << "Enter size of sample: ";
cin >> n;
cout << "Enter z-score: ";
cin >> z;
oneSampZTest(mean1, mean2, stDev, n, z);
}
else if (menuLoopChoice == "B" || menuLoopChoice == "b")
{
cout << "Enter mean of sample one: ";
cin >> mean1;
cout << "Enter mean of sample two: ";
cin >> mean2;
cout << "Enter standard deviation of population one: ";
cin >> stDev1;
cout << "Enter standard deviation of population two: ";
cin >> stDev2;
cout << "Enter size of sample one: ";
cin >> n1;
cout << "Enter size of sample two: ";
cin >> n2;
cout << "Enter z-score: ";
cin >> z;
twoSampZTest(mean1, mean2, stDev1, stDev2, n1, n2, z);
}
else if (menuLoopChoice == "C" || menuLoopChoice == "c")
{
cout << "Enter population mean: ";
cin >> mean1;
cout << "Enter sample mean: ";
cin >> mean2;
cout << "Enter sample standard deviation: ";
cin >> stDev;
cout << "Enter size of sample: ";
cin >> n;
cout << "Enter t-score: ";
cin >> t;
oneSamptTest(mean1, mean2, stDev, n, z);
}
else if (menuLoopChoice == "D" || menuLoopChoice == "d")
{
cout << "Enter mean of sample one: ";
cin >> mean1;
cout << "Enter mean of sample two: ";
cin >> mean2;
cout << "Enter standard deviation of sample one: ";
cin >> stDev1;
cout << "Enter standard deviation of sample two: ";
cin >> stDev2;
cout << "Enter size of sample one: ";
cin >> n1;
cout << "Enter size of sample two: ";
cin >> n2;
cout << "Enter t-score: ";
cin >> t;
twoSamptTest(mean1, mean2, stDev1, stDev2, n1, n2, t);
}
else if (menuLoopChoice == "E" || menuLoopChoice == "e")
{
cout << "Enter the population proportion: ";
cin >> p1;
cout << "Enter the sample proportion: ";
cin >> p2;
cout << "Enter the sample size: ";
cin >> n;
cout << "Enter the z-score: ";
cin >> z;
onePropZTest(p1, p2, n, z);
}
else if (menuLoopChoice == "F" || menuLoopChoice == "f")
{
cout << "Enter sample proportion one: ";
cin >> p1;
cout << "Enter sample proportion two: ";
cin >> p2;
cout << "Enter the x value of proportion one: ";
cin >> x1;
cout << "Enter the x value of proportion two: ";
cin >> x2;
cout << "Enter the size of sample one: ";
cin >> n1;
cout << "Enter the size of sample two: ";
cin >> n2;
cout << "Enter the z-score: ";
cin >> z;
twoPropZTest(p1, p2, x1, x2, n1, n2, z);
}
else if (menuLoopChoice == "q" || menuLoopChoice == "Q")
{
runUserInputLoop = false;
}
}
On the first iteration through the loop, everything works fine. However, on all subsequent iterations, the loop seems to iterate once, without any input, and then again, allowing me to enter input once again. So essentially, there is an extra iteration that causes it to perform this portion of the while loop twice:
displayMenu();
cout << "Enter the number that corresponds with your choice from the menu: ";
getline(cin, menuLoopChoice);
Here is a picture of how it looks in the console: . The crudely circled portion is the "ghost iteration." I feel like it should be something simple, but I'm not extremely familiar with C++ yet, so I'm stumped. The full code for the program is available here if necessary.

std::istream::operator>> reads characters from the stream until it encounters whitespace (such as an end-of-line character), but it leaves the whitespace character in the stream, so the next read will see it. That's fine if the next read is an operator>>, since it will skip over leading whitespace, but std::getline() just reads until it sees the delimiter character ('\n' by default). Since the previous call to operator>> left a '\n' as the next character in the stream, std::getline() sees it, and returns immediately. To get around this, you can call std::cin.ignore() at the end of your loop to discard the '\n' that's been left in the input stream.

Related

Undefined reference error along with exit status error when trying to call function in database management system

So I am trying to call a function which creates an assessment class object within the newStudent function. Ideallly the aim is for the newStudent function to run and after it reaches level selection it would call the respective makeAssess functions. Each of the makeAssess functions would then recursively call themselves until the total weighting of each level is 100 and then move onto the next makeAssess function. All the makeAssess functions were already defined at the start of the program.
Edit: Iam using CodeBlocks with a GNU GCC compiler. The two errors are "|undefined reference to `makeassessH()'|" and "|error: ld returned 1 exit status|"
MPE:
//Relevant libraries
#include <iostream>
#include <fstream>
using namespace std;
int option;
void newStudent();
void makeassessH();
void makeassessI();
void makeassessC();
class Student {
public:
int stuNum;
std::string stuName;
int startDate;
int endDate;
string progofStudy;
char level;
};
class Assessment{
public:
std::string title;
int weight;
double grade;
string deadline;
};
int main()
{
//The option page
while (option != 5) {
cout << "\nPlease choose an option\n"
"1. Add new students\n"
"2. Student Login\n"
"3. Staff Login\n"
"4. Admin View\n"
"5. Exit\n"
"Enter option: ";
cin >> option;
if (option == 1) {
newStudent();
} else if (option == 5)
return 0;
}
}
void newStudent() {
Student stu;
string studentName = stu.stuName;
cout << "Please enter in your student number: ";
cin >> stu.stuNum;
cout << "Please enter in your name: ";
cin.ignore();
getline (cin, studentName);
cout << "Please enter in your start date: ";
cin >> stu.startDate;
cout << "Please enter in your end date: ";
cin >> stu.endDate;
cout << "Please enter in your programme of study: ";
cin.ignore();
getline(cin, stu.progofStudy);
cout << "Please enter your level of study: ";
cin >> stu.level;
if(stu.level == toupper('h')){
makeassessH();
makeassessI();
makeassessC();
}else if (stu.level == toupper('i')){
makeassessI();
makeassessC();
}else if(stu.level == toupper('c')) {
makeassessC();
}
}
void makeassesH(){
Assessment assessmentH;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentH.title);
cout << "Assessment weighting: ";
cin >> assessmentH.weight;
cout << "Assessment grade: ";
cin >> assessmentH.grade;
cout << "Assessment deadline: ";
cin >> assessmentH.deadline;
}
void makeassessI(){
Assessment assessmentI;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentI.title);
cout << "Assessment weighting: ";
cin >> assessmentI.weight;
cout << "Assessment grade: ";
cin >> assessmentI.grade;
cout << "Assessment deadline: ";
cin >> assessmentI.deadline;
}
void makeassessC(){
Assessment assessmentC;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentC.title);
cout << "Assessment weighting: ";
cin >> assessmentC.weight;
cout << "Assessment grade: ";
cin >> assessmentC.grade;
cout << "Assessment deadline: ";
cin >> assessmentC.deadline;
int totalWeight = totalWeight + assessmentC.grade;
}
The error message is telling you (and us all now) that you have declared a function named
void makeassessH()
but you never defined it. You do have a function named
void makeassesH()
but that's not the same spelling.

Having problem validating the radius in this code

I have the following code in which I'm trying to validate the radius. If the radius is zero or negative, I'm supposed to give the user endless opportunities to write the radius again until it's valid. When I tested the code, I wrote a negative value and it worked just fine, it gave me endless opportunities until I gave a valid value, but if I wrote a correct value since the beginning, it made me write the value again as if it was incorrect.
#include <iostream>
#include <stdlib.h>
#include "listaEnlazada.h"
using namespace std;
using namespace listaenlazada;
void menu()
{
cout << "\n\t\tLISTA ENLAZADA SIMPLE\n\n";
cout << "1. Insert at begginig " << endl;
cout << "2. Insert at the end " << endl;
cout << "3. Insert in a specific position " << endl;
cout << "4. Write list " << endl;
cout << "5. Search element " << endl;
cout << "6. Exit " << endl;
}
int main() {
CircPtr cabezaLista = NULL, position;
int op;
string name;
double radius;
double x;
double y;
int pos;
do {
menu();
cin >> op;
switch(op)
{
case 1:
cout << "Write the name of the circle: ";
cin >> name;
cout << "\n Write radius: ";
cin >> radius;
do{
cout << "Invalid input. ";
cin >> radius;
}while(radius <= 0);
cout << "\n Write center: ";
cout << "X: ";
cin >> x;
cout << "Y: ";
cin >> y;
insertarCabeza(cabezaLista, name, radius, x, y);
break;
case 2:
cout << "Write the name of the circle: ";
cin >> name;
cout << "\n Write radius: ";
cin >> radius;
do{
cout << "Invalid input. ";
cin >> radius;
}while(radius <= 0);
cout << "\n Write center: ";
cout << "X: ";
cin >> x;
cout << "Y: ";
cin >> y;
insertarFinal(cabezaLista, name, radius, x, y);
break;
case 3:
cout << "Write the name of the circle: ";
cin >> name;
cout << "\n Write radius: ";
cin >> radius;
do{
cout << "Invalid input. ";
cin >> radius;
}while (radius <= 0);
cout << "\n Write center: ";
cout << "X: ";
cin >> x;
cout << "Y: ";
cin >> y;
cout << "Position : ";
cin >> pos;
posicion = buscarPosicion(cabezaLista, pos-1);
if (posicion != NULL)
insertarPosicion(posicion, name, radius, x, y);
break;
case 4:
cout << "\n\n Showing list : ";
escribirLista(cabezaLista);
break;
case 5:
cout << "\n Center of circle to search: ";
cout << "X: ";
cin >> x;
cout << "Y: ";
cin >> y;
buscarElemento(cabezaLista, x, y);
break;
case 6:
cout << "\n End of the program. ";
break;
}
cout << endl;
}while(op != 6);
return 0;
}
Just use while loop instead of do while loop. In your code because of cin you are taking one input value and for any value which user enters, next do while loop execute ones without checking condition so your prompting with invalid input on the correct radius input.
Instead of this
cout << "\n Write radius: ";
cin >> radius;
do{
cout << "Invalid input. ";
cin >> radius;
}while(radius <= 0);
Do like this
cout << "\n Write radius: ";
cin >> radius;
while(radius <= 0){
cout << "Invalid input. ";
cin >> radius;
}
Learn the basics of the loops.

I feel like the input code I put into my struct can be condensed, any suggestions on how to keep the data individual while keeping the code short?

I've been trying to figure out how to input information into my struct, but I would like to condense the code.
#include <iostream>
using namespace std;
struct Employee //The whole program is going to revolve around this struct
{
char first[10], last[10];
float Hours_Worked, Hourly_Rate, Fed_Tax_Rate, St_Tax_Rate;
}Kobe, Lebron, Larry, Michael; //Struct declarations
The Code right here is the one I'm talking about. My preferred design was to use a for loop that loops 4 times, however I need individual information.
int main()
{
Employee Kobe;
cout << "First name: ";
cin >> Kobe.first;
cout << "Last name: ";
cin >> Kobe.last;
cout << "Hours worked: ";
cin >> Kobe.Hours_Worked;
cout << "Federal Tax Rate: ";
cin >> Kobe.Fed_Tax_Rate;
cout << "State Tax Rate: ";
cin >> Kobe.St_Tax_Rate;
Employee Lebron;
cout << "First name: ";
cin >> Lebron.first;
cout << "Last name: ";
cin >> Lebron.last;
cout << "Hours worked: ";
cin >> Lebron.Hours_Worked;
cout << "Federal Tax Rate: ";
cin >> Lebron.Fed_Tax_Rate;
cout << "State Tax Rate: ";
cin >> Lebron.St_Tax_Rate;
Employee Larry;
cout << "First name: ";
cin >> Larry.first;
cout << "Last name: ";
cin >> Larry.last;
cout << "Hours worked: ";
cin >> Larry.Hours_Worked;
cout << "Federal Tax Rate: ";
cin >> Larry.Fed_Tax_Rate;
cout << "State Tax Rate: ";
cin >> Larry.St_Tax_Rate;
Employee Michael;
cout << "First name: ";
cin >> Michael.first;
cout << "Last name: ";
cin >> Michael.last;
cout << "Hours worked: ";
cin >> Michael.Hours_Worked;
cout << "Federal Tax Rate: ";
cin >> Michael.Fed_Tax_Rate;
cout << "State Tax Rate: ";
cin >> Michael.St_Tax_Rate;
return 0;
}
Define a Employee with an input method to get the input
struct Employee
{
char first[10], last[10];
float Hours_Worked, Hourly_Rate, Fed_Tax_Rate, St_Tax_Rate;
bool getinput(std::istream & in,
std::ostream & out);
};
Then you implement this method
bool Employee::getinput(std::istream & in,
std::ostream & out);
{
out << "First name: ";
in >> first;
out << "Last name: ";
in >> last;
out << "Hours worked: ";
in >> Hours_Worked;
out << "Federal Tax Rate: ";
in >> Fed_Tax_Rate;
out << "State Tax Rate: ";
in >> St_Tax_Rate;
return in.good(); //always good to know if the input succeeded
}
and then you call the method
Employee Kobe;
Kobe.getinput(cin, cout);
Employee Lebron;
Lebron.getinput(cin, cout);
Employee Larry;
Larry.getinput(cin, cout);
Employee Michael;
Michael.getinput(cin, cout);
cin and cout are being passed in in an abstracted form so that you can call getinput on different input streams, a network socket for example.
Use an array of Employees and a for-loop to avoid writing duplicate code:
#include <iostream>
using namespace std;
struct Employee
{
char first[10];
char last[10];
float Hours_Worked;
float Hourly_Rate;
float Fed_Tax_Rate;
float St_Tax_Rate;
};
int main()
{
Employee employees[4];
for (auto &e : employees) {
cout << "First name: ";
cin >> e.first;
cout << "Last name: ";
cin >> e.last;
cout << "Hours worked: ";
cin >> e.Hours_Worked;
cout << "Hourly rate: ";
cin >> e.Hourly_Rate;
cout << "Federal Tax Rate: ";
cin >> e.Fed_Tax_Rate;
cout << "State Tax Rate: ";
cin >> e.St_Tax_Rate;
}
for (auto const &e : employees)
cout << e.first << ' ' << e.last << '\n' << e.Hours_Worked << " / "
<< e.Hourly_Rate << " / " << e.Fed_Tax_Rate << " / " << e.St_Tax_Rate << "\n\n";
}
If you're not (yet) familiar with range-based for-loops you can of course use traditional loops like
for(size_t i{}; i < sizeof(employees)/sizeof(*employees); ++i)
// and access eployees[i] in the loops body.

Having to input value twice to work C++

#include <iostream>
#include <limits>
#include <math.h>
using namespace std;
int main()
{
float startTemperature;
float endTemperature;
float loopTemperature;
float stepSize;
float i;
float numberOne;
cout << "Please enter a start temperature: " << endl;;
cin >> startTemperature;
while(!(cin >> startTemperature)){
cin.clear();
cout << "Invalid input. Try again: ";
}
cout << "Please enter an end temperature: ";
cin >> endTemperature;
while(!(cin >> endTemperature)) {
cin.clear();
cin.ignore(256, '\n');
cout << "Invalid temperature. Please try again: ";
}
cout << "Please enter a step size: ";
cin >> stepSize;
while(!(cin >> stepSize)) {
cin.clear();
cin.ignore(256, '\n');
}
for(i = startTemperature; i < endTemperature; i += stepSize) {
if(i == startTemperature) {
cout << "Celsius" << endl;
cout << "-------" << endl;
cout << startTemperature << endl;
loopTemperature = startTemperature + stepSize;
}
loopTemperature += stepSize;
if(loopTemperature > 20) {
break;
}
cout << loopTemperature << endl;
}
}
Hi, The problem with this code is that I have to input the value of the temperature twice. I have looked at other answers and I think it is something to do with the cin buffer but I don't know exactly what is wrong.
In the line
cin >> startTemperature; // <---problem here
while(!(cin >> startTemperature)){
cin.clear();
cout << "Invalid input. Try again: ";
}
You are taking input once, then again in the loop. That's is why you had to give input twice.
Just remove first input line, same for endTemparature and stepSize.
You're asking for input before the while loop, then again in the loop condition statement. Change the condition in your while statement to
while(!cin){
//error handling you already have
cin>>startTemperature; //endTemperature respectively
}
It's not only for the temperature but rather for every input. Change your code to the one below:
cout << "Please enter a start temperature: " << endl;;
while (!(cin >> startTemperature)){
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
cout << "Invalid input. Try again: ";
}
cout << "Please enter an end temperature: ";
while (!(cin >> endTemperature)) {
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
cout << "Invalid temperature. Please try again: ";
}
cout << "Please enter a step size: ";
while (!(cin >> stepSize)) {
cin.clear();
cin.ignore(std::numeric_limits<int>::max(), '\n');
cout << "Invalid step size. Please try again: ";
}
Reason:
You had redundant cin calls. Also use std::cin.ignore(std::numeric_limits<int>::max(), '\n'); instead of arbitrary number 256.

Why cant i reject Decimals? (C++)

With this code:
#include <iostream>
#include <iomanip>
using namespace std;
//Functions
int power(int base,int exp);
double energy(int z, int n);
//Main
int main() {
const double E0(13.6),hce(1.24E-6),e(1.6E-19);
int n1,n2,z;
double E;
cout << "**************************************" << endl;
cout << "Welcome to the energy level calculator\n" << endl;
cout << "Please enter the atomic number, z: " << endl;
cin >> z; //Ask for z
cout << "Please enter n for the initial energy level: " << endl;
cin >> n1; //Ask for n1
cout << "Please enter n for the final energy level: " << endl;
cin >> n2; //Ask for n2
while(cin.fail()||z<1||n1<1||n2<1){
cout << "\n\n\n\n\nPlease enter non-zero integers only, try again\n\n\n\n\n\n" << endl;
cout << "**************************************" << endl;
cin.clear();
cin.ignore();
cout << "Please enter the atomic number, z: " << endl;
cin >> z; //Ask for z
cout << "Please enter n for the initial energy level: " << endl;
cin >> n1; //Ask for n1
cout << "Please enter n for the final energy level: " << endl;
cin >> n2; //Ask for n2
}
etc...
The program is only allowed to accept Integers
If i enter a decimal, such as 1.2 the program rejects the 1. but uses the 2 as z when it should be asking for input from the keyboard?
Can anyone help?
Since you asked for an explanation, when you enter 1.2
cin >> z; //Successfully reads '1' into 'z'
cin >> n1; //Fails to read '.' into 'n1'. '.' remains the first character in the stream.
cin >> n2; //Fails to read '.' into 'n2'. '.' remains the first character in the stream.
You then loop back to the beginning of your loop.
cin.clear(); //clears the fail flag from the two previous failed inputs
cin.ignore(); // ignores the '.'
cin >> z; //Reads '2' into 'z'. The stream is now empty.
The program then blocks on cin >> n1 waiting for more characters to be placed in the stream.
After each input, you should see if the input failed.
cin>>n1;
if(cin.fail())
cin.ignore();