Boolean condition not working properly in do-while loop - c++

The loop in the function require() takes 3 conditions, a > b or "a" or "b" aren't digits. Even when I don't satisfy the conditions and put 2 integers in, it just loops once again.
Also when I put in a character then it just endlessly loops "Enter minimum number Enter maximum number" ignoring the cins. Anyone know why? I'm a beginner so this is probably really obvious
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int random(int minN, int maxN) //generates random number within specified range
{
srand (time(NULL));
int x = (maxN - minN);
int y = minN + (rand() % (x+1));
return y;
}
int require() //makes sure a < b and both are digits
{
int a,b;
do {
cout << "Enter minimum number" << endl;
cin >> a;
cout << "Enter maximum number. Note: Has to be greater or equal to minimum." << endl;
cin >> b;
} while (a > b || !isdigit(a) || !isdigit(b));
return random(a,b);
}
int main()
{
cout << require() << endl;
}

You should not use isdigit as this relates to a particular character is a digiti. Instead the loop should look like this:
int require() //makes sure a < b and both are digits
{
validNumbers = true;
do
{
cout << "Enter minimum number" << endl;
cin.clear();
cin >> a;
} while (cin.fail());
do
{
cout << "Enter maximum number. Note: Has to be greater or equal to minimum."
<< endl;
cin.clear();
cin >> b;
} while (cin.fail() || a > b);
return random(a,b);
}
PS: You only need to call srand (time(NULL)); once at the start of the program.

You are reading the numbers as, well, numbers not as characters as the isdigit function expects. If you are using a C++11 compliant standard library, the values of a and b will actually be zero if the input is not valid integer numbers, which means that e.g. !isdigit(a) will be true. If you are using a non-C++11 library, then the value of a and b will be random, and will most likely cause !isdigit(a) to be true as well as the amount of valid digit ASCII values in a full 32-bit integer range is quite small.
If you read a reference about the input operator, like this one you will see that if extraction fails, then the streams failbit will be set. This can either be tested "inline" like this:
if (!(std::cin >> a))
{
std::cout << "Not a valid number, try again: ";
continue;
}
Or it can be tested using the streams fail function.

Related

How do I clear the values in a string during each loop iteration?

I want to append a different value of b to my original number, but refresh after one iteration of the loop (after each cout) the original num value and the decVal value back to an empty string and 0. How would I do that? For example, instead of returning 001 = 1, 011 = 3, I get 001 = 1, 001011 = 4.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void main()
{
int n, decVal;
int i = 7;
string num, b, originalnum;
cin >> n;
for (x = 0; x < n; ++i)
{
cin >> num;
cin.get(b);
cin.ignore();
originalnum += b;
decVal += atoi(&b) * pow(2, i);
i -= 1;
cout << "The decimal equivalent of " << originalnum << " = " << decVal << endl;
}
}
If I understand what you are asking, you want to be able to repeat entering the number of bits and outputting the string holding the representation of the bits and the decimal value. You want all variables to be reset between different iterations for decVal. To make that possible, along with fixing a few errors, you simply need to wrap what you are currently doing in another loop so that for each iteration of the outer loop, you process all the bits you like an come up with a final decVal to output.
Before looking at a solution, as mentioned in the comment above, void main() is only valid for a freestanding environment (e.g. no Operating System, like a microcontroller, etc..) Otherwise, the allowable declarations for main for are int main (void) and int main (int argc, char *argv[]) (which you will see written with the equivalent char **argv). See What should main() return in C and C++?
While convenient, you will also want to read Why is “using namespace std;” considered bad practice? and so you understand the difference between '\n' and std::endl, go ahead a look at C++: “std::endl” vs “\n”
One thing you must always do with EVERY input is to validate it succeeds by checking the stream-state after the attempted input and BEFORE you use the variable filled by the input. If a matching failure occurs, failbit will be set and you must clear the error bit before attempting your next input. You can handle the error any way you like, from either ending the program, or by clearing the error bit and removing the characters that caused the problem with .ignore() (examples of both are shown below). Essentially, at minimum, you need something like:
if (!(std::cin >> n)) { /* validate EVERY user input */
std::cerr << "invalid unsigned input -- exiting.\n";
return 1;
}
(note: instead of just calling .ignore(), you should use its full and proper invocation removing up to the maximum number of values for any particular circumstance. When reading from a file-steam, that is: std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');)
Now for your program setup, you can essentially just use a continual loop around code similar to what you have and just provide a mechanism to exit the outer loop when the user is done entering values. For example, using a simple while(1) loop and having the user enter anything other than a valid number for n, you could do:
while (1) { /* outer loop - loop continually */
size_t n; /* declare variables within loop */
uint32_t decVal = 0;
std::string originalnum {};
std::cout << "\nenter no. of bits ('q' to quit): ";
if (!(std::cin >> n)) { /* validate EVERY user input */
std::cerr << "invalid unsigned input -- exiting.\n";
return 1;
}
Note: all variables are declared inside the loop, so for each iteration, the variables are declared and initialized each time. Above the user is told to press 'q' to quit -- but can enter anything that is not a valid number to exit. That will simply exit the program returning control to the calling process.
Look at your code, there really isn't any need for the pow() function to compute decVal from the user's entry of 0's and 1's. Instead, you can simply declare decVal as an unsigned value (an exact with uint32_t is used below) and simply use Left-Shift to shift each input by the current loop counter number of bits.
Using the left-shift described above to compute decVal (ensuring decVal is initialized to zero when declared), and adding the user inputs to the front of the string to preserve LSB first order, you could do:
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
#include <climits>
int main (void)
{
while (1) { /* outer loop - loop continually */
size_t n; /* declare variables within loop */
uint32_t decVal = 0;
std::string originalnum {};
std::cout << "\nenter no. of bits ('q' to quit): ";
if (!(std::cin >> n)) { /* validate EVERY user input */
std::cerr << "invalid unsigned input -- exiting.\n";
return 1;
}
if (n > sizeof (uint32_t) * CHAR_BIT) { /* validate EVERY value in range */
std::cerr << " error: n exceeds no. of bits avaialble.\n";
return 1;
}
for (size_t i = 0; i < n;) { /* inner loop, process bits */
uint32_t bit;
std::cout << " bit" << std::setw(2) << i << ": ";
if (!(std::cin >> bit) || bit > 1) {
std::cerr << " error: invalid bit input.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
decVal += bit << i; /* no need for pow(), left-shift */
originalnum.insert(0, 1, bit + '0'); /* build originalnum each iteration */
i++; /* increemnt on good input */
}
/* result */
std:: cout << "The decimal equivalent of " << originalnum <<
" = " << decVal << '\n';
}
}
(note: Numeric limits -- cppreference.com shows the header files needed for each limit used)
Example Use/Output
Below is input and output similar to what you show, but with prompts added to guide the user, and error handling implemented to ensure only valid 0's and 1's are taken as input:
$ ./bin/decval
enter no. of bits ('q' to quit): 3
bit 0: 1
bit 1: 1
bit 2: 0
The decimal equivalent of 011 = 3
enter no. of bits ('q' to quit): 3
bit 0: 1
bit 1: 0
bit 2: 0
The decimal equivalent of 001 = 1
enter no. of bits ('q' to quit): 3
bit 0: 1
bit 1: 0
bit 2: pickles
error: invalid bit input.
bit 2: 1
The decimal equivalent of 101 = 5
enter no. of bits ('q' to quit): q
invalid unsigned input -- exiting.
Look things over and let me know if you have further questions or if I misunderstood your intent.
Just clear the string after the
cout << ... << endl;
Try this
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void main()
{
int n, decVal;
int i = 7;
string num, b, originalnum;
cin >> n;
for (x = 0; x < n; ++i)
{
cin >> num;
cin.get(b);
cin.ignore();
originalnum += b
decVal += atoi(&b) * pow(2, i);
i -= 1
cout << "The decimal equivalent of " << originalnum << " = " << decVal << endl;
originalnum = "";
n = 0;
}
}

Undefined behaviour when entering `char` for integer variable with `std::cin`

I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:
int num1;
bool cond {false};
while(!cond){
cout<<"enter 2:";
cin>>num1;
if (!isdigit(num1)){
cout<<"not a digit:";
cin>>num1;
}
//
if(num1 == 2)
cond = true;
}
I would suggest trying something a little more straightforward instead of your current code:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num1;
cout << "Please enter the number 2:";
cin >> num1;
while (num1 != 2)
{
cin.clear(); //Clears the error flag on cin.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You did not enter the number 2, Please try again:";
cin >> num1;
}
return 0;
}
Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.
Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.
You need to use the header file #include<limits> to use this.
I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int num1;
string input;
bool cond{ false };
cout << "enter 2:";
while (!cond) {
getline(cin, input);
stringstream ss(input);
ss >> num1;
if( ss.fail() ){
cout << "not a digit:";
continue;
}
//
if (num1 == 2)
cond = true;
else
cout << "enter 2:";
}
return 0;
}
int num1;
bool cond {false};
do{
cout<<"enter 2:";
cin>>num1;
if (cin.good()) {
cond = true;
}else {
cin.clear();
cin.ignore();
cout << "Invalid, please enter 2." << endl;
}
}while(!cond);
While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.
Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.
I hope this solves your problem
Why does the loop iterate infinitely?
Let's take this example
int a;
std::cin >> a;
std::cout << "Entered: " << a;
Now let's test it with different inputs
with int
5
Entered: 5
10
Entered: 10
Yes just as we would expect, but what happens when you enter a char?
with char
r
Entered: 0
f
Entered: 0
Why does this happen?
When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.
How to solve this?
As I have mentioned earlier, it fails. When this fails you can catch it this way
if (!(std::cin >> a))
{
std::cout << "Invalid input ! \n";
}
We're saying, if the input fails, show the message.
let's test this new code.
int a;
if (!(std::cin >> a))
{
std::cout << "Invalid input !\n";
}
else
{
std::cout << "Entered: " << a;
}
5
Entered: 5
r
Invalid input !
How to print char value of the int?
If you want to just print the ASCII value of the entered number, you need to cast the value into char.
You can do
int num = 48;
char character_value = num;
Here C++ will implicitly convert char into int.
But if you need a safer type of conversion, prefer using static_cast<>.
The syntax looks like this
int a = 5;
char character_value = static_cast<char>(a);
Static cast in C++
Type casting in C++
Dealing with invalid input in C++

why does my calculator program start flashing and scrolling when i enter a large number

my program is a calculator that currently only does addition and subtraction, but when i input a large number it starts flashing and scrolling. it works fine for small numbers. the program isn't long so here it is. a youtube video of the problem https://youtu.be/Fa03WtgXoek
#include <iostream>
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
return a;
}
int add()
{
int x = GVFU();
int y = GVFU();
int z = x + y;
std::cout <<z <<std::endl;
return 0;
}
int subtract()
{
int x = GVFU();
int y = GVFU();
int z = x - y;
std::cout <<z << std::endl;
return 0;
}
int main()
{
for ( ; ; )
{
std::cout << "enter 1 for addition and 2 for subtraction";
int c;
std::cin >> c;
if (c==1)
{
add();
}
if (c==2)
{
subtract();
}
std::cout << "press 1 to end";
int e;
std::cin >>e;
if (e==1)
{
return 0;
}
}
}
If you try to read a value from cin and the value read doesn't match the expected format, it causes the stream to fail and all future read operations will instantly return without reading anything.
Independently, in C++ integer values for the int type have a minimum and maximum possible value that depends on what compiler and system you're using. If you exceed that value when entering a number, cin will consider it a failed read.
Putting this together, once you enter a value that's too large, the program will keep running through the main loop in your program, prompting for a value, instantly returning without actually getting user input, then calculating garbage values.
To fix this, you'll need to either (1) just hope the user doesn't type in anything unexpected or (2) get user input more robustly. There are a number of good explanations about how to do option (2) here on Stack Overflow, and now that you know what the root cause of the issue is you can hopefully get the code fixed and working!
Use
std::cout << std::numeric_limits<int>::max() << std::endl;
and include #include <limits> and you will find out max int value on your machine.
int on your system is likely a 32-bit signed two's complement number, which means the max value it can represent is 2,147,483,647.
If you add bigger number stream will fail and all next read operations will return without reading anything.
Use unsigned long long which will allow you to insert bigger numbers.
You are taking your inputs as " int " and value range for int is between -2,147,483,648 to 2,147,483,647.
Which means that if you exceed this value 2,147,483,647 it can not be stored as an integer(int) type.
You should probably use Long data type for such large numbers.
You can add a following check in your code if the user input more than int limit
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
return a;
}
I would also add exit if invalid number
#include <iostream>
#include <cstdlib>
using namespace std;
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
std::exit(EXIT_FAILURE);
}
return a;
}
Note: You could also more info instead of just "Invalid input "
Output like size or limit info
enter 1 for addition and 2 for subtraction1
enter number4535245242
Invalid input
Program ended with exit code: 1

cin infinite loop when reading in a non-numeric value

I had a strange behavior in a program and I spent long time trying to deduce why. it was an infinite loop with no sense. Testing these lines of code(under suspicion) i got the same result. Every time I type in a non-numeric value such a symbol, the program runs through an infinite loop printing zeros, which i guess is how cout represents the wrong value entered. I'd like to know why is that weird behavior from cin, printing all those zeros instead of stopping when it finds a wrong reading.
#include <iostream>
using namespace std;
int main()
{
int n = 0;
while(n >= 0) {
cin >> n;
cout << n << endl;
}
return 0;
}
the program runs through an infinite loop printing zeros, which i guess is how cout represents the wrong value entered.
That is not quite right: when you ask cin for an int, but there's no int, you get no value back, but the invalid input remains in the buffer. When you ask for int again in the next iteration of the loop, same thing happens again, and no progress is made: bad data remains in the buffer.
That's why you get an infinite loop. To fix this, you need to add some code to remove bad data from the input buffer. For example, you could read it into a string, and ignore the input:
int n = 0;
while(n <= 0) {
cin >> n;
if (!cin.good()) {
cin.clear();
string ignore;
cin >> ignore;
continue;
}
cout << n << endl;
}
Demo.
You need to "eat" the non-numerical input i.e.
#include <iostream>
using namespace std;
int main()
{
int n = 0;
while(n >= 0) {
cin >> n;
if (!cin) {
char c;
cin >> c;
} else {
cout << n << endl;
}
}
return 0;
}

Is there a way to not include a negative number in an average, when entering a negative number is how you terminate the program?

Sorry about last time for those who saw my previous thread. It was riddled with careless errors and typos. This is my assignment:
"Write a program that will enable the user to enter a series of non-negative numbers via an input statement. At the end of the input process, the program will display: the number of odd numbers and their average; the number of even numbers and their average; the total number of numbers entered. Enable the input process to stop by entering a negative value. Make sure that the user is advised of this ending condition."
And here is my code:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int number, total1=0, total2=0, count1=0, count2=0;
do
{
cout << "Please enter a number. The program will add up the odd and even ones separately, and average them: ";
cin >> number;
if(number % 2 == 0)
{
count1++;
total1+=number;
}
else if (number >= 0)
{
count2++;
total2+=number;
}
}
while (number>=0);
int avg1 = total1/count1;
int avg2 = total2/count2;
cout << "The average of your odd numbers are: " << avg1 << endl;
cout << "The average of your even numbers are " << avg2 << endl;
}
It seems to be working fine, but when I enter a negative number to terminate the program, it includes it with the rest of the averaged numbers. Any advice to get around this? I know it's possible, but the idea escapes me.
Your main loop should be like this:
#include <iostream>
for (int n; std::cout << "Enter a number: " && std::cin >> n && n >= 0; )
{
// process n
}
Or, if you want to emit a diagnostic:
for (int n; ; )
{
std::cout << "Enter a number: ";
if (!(std::cin >> n)) { std::cout << "Goodbye!\n"; break; }
if (n < 0) { std::cout << "Non-positve number!\n"; break; }
// process n
}
After here:
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
Immediately check if the number is negative
if(number < 0) break;
Now you wouldn't need to use your do-while loop in checking if the number is negative. Thus, you can use an infinite loop:
while(true) {
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
if(number < 0) break;
// The rest of the code...
}
ADDITIONAL:
There is something wrong in your code. You aren't showing the user how much the number of even and odd numbers are, and the total number of numbers entered.
ANOTHER ADDITIONAL: You should use more meaningful variable names:
int totalNumEntered = 0, sumEven = 0, sumOdd = 0, numEven = 0, numOdd = 0;
Of course I am not limiting you to these names. You can also use other similar names.
FOR THE INTEGER DIVISION PROBLEM:
You must cast your expression values to the proper type (in this case, it is float). You should also change the averages variables' types to float:
float avg1 = float(total1) / float(count1);
float avg2 = float(total2) / float(count2);
Immediately after cin >> number, check for < 0, and break if so. Try to step through the program line by line to get a feel for the flow of execution. Have fun learning, and good luck!