Incorrect sum when adding up numbers - c++

Ok, here's the code to add indefinite numbers and present the sum in c++. But error is that addition taking place is of first number and the last digits of all the other numbers. For example if i want to add 30 + 40 + 55 + 70, my program counts 30 + 0 + 0 + 5 + 0 = 35. What am I doing wrong?
#include <iostream>
using namespace std;
int main()
{
int num = 0;
int sum = 0;
cout << "Please enter numbers you want to add and end with N or n: ";
for (;;)
{
cin >> num;
sum += num;
cout << endl;
char indicator ('q');
cin >> indicator;
if (( indicator == 'n') || (indicator == 'N'))
break;
}
cout << "The sum is: " << sum << " ";
return 0;
}

I'm not sure I fully understand what you are trying to do, but if you want to add a list of integers terminated by an N (or n) character, then you should read each entity as a string, see if it's the terminating character, and if it's not, then convert it to an integer:
int sum = 0;
while (true) {
std::string s;
std::cin >> s;
if (tolower(s[0]) == 'n')
break;
sum += std::stoi(s);
}
Of course, the above code is only a skeleton -- in production code, you should always check if I/O operations succeeded and sanitize your input. A more complete example would be:
std::string s;
while (std::cin >> s) {
int ch = s[0];
if (ch > 0 && tolower(ch) == 'n')
break;
try {
sum += std::stoi(s);
} catch (const std::invalid_argument &e) {
// handle conversion error
break;
} catch (const std::out_of_range &e) {
// handle out-of-range error
break;
}
}

When you read the indicator, you extract the next non-blank character from the input stream; if the user has entered a number, this is the first digit. There are several ways of working around this.
The simplest is simply to loop on:
while ( std::cin >> num ) {
sum += num;
}
The input will fail if the next input doesn't have the form of a number (without extracting it). (This also has the advantage that you don't use the input if it fails for some reason.) This is more or less the standard idiom.
If you really do want to check for the 'n', you can use std::cin.peek() to look ahead one character, without extracting it. This doesn't skip white space, however, so you might want to do std::cin >> std::ws first. In this case, you'd probably want to wrap it in a function:
bool
terminationRequested( std::istream& source )
{
source >> std::ws;
return source.peek() == 'n' || source.peek() == 'N';
}
and then
while ( ! terminationRequested( std::cin ) ) {
int num;
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
You still have to check for a possible error after std::cin >> num. Otherwise, if the user enters "a", you'll end up in an endless loop, adding an undefined value to sum.
Alternatively, another frequent idiom is too use putback to return the indicator to the stream:
while ( std::cin >> indicator && indicator != 'n' && indicator != 'N' ) {
std::cin.putback( indicator );
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
Again, you'll have to handle the errors somehow. Using num if std::cin >> num fails is undefined behavior.

It's because you read the indicator character which will remove and ignore the next input digit by the user from the input stream.

Related

how to make cin only take integer inputs

i new to programming and we are required to create a program that dont exit when the user inputs the wrong input, but i only learned the basics so far.. i already solved when the number is above and below 100 but when the user accidentally inserted a non integer it will go into a error loop. btw this is an average calculator.
#include <iostream>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
cout << "how many numbers will you input?: ";
cin >> n;
while ( n > 100 || n <= 0 )
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for ( int i = 0; i < n; ++i )
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}
If std::istream::operator >> fails, it will set failbit. Therefore, you should check failbit (for example by calling std::cin.fail()) to see whether the conversion was successful, before using the result of the conversion.
If the conversion fails due to bad input, then the next call to std::istream::operator >> will automatically fail due to failbit being set. That is why you are getting stuck in an infinite loop. If you want to attempt input again after a conversion failure, you will first have to clear failbit, by using the function std::cin.clear().
Also, you will have to discard the bad input that caused the conversion to fail, because otherwise, the next time you call std::istream::operator >>, the conversion will fail again for the same reason. In order to clear the bad input, you can use std::cin.ignore(), like this:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
In order to use std::numeric_limits, you will have to #include <limits>.
After performing these fixes on your code, it should look like this:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
bool input_ok;
//repeat until input is valid
do
{
cout << "How many numbers will you input? ";
cin >> n;
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else if ( n > 100 || n <= 0 )
{
cout << "Error: Number should in range of (1 to 100) only!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
for ( int i = 0; i < n; ++i )
{
do
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}
This program has the following behavior:
How many numbers will you input? 200
Error: Number should in range of (1 to 100) only!
How many numbers will you input? -31
Error: Number should in range of (1 to 100) only!
How many numbers will you input? test
Error: Conversion to integer failed!
How many numbers will you input? 4abc
1. Enter number: 1
2. Enter number: 2
3. Enter number: 3
4. Enter number: 4
Average = 2.5
As you can see, the program now works in that it can now handle bad input such as test. It rejects that input and reprompts the user for new input.
However, one problem with this program is that it accepts 4abc as valid input for the number 4. It would probably be appropriate to reject such input instead. One way to fix this would be to inspect the remainder of the line, instead of simply discarding it.
Another issue is that this solution contains a lot of code duplication. Apart from the range check, both do...while loops are nearly identical. Therefore, it would be better to put this loop into a function, which can be called from several places in your code.
However, I generally don't recommend that you use std::istream::operator >>, because its behavior is not always intuitive. For example, as already pointed out above:
It does not always read a whole line of input, so that you must explicitly discard the remainder of the line.
It accepts 4abc as valid input for the number 4.
In my experience, if you want proper input validation of integer input, it is usually better to write your own function that reads a whole line of input using std::getline and converts it with std::stoi. If the input is invalid, then the function should automatically reprompt the user.
In my example below, I am calling this function get_int_from_user.
If you want to additionally ensure that the input is in a certain range, then you can call the function get_int_from_user in an infinite loop, and break out of that loop once you determine that the input is valid.
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
int get_int_from_user( const std::string& prompt );
int main()
{
int nums[100];
int n;
double sum;
//repeat loop forever, until input is good
for (;;) //equivalent to while(true)
{
n = get_int_from_user( "How many numbers will you input? " );
if ( 1 <= n && n <= 100 )
//input is good
break;
std::cout << "Error! Number should in range of (1 to 100) only.\n";
}
//read one number per loop iteration
for( int i = 0; i < n; i++ )
{
std::ostringstream prompt;
prompt << "Enter number #" << i + 1 << ": ";
nums[i] = get_int_from_user( prompt.str() );
sum += nums[i];
}
std::cout << "Average: " << sum / n << '\n';
}
int get_int_from_user( const std::string& prompt )
{
std::string line;
std::size_t pos;
int i;
//repeat forever, until an explicit return statement or an
//exception is thrown
for (;;) //equivalent to while(true)
{
//prompt user for input
std::cout << prompt;
//attempt to read one line of input from user
if ( !std::getline( std::cin, line ) )
{
throw std::runtime_error( "unexpected input error!\n" );
}
//attempt to convert string to integer
try
{
i = std::stoi( line, &pos );
}
catch ( std::invalid_argument& )
{
std::cout << "Unable to convert input to number, try again!\n";
continue;
}
catch ( std::out_of_range& )
{
std::cout << "Out of range error, try again!\n";
continue;
}
//The remainder of the line is only allowed to contain
//whitespace characters. The presence of any other
//characters should cause the entire input to get rejected.
//That way, input such as "6sdfj23jlj" will get rejected,
//but input with trailing whitespace will still be accepted
//(just like input with leading whitespace is accepted by
//the function std::stoi).
for ( ; pos < line.length(); pos++ )
{
if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )
{
std::cout << "Invalid character found, try again!\n";
//we cannot use "continue" here, because that would
//continue to the next iteration of the innermost
//loop, but we want to continue to the next iteration
//of the outer loop
goto continue_outer_loop;
}
}
//input is valid
return i;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
How many numbers will you input? 200
Error! Number should in range of (1 to 100) only.
How many numbers will you input? -31
Error! Number should in range of (1 to 100) only.
How many numbers will you input? test
Unable to convert input to number, try again!
How many numbers will you input? 4abc
Invalid character found, try again!
How many numbers will you input? 4
Enter number #1: 1
Enter number #2: 2
Enter number #3: 3
Enter number #4: 4
Average: 2.5
As you can see, it now correctly rejects the input 4abc.
I believe that using the function get_int_from_user makes the code in main much cleaner.
Note that the code above uses one goto statement. Under most circumstances, you should avoid using goto, but for breaking out of nested loops, it is considered appropriate.
#include <iostream>
#include <limits>
using namespace std;
int avg(int sum, int n)
{
int average;
average = sum/n;
cout<<"Avg = "<<average;
}
int main()
{
int n;
cout << "how many numbers will you input?: ";
cin >> n;
int w = n;
int num[w];
int sum;
while(n>100||n<=0)
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for(int i = 0; i < n; ++i)
{
cout << i + 1 << "Enter number: ";
cin >> num[i];
if(!cin)
{
cout << "Wrong Choice. " << endl;
cin.clear();
cin.ignore( numeric_limits<std::streamsize>::max(), '\n' );
n++;
continue;
}
else
{
sum += num[i];
}
}
cout<<"Sum = "<<sum<<endl;
avg(sum,w);
}

While condition: How to allow comparison between non-integer/double user input and integer limits

Objective: Run a while loop that will repeat until the user inputs an integer between 1-3 (inclusive). So if an integer that is smaller than 1 or bigger than 3 is inputted or any character or string is inputted, the loop repeats.
My noob knowledge: I know how to compare user input when it is an integer, but when it is a char or string datatype input all I get is an infinite loop. Plus I declared the inputtable variable as an integer, so not sure how to go on about this.
I've done some Google searches but can't seem to find a question similar enough to mine.
Advice is highly appreciated :)
Code below:
int Decision1 = 4;
while ( Decision1 < 1 || Decision > 3)
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << "\n\n";
}
int Decision1;
while(std::cin >> Decision1) {
if(Decision1 >= 1 && Decision1 <= 3) break;
// todo
}
You can use ASCII codes for checking number or character.
#include <iostream>
int main() {
char Decision1 = '0';
while ( (Decision1 < 49 && Decision1 >=47) || (Decision1 >51 && Decision1 <=57 ))
{
std::cout << "Enter answer here: ";
std::cin >> Decision1;
std::cout << Decision1;
std::cout << "\n";
}
}
I hope helpful for you.
Keep in mind: when you read input from std::cin you're reading text that's typed at the console. The stream extractor tries to convert that text to the target type. That is, in
int i;
std::cin >> i;
the >> operator looks for digit characters and figures out what value those characters represent. If the characters can't be converted to an integer value the extraction fails. Streams have a conversion to bool that tells you whether the stream is in a good state, or whether an attempted operation failed. So:
int i;
if (std::cin >> i)
std::cout << "got a value!\n";
To write a loop that prompts for valid input you need to reverse the test:
int i;
while (!(std::cin >> i) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To also check that the value is in the required range, just do it:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
// now clear the input stream, so it's back in a good state
}
To clear the input stream, you have to reset its internal flags. You do that with std::cin.clear();. And, depending on what you think was typed in, you probably want to get rid of any additional characters that the user typed. You do that with std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n'). That tells the stream to discard character until it reaches a newline (press ENTER), or until it has read a huge number of characters.
Putting it all together:
int i;
while (!(std::cin >> i) || i < 1 || i > 3) {
std::cout << "bad input\n":
std::cin.clear();
std::cin::ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Yes, this clears the stream state and flushes the input when the input was a valid integer but out of range; that's harmless. It's a waste of time, but the speed of keyboard input is limited by how fast the user types, which is much slower than anything that the code in this loop does.

How to properly use cin.peek()

This function is supposed to read a fraction and place it in an array. If the user enters '0' the function is supposed to exit. I am trying to do this using the cin.peek() function but execution always goes into the if statement and doesn't allow the user to exit.
How should I properly code this (I am open to not using peek(), I thought it was the simplest way of doing it.)
Thanks!
void enterFrac(Fraction* fracs[], int& index)
{
int n, d;
char c, slash;
cout << "Enter fractions (end by entering a 0): ";
c = cin.peek();
if ( c != '0')
{
cin >> n >> slash >> d;
Fraction* f = new Fraction();
f->num = n;
f->den = d;
fracs[index] = f;
index++;
}
}
This test of peek() works however:
#include <iostream>
using namespace std;
int main () {
char c;
int n;
char str[256];
cout << "Enter a number or a word: ";
c=cin.peek();
if ( (c >= '0') && (c <= '9') )
{
cin >> n;
cout << "You have entered number " << n << endl;
}
else
{
cin >> str;
cout << " You have entered word " << str << endl;
}
return 0;
}
There are two issues with your use of std::istream::peek():
This function access the next character and does not skip leading whitespace. You probably want to skip leading whitespace before determining what the next character is, e.g., using the manipulator std::ws: (std::cin >> std::ws).peek().
The result from std::istream::peek() is not a char. Instead, it is an std::char_traits<char>::int_type (which is a fancy spelling of int). The result may, e.g., be std::char_traits<char>::eof() and if the value of '0' happens to be negative (I'm not aware of any platform where it is; however, e.g., the funny character from my name 'ü' is a negative value on platforms where char is signed) you wouldn't get the correct result, either. That is, you normally compare the result of std::istream::peek() against the result of std::char_traits<char>::to_int_type(), i.e., you'd use something like this: std::cin.peek() == std::char_traits<char>::to_int_type('0')
That said, your program doesn't check whether it could successfully read the nominator and the denominator, separated by a slash. You always want to verify that reading was successful, e.g., using something like
if ((std::cin >> nominator >> slash >> denominator) && slash == '/') {
...
}
Just for entertainment, you can create a manipulator for testing that a character is a slash, indeed:
std::istream& slash(std::istream& in) {
if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type('/')) {
in.setstate(std::ios_base::failbit);
}
return in;
}
This way, you'd encapsulate the test for slash. If you need to use this in multiple places this is quite handy.

Using C isdigit for error checking

While using the boolean check for the int num this loop doesn't work. The lines after it go unrecognized. Enter and integer like 60 and it just closes. Did I use isdigit wrong?
int main()
{
int num;
int loop = -1;
while (loop ==-1)
{
cin >> num;
int ctemp = (num-32) * 5 / 9;
int ftemp = num*9/5 + 32;
if (!isdigit(num)) {
exit(0); // if user enters decimals or letters program closes
}
cout << num << "°F = " << ctemp << "°C" << endl;
cout << num << "°C = " << ftemp << "°F" << endl;
if (num == 1) {
cout << "this is a seperate condition";
} else {
continue; //must not end loop
}
loop = -1;
}
return 0;
}
When you call isdigit(num), the num must have the ASCII value of a character (0..255 or EOF).
If it's defined as int num then cin >> num will put the integer value of the number in it, not the ASCII value of the letter.
For example:
int num;
char c;
cin >> num; // input is "0"
cin >> c; // input is "0"
then isdigit(num) is false (because at place 0 of ASCII is not a digit), but isdigit(c) is true (because at place 30 of ASCII there's a digit '0').
isdigit only checks if the specified character is a digit. One character, not two, and not an integer, as num appears to be defined as. You should remove that check entirely since cin already handles the validation for you.
http://www.cplusplus.com/reference/clibrary/cctype/isdigit/
If you're trying to protect yourself from invalid input (outside a range, non-numbers, etc), there are several gotchas to worry about:
// user types "foo" and then "bar" when prompted for input
int num;
std::cin >> num; // nothing is extracted from cin, because "foo" is not a number
std::string str;
std::cint >> str; // extracts "foo" -- not "bar", (the previous extraction failed)
More detail here:
Ignore user input outside of what's to be chosen from

Problem with input in c++

I have a very basic question i want to take integer input in certain range from user. if the user gives some string or char instead of integer. then my program goes to infinite loop.
my code is some what like that
cin >> intInput;
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
cin >> intInput;
}
I am only allowed to use c++ libraries not the c libraries.
As mentioned in the possible duplicate, you should check the state of cin on each loop.
Possible implementation:
if(cin >> intInput)
while(intInput > 4 || intInput < 1 ){
cout << "WrongInput "<< endl;
if(!(cin >> intInput)){ break; }
}
Very ugly code, just trying to illuminate the answer which is to check the state of cin.
The solution to this answer is to always read lines from the standard input.
std::string input; int value = 0;
do
{
// read the user's input. they typed a line, read a line.
if ( !std::getline(std::cin,input) )
{
// could not read input, handle error!
}
// attemp conversion of input to integer.
std::istringstream parser(input);
if ( !(parser >> value) )
{
// input wasn't an integer, it's OK, we'll keep looping!
}
}
// start over
while ((value > 4) || (value < 1));
#include <locale>
..
if(!isalpha(intInput)) {
..
}
Note, this won't work if, for example the user enters a "+" but maybe it will put you in the right direction..