Getting stuck in infinite loop - c++

When I'm running this program for class, I'm getting stuck in an infinite loop whenever I enter a '|' character to end the while loop. I feel like I'm missing something obvious.
This problem is found on page 126 of Bjarne Stroustrup's C++ Programming book, but as a quick rundown, I'm just supposed to find the largest and smallest numbers that are typed in the by the user and return info on it. Typing in '|' is supposed to exit the loop so that I can get down to the part where it gives information about all the numbers inputted, but whenever I type that character (or any character that's not a number), it creates an infinite loop.
Here is my code.
int main()
{
vector<double> nums;
while (true)
{
double current_num;
cout << "enter a double \n";
cin >> current_num;
if (current_num == '|')
break;
nums.push_back(current_num);
sort(nums.begin(), nums.end());
cout << nums[nums.size()-1] << " is the largest so far.\n";
cout << nums[0] << " is the smallest so far.\n";
}
cout << nums[nums.size()-1] << " is the largest number.\n";
cout << nums[0] << " is the smallest number.\n";
cout << "Number of values entered: " << nums.size() << '\n';
double sum = 0;
for (int k = 0; k<nums.size(); ++k)
sum += nums[0];
cout << "Sum of all values: " << sum << '\n';
for (int j=0; j<nums.size(); ++j)
cout << nums[j] << ' ';
return 0;
}
I was using VS13 in class and I wasn't having this problem, but now I'm coding in notepad++ and using PuTTY to compile at home (although I doubt this has anything to do with it).

You are comparing a character with a double here :
if (current_num == '|')
And this comparison will never do what you want it to do.
Read a character first, compare it with '|', then do a double conversion if necessary.
Note:
For your record the ASCII value of '|' is 124, so if you enter 124 your loop will end...

Because you are trying to insert a non number into a double.
I thing that in your case you should read the input into a string/char and parse it.

you are comparing number with a character.
if (current_num == '|')
current_num contains the number in type double that you are trying to compare with a char which is '|'

Problem is here:
if(current_num == '|'){
}
Instead read in a std::string and parse it to a double.
So the modified snippet will look something like this:
while (true)
{
string strNum;
double current_num;
cout << "enter a double \n";
cin >> strNum;
if (strNum == "|")
break;
istringstream strm(strNum);
strm >> current_num;
nums.push_back(current_num);
sort(nums.begin(), nums.end());
cout << nums[nums.size()-1] << " is the largest so far.\n";
cout << nums[0] << " is the smallest so far.\n";
}

Related

Trying to validate input in C++

The idea behind this code in c++ is to calculate the sum of all the entered numbers. When the user enters 0, the program should stop. This part of the code is working as I intended, but I'd like to include a variant which recognizes that a character different than a float number has been entered, ignore it in the calculation and allow the user to continue entering float numbers. At the moment, entering anything else but a float number stops the program.
I know there's a "if (!(cin >> numb))" condition, I've tried parsing it in different places in the code, but I can't figure out how to force the program to ignore these invalid inputs. I would be very grateful for any help.
#include <iostream>
#include <stdlib.h>
using namespace std;
float numb; float sum=0;
int main()
{
cout << "This app calculates the sum of all entered numbers." << endl;
cout << "To stop the program, enter 0." << endl << endl;
cout << "Enter the first number: ";
cin >> numb;
while(true)
{
sum += numb;
if (numb!=0)
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Enter another number: ";
cin >> numb;
}
else
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Entered 0." << endl;
cout << "Press Enter to terminate the app." << endl;
exit(0);
}
}
return 0;
}
You have three options:
trial and error: try to read a float, and in case of error clear the error flag, ignore the bad input and read again. The problem is that you don't know really how many of the input is to be ignored.
read strings: read space delimited strings, try to convert the string using stringstream, and just ignore the full string in case of error. The problem is that if the input starts with a valid float but then contains invalid characters (e.g. 12X4), the invalid part will be ignored (e.g. X4)
control parsing: read space delimited strings, try to convert the string using std::stof(), and check that all characters of the string where successfully read
Here the second approach, with a slightly restructured loop, so that a 0 entry will lead to exiting the loop and not the full program:
string input;
while(cin >> input)
{
stringstream sst(input);
if (sst>>numb) {
sum += numb;
cout << "Sum equals: " << sum << endl << endl;
if (numb==0)
{
cout << "Entered 0." << endl;
break; // exits the while loop
}
cout << "Enter another number: ";
}
else
{
cout << "Ignored entry "<<input<<endl;
}
}
cout << "Press Enter to terminate the app." << endl;
Online demo
If you prefer a more accurate parsing, consider something like:
size_t pos=0;
float xx = stof(input, &pos );
if (pos!=input.size()) {
cout << "error: invalid trailing characters" <<endl;
}
You have to clear the failbit after a failed read. After that, you can read in the invalid stuff into a string (that you just ignore). This function will read in values and add them up until it encounters a 0 or the end of the input stream.
int calc_sum_from_input(std::istream& stream) {
int sum = 0;
// If it couldn't read a value, we just read the thing into here
std::string _ignored;
while(stream) // Checks if the stream has more stuff to read
{
int value;
if(stream >> value)
{
if(value == 0) // Exit if it read the value 0
break;
else
sum += value; // Otherwise update the sum
}
else {
// Clear the failbit
stream.clear();
// Read ignored thing
stream >> _ignored;
}
}
return sum;
}
The logic is basically:
set the initial sum to 0
check if there's stuff to read
if there is, try reading in a value
if successful, check if the value is 0
if it's 0, exit and return the sum
otherwise, add the value to the sum
otherwise, clear the failbit (so that you can read stuff in again) and read the bad value into a string (which gets ignored)
otherwise, return the value

Keeping track of which is the smallest and which is the largest value so far in a loop

could you please help me with solving simple problem? I am very fresh with C++ and learning from book "Programming: Principles and Practice Using C++ by Bjarne Stroustrup". I have never learnt C++ before so I am not familiar with many useful features. The drill says:
"6. Now change the body of the loop so that it reads just one double
each time around. Define two variables to keep track of which is the
smallest and which is the largest value you have seen so far. Each
time through the loop write out the value entered. If it’s the
smallest so far, write the smallest so far after the number. If it is
the largest so far, write the largest so far after the number"
I do not know how to do this correctly without using vector. Here is my code:
#include "C:/std_lib_facilities.h"
int main()
{
double a, b,differ=0;
char c=' ';
cout << "Enter two values: \n";
while (c != '|' && cin >> a >> b )
{
if (a > b)
{
cout << "The smaller value is: "<< b << " and the larger value is: " << a << "\n \n";
differ = a - b;
if (differ < 1.0 / 100)
cout << "Numbers are almost equal\n\n";
}
else if (a < b)
{
cout << "The smaller value is: " << a << " and the larger value is: " << b << "\n \n";
differ = b - a;
if (differ < 1.0 / 100)
cout << "Numbers are almost equal\n\n";
}
else
{
cout << "These values are equal!\n";
}
cout << "Enter a character | to break loop: \n";
cin >> c;
}
cout << "You have exited the loop.\n";
keep_window_open();
}
And here are previous steps, these I have solved with code above:
Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the
program when a terminating '|' is entered.
Change the program to write out the smaller value is: followed by the smaller of the numbers and the larger value is: followed by the
larger value.
Augment the program so that it writes the line the numbers are equal (only) if they are equal.
Change the program so that it uses doubles instead of ints.
Change the program so that it writes out the numbers are almost equal after writing out which is the larger and the smaller if the two
numbers differ by less than 1.0/100.
Could you give me some hint how to do step 6.? I had some ideas but none of them worked..
Here is new code:
#include "C:/std_lib_facilities.h"
int main()
{
double smallestSoFar = std::numeric_limits<double>::max();
double largestSoFar = std::numeric_limits<double>::min();
double a,differ=0;
char c=' ';
cout << "Enter value: \n";
while (c != '|' && cin >> a)
{
if (a > largestSoFar)
{
largestSoFar = a;
cout <<"Largest so far is: "<< largestSoFar << endl;
}
else if (a < smallestSoFar)
{
smallestSoFar = a;
cout <<"Smallest so far is: "<< smallestSoFar << endl;
}
else if(smallestSoFar >= a && a<=largestSoFar)
cout << a << endl;
cout << "Enter a character | to break loop: \n";
cin >> c;
}
cout << "You have exited the loop.\n";
keep_window_open();
}
I do not know how to do this correctly without using vector.
You do not need vector for this. The description correctly says that two variables would be sufficient:
// Declare these variables before the loop
double smallestSoFar = std::numeric_limits<double>::max();
double largestSoFar = std::numeric_limits<double>::min();
Modify your loop to read into a, not into both a and b. Check the newly entered value against smallestSoFar and largestSoFar, do the printing, and re-assign smallest and largest as necessary. Note that the first time around you should see both printouts - for largest so far and for smallest so far.
Based on the knowledge that you are suppose to know at the current stage for the this assignment. The code should go something like this:
#include < iostream>
#include < cstdlib>
int main() {
double num_1 = 0;
double num_2 = 0;
double largest = 0;
double smallest = 0;
bool condition1 = true;
while (true) {
std::cin >> num_1;
if (num_1 > largest){
largest = num_1;
}
else if (num_1 < smallest) {
smallest = num_1;
}
std::cout << "The largest so far: " << largest << std::endl;
std::cin >> num_2;
if (condition1) {
smallest = largest;
condition1 = false;
}
if (num_2 < smallest) {
smallest = num_2;
}
else if (num_2 > largest) {
largest = num_2;
}
std::cout << "The smallest so far: " << smallest << std::endl;
}
system("pause");
return 0;
}
double large = 0;
double small = 0;
double input;
int counter = 0;
while (counter < 5) {
cin >> input;
cout <<"Large value: "<< large << '\t' <<"Small value: "<< small\
<< '\t' <<"Input value: "<< input << '\n';
if (input < small) {
cout << "The smallest value is " << input<<\
"\nthe largest value is "<< large<<'\n';
small = input;
}
else if (input > small&& input < large) {
cout << "The smallest value is " << small << \
"\nthe largest value is " << large<<'\n';
}
else if (input > small&& input > large) {
cout << "The smallest value is " << small << \
"\nthe largest value is " << input << '\n';
large = input;
}
counter += 1;

Using C++ to receive int inputs and displaying the larger and smaller number

The instructions are to
Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating 'I' is entered.
Change the program to write out the smaller value is: followed by the smaller of the nwnbers and the larger value is: followed by the larger value.
I got the program to run but it terminates with a Range error: Can anybody correct my mistake in this code?
/*a drill in the Programming Principles
and Practice Using C++ by Bjarne Stroustrup*/
#include "std_lib_facilities.h" /*standard library from the author's website*/
int main()
{
vector<int>values;
int a, b; //ints declared
while(cin>>a>>b){ //ints read
values.push_back(a); //ints put into vector
values.push_back(b); //********************
}
for(int i = 0; i < values.size(); ++i){ //loop
if(values[i]>values[i+1]){
cout << "The larger value is: " << values[i] << endl; /*print larger value on screen*/
}
else
cout << "The smaller value is: " << values[i] << endl; /*prints smaller value on screen*/
}
return 0;
}
values[i+1] goes out of bounds for the last value, so you need to change your for loop condition
for(int i = 0; i < values.size() - 1; ++i){
// ^^^
1.Write a program that consists of a while-loop that (each time around
the loop) reads in two ints and then prints them. Exit the program
when a terminating 'I' is entered.
int a, b = 0;
// anything that isn't a int terminate the input e.g. 2 3 |
while (cin >> a >> b)
cout << a << " " << b << "\n";
2.Change the program to write out the smaller value is: followed by the smaller of the nwnbers and the larger value is: followed by the larger value.
int a, b;
const string smaller = "smaller value is: ";
const string larger = "larger value is: ";
while (cin >> a >> b) {
if (a < b)
cout << smaller << a << larger << b << endl;
else
cout << smaller << b << larger << a << endl;
}
if (cin.fail()) {
cin.clear();
char ch;
if (!(cin >> ch && ch == '|'))
throw runtime_error(string {"Bad termination"});
}

Can't compare string with while and if statements

I'm trying to create a command menu where the user will be able to perform as many commands as he/she wants until pressing "q" which will end the loop. I think I have everything I need to do this except I realized mid-way that my professor asked to use string. When I included string into the program, I began to get error messages saying "could not convert string to bool" wherever there was a while or if statement. What can I do to fix this problem and get my program working. Thanks in advance.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char option;
char number=0;
string s;
string n;
string p;
string q;
char number2;
cout << " Please enter a number: "<< endl;
cin >> number;
do {
cout << " Please enter a command: " << endl;
cout << " s- square the number " << endl;
cout << " n- add the number and (number +1) " << endl;
cout << " p- add the number and (number -1) " << endl;
cout << " q- quit" << endl;
cin >> option;
if (option=s) {
s= number*number;
cout << "Square of this number is : " << s;
}
else if ( option=n){
number2= number+1;
n= number+number2;
cout << "Sum of" << number << "+" << number2 << "is: " << n;
}
else if (option=p) {
number2= number-1;
p= number+number2;
cout << "Sum of" << number << "+" << number2 << "is" << p;
}
else if (option=q)
cout << "Terminating Program";
} while(option);
return 0;
}
you're assigning in the if and else if rather than comparing.
if (option=s) {
should be
if (option=='s') {
note the double =
Also, you need to put single quotes (') around the character choice.
It's a common mistake that even experienced developers make.
These declarations
char number=0;
string s;
string n;
string p;
string q;
char number2;
should all be int
int number=0;
int s;
int n;
int p;
int q;
int number2;
Let me answer as if I were who will evaluate your homework. You have several issues here:
You are asked to use string. Avoid the use of char and string together.
char option; // professor asked to use string: (-1) point
string option; // ok
When you use a single =, like in option="a", you are assigning the value "a" to the variable option. But in the if-else statements you want to compare, so you should use the == comparison operator. Also, you can't compare a char with a string.
if(option = "a") // error: expression must have bool type: (-2) points
if(option == 'a') // error: no operator "==" matches std::string == char; (-2) points
if(option == "a") // ok
You use while(option), but option is declared as a char, not as a bool. Replace this line to while(option!="q") to finish when you enter q.
while(option); // error: expression must have bool type; (-2) points
while(option != "q"); // GOOD!
Also, your program will finish when you scape from the while-statement; so, try to put the "Terminating Program" message after this.
You do not need to declare such many variables (s, n, p, q, number2). Try to use temporary variables inside each scope, for example:
if (option=="s")
{
cout << "Square of this number is : " << number*number << endl;
}
else if ( option=="n")
{
int number2= number+1;
cout << "Sum of " << number << "+" << number2 << " is : " << number+number2 << endl;
}
In the form you write this code, every time you type a new option you will obtain an output like:
Sum of 10+11 is : 21 Please enter a command:
This is ugly to me (-1 point). Try to put a newline (<< endl;) after every cout lines.
Finally, what if I type any other letter not listed in the menu? I would expect a message like Enter a valid option (-1 point).

First while loop's first iteration always fails to take input. 2+ loops work fine

The bug starts at cin.getline ( string, 25, '\n' ); or the line below it (strtod). If I use cin, it works, except I cannot quit out. If I type anything that's not a double, an infinite loop runs. Need help. Basically, the first iteration runs, does not ask for input, so the user gets the math questions wrong. The second iteration works fine. And the next is fine, too. If I back out, using q, I get dumped back to the mode-chooser. After choosing a mode, the bug reappears for the first iteration. Next iterations it's gone.
int main()
{
char choice, name[25], string[25], op;
int operator_number, average, difference, first_operand, second_operand, input, answer, total_questions = 0, total_correct = 0;
double dfirst_operand, dsecond_operand, dinput, danswer, percentage;
bool rounding = false;
srand ( time(NULL) );
cout << "What's your name?\n";
cin.getline ( name, 25, '\n' );
cout << '\n' << "Hi, " << name << ".";
do {
do {
cout << "\nWhich math operations do you want to practice?\n 1. Addition\n 2. Subtraction\n 3. Multiplication\n 4. Division\n 5. Mixed\n 6. Difference of squares multiplication.\nChoose a number (q to quit).\n";
cin >> choice;
} while( choice < '1' || choice > '6' && choice!= 'q');
cout << "\n";
switch(choice) {
case '1':
while( string[0]!= 'q') {
dfirst_operand = rand() % 15 + 1;
dsecond_operand = rand() % 15 + 1;
danswer = dfirst_operand + dsecond_operand;
cout << dfirst_operand << " + " << dsecond_operand << " equals?\nEnter q to quit.\n";
cin.getline ( string, 25, '\n' );
dinput = strtod( string,NULL);
//cin >> dinput;
if(string[0]!='q') {
++total_questions;
if(dinput==danswer) {
++total_correct;
cout << "Correct. " << total_correct << " correct out of " << total_questions << ".";
} else {
cout << "Wrong. " << dfirst_operand << " + " << dsecond_operand << " equals " << danswer << ".\n" << total_correct << " correct out of " << total_questions << ".";
};
percentage = floor(10000 * (float) total_correct / total_questions)/100;
cout << ' ' << percentage << "%.\n\n";
}
}
break;
}
} while(choice!='q');
return 0;
}
The problem is this line:
cin >> choice;
This line parses the input buffer for character input that can be converted to an integer. So if you enter:
2<newline>
The string "2" is converted, and <newline> remains in the input buffer; so the subsequent cin.getline() is satisfied immediately.
This is also why JonH's suggestion does not work, you need to purge the input buffer after the cin << choice input. An alternative is to use cin.getline() for all input (or better; use ::getline() which operates on std::string rather than C-strings), and then parse that input using a std::istringstream object when you need formatted input scanning.
However if you must use cin.ignore() to solve this problem, you should do it thus:
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
where std::numeric_limits is defined in the header. Your solution trusts the user not to enter more than 25 characters. That is not a very safe assumption.
Try to throw a cin.ignore() right after or before the cin.getline().