C++ - Cin.fail when space on begining - c++

I need help with cin.fail when it starts with a space.
This is what I mean.
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
char b[80];
int e,d,v,m=0;
for(int i=0;i<80;i++)
{
b[i]=0;
}
cout << "Insert number in binary:" << endl;
cin >> b;
v=0;
for(int i=0;i<80;i++)
{
if(b[i]=='1' || b[i]=='0' || b[i]=='\n')
{
v++;
}
else if(b[i]!=0 || b[i]!='\0' || b[i]==' ')
{
cout << "Error" << endl;
return 0;
}
}
e=v-1;
d=0;
m=0;
for(int i=0;i<v;i++)
{
m=(b[i]-48)*(pow(2,e));
d=d+m;
e=e-1;
}
cout << "His number in decimal: "<< d << endl;
return 0;
}
When there is something like 1010 it OK, it will give me number.
If it contains other number - 2,3 etc.. it will fail, its OK
But when it get something like _101010 .. programm will still proceed and it will give me number, but I need it to fail. So I need something like .. when b contains 1 0 or \n, programm will continue, otherwise it will fail. But when I put in \n like
if(b[i]=='1' || b[i]=='0' || b[i]=='\n') - its not working .. I mean, programm fails in any case ...
Sorry for asking on this "stupid" question, but I am doing it for hours and still didnt figure it out .. Thanks guys.

cin >> b; will skip leading whitespace and then read the next word. That's how it is designed.
If you want to read an entire line of input, use getline instead.
It will also be much easier, and a lot safer, if you read into a std::string instead of a fixed size char b[80];. If you ever happen to read more than 80 characters into that, you're toast.

Related

Need some help finding a logical error in my while loop

I am learning C++, and I am doing some exercises in the book I am using. One of them asks to write a program that asks a user how many numbers they want to add up. Then prompt for the numbers the user wants to add or to enter '|' once finished. The numbers are then pushed into a vector. Part of the program asks to check if the size of the vector is equal to the original number of input items and that is where I keep getting an error.
cout << "Please enter the numbers and | once you are done: ";
while(true)
{
for(int num; cin >> num; )
{
if(num == '|')
{
break;
}
ints.push_back(num);
}
if(ints.size() != n)
{
cout << "There are more or less numbers in the vector than originally specified\n"
<< "Vector will be cleared; please re-enter the values: ";
ints.clear();
continue;
}
else
{
break;
}
}
The problem is that if the number of input is off, the message goes into an infinite loop and I am not sure how to fix it.
EDIT: n is the variable that holds in the number of values user wanted to enter.
Thanks!
num is an integer and cin >> num won't extract | symbol. Comparison num == '|' may not work as expected because num could have the numeric value of | ascii symbol even when user did not input any | symbol. You should properly handle end marker reading:
// loop will break when user enters `|` because it is not an integer
// setting failbit of cin
for(int num; cin >> num;)
{
ints.push_back(num);
}
cin.clear(); // reset failbit making cin able to read again
// check the end marker entered by user
{
string end_marker;
cin >> end_marker;
if("|" != end_marker)
{
// use of endl will flush the stream ensuring that
// printed text won't stuck in the buffer
cout << "Please use | as end marker" << endl;
continue;
}
}
Here is how I implemented it. I am worried about the logic in your while loop. I had been taught to avoid while(true) whenever possible. You know the logic behind how your code should work. With more practice you'll start to recognize the conditions you need to use. I am sure there are better ways to do it. But this is the way I tried it.
But to answer your question, the main reason it is failing is because integers cannot compare themselves with characters.
if(num == '|')
That does not work since num is an integer and not a character.
Normally I would implement this in a class and since global variables are not highly looked upon I created my own namespace. You'll have to finish the rest of the logic yourself however:
#include <iostream>
#include <vector>
#include <string>
namespace global
{
std::vector<std::string> strings;
std::vector<int> ints;
std::string a = " ";
int num = 0;
}
void doWork()
{
std::cout << "Please enter the number of integers you would like to add up: ";
std::cin >> global::num;
std::cout << "Please enter the numbers and | once you are done: ";
while (global::a != "|")
{
std::cin >> global::a;
global::strings.push_back(global::a);
}
global::strings.pop_back();
for(auto &e : global::strings)
{
global::ints.push_back(std::stoi(e));
}
}
int main()
{
doWork();
if(global::ints.size() != global::num)
{
std::cout << "Size of vector does not match the size specified. Clearing vector" << std::endl;
global::ints.clear();
global::strings.clear();
global::num = 0;
global::a = " ";
doWork();
}
}
I made a vector of char's and converted those into integers so that way you could add them up. The while loop should be checking for | rather than always running true. It then will check the size of the vector in the end, clear it if it does not match, and ask you to do it again. This is the best way that I could think of doing it.
EDIT: as VTT pointed out, char can only do one character at a time. I have converted it into a string in order to handle the conversion.
EDIT 2: reset the values of global::num and global::a to their default at the end of the failure in order to prevent crashing.

how to allow multiple inputs in case of an incorrect data type entry in cpp?

I have a program which generates random number and asks user to keep guessing it until he/she gets it right. I want it to keep accepting new values even if i incorrectly enter any other data type by handling the error cases.
My problem is that when i am trying to run the below program, as soon i input a character and hit enter, it goes into an infinite loop. I tried using cin.ignore() and cin.clear() but that just makes the program stop after the first entry.
Can anyone please help me understand what is going on and how to achieve the desired output? Thanks in advance.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
int main()
{
int secret_num, guess;
srand(time(NULL));
secret_num=rand() % 101 + 0;
cout<<"Enter your guess between 0 and 100: ";
do
{
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
}
else if( isnumber(guess))
{
if(guess>secret_num)
cout<<"Too high";
else if(guess<secret_num)
cout<<"too low";
cout<<endl;
}
}
while(secret_num!=guess);
if((guess==secret_num)| (isnumber(guess)))
{
cout<<"yes the correct number is "<<secret_num<<endl;
}
return 0;
}
Edit: Here is a screenshot of what the output looks like with cin.clear() and cin.ignore(1000,'\n') in my code, when i enter a number after entering character twice.
if (!(cin >> guess))
{
cout << " The entered value is not an integer" << endl;
cin.clear(); // clear must go before ignore
// Otherwise ignore will fail (because the stream is still in a bad state)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
By default cin.ignore will ignore a single character. If they type more than 1 char, it won't be enough, that's why I've modified it a bit.
if ((guess == secret_num) | (isnumber(guess)))
| is a bitwise operator [OR]
|| is the logical operator [OR]
But I think what you actually want is && (AND)
if ((guess == secret_num) && (isnumber(guess)))
There're several problems.
You should use cin.clear() and cin.ignore() as #José suggested.
What's isnumber()? I guess it's returning false so no hint message (i.e. "Too high" and "too low") is printed out, looks like it stops although it's just waiting the next input. And isnumber() doesn't make sense to me. guess has been declared as an int, it has to be a number, doesn't it?
if((guess==secret_num)| (isnumber(guess))) is unnecessary here. The loop won't end until the user input the correct number, this condition should have been statisfied.
You can use clear and flush
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
cin.clear();
fflush(stdin);
}
This works if you are reading from console. Otherwise you can go with #José answer.
I would change the logic inside your loop as there are some useless tests. This works for me:
#include <iostream>
#include <limits>
#include <cstdlib> // You may take a look at <random> and <chrono>
#include <time.h>
using std::cout;
using std::cin;
int main() {
srand(time(NULL));
int secret_num = rand() % 101;
cout << secret_num << '\n';
cout << "Enter your guess between 0 and 100:\n";
int guess = -1;
do {
cin >> guess;
if ( cin.eof() )
break;
if ( cin.fail() ) {
cout << "The entered value is not an integer, please retry.\n";
// clear the error flag
cin.clear();
// ignore the rest of the line
cin.ignore(std::numeric_limits<int>::max(),'\n');
// clear the value of the variable
guess = -1;
continue;
}
// now we know that guess is a number
if ( guess > secret_num )
cout << "Too high\n";
else if ( guess < secret_num )
cout << "Too low\n";
else {
cout << "Yes the correct number is " << secret_num << std::endl;
break;
}
} while ( true );
return 0;
}

Super basic code: Why is my loop not breaking?

for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
cout << size;
if(inputnum[i] == '.')
{
break;
}
}
The break breaks the input stream but the size keeps outputting.
The output of size is 012345678910111213...474849.
I tried putting size++ inside the loop but it made no difference. And size afterwards will be equal to 50, which means it went through the full loop.
I forgot to explain that I added the cout << size within the loop to debug/check why it outputted to 50 after the loop even if I only inputted 3 numbers.
I suspect that inputnum is an array of int (or some other numeric type). When you try to input '.', nothing actually goes into inputnum[i] - the cin >> inputnum[i] expression actually fails and puts cin into a failed state.
So, inputnum[i] is not changed when inputting a '.' character, and the break never gets executed.
Here's an slightly modified version of your code in a small, complete program that demonstrates using !cin.good() to break out of the input loop:
#include <iostream>
#include <ostream>
using namespace std;
int main()
{
int inputnum[50];
int size = 0;
for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
if (!cin.good()) {
break;
}
}
cout << "size is " << size << endl;
cout << "And the results are:" << endl;
for (int i = 0; i < size; ++i) {
cout << "inputnum[" << i << "] == " << inputnum[i] << endl;
}
return 0;
}
This program will collect input into the inputnum[] array until it hits EOF or an invalid input.
What is inputnum ? Make sure t's a char[]!! with clang++ this compiles and works perfectly:
#include <iostream>
int main() {
int size = 0;
char inputnum[60];
for(int i=0;i<50;i++,size++) {
std::cin >> inputnum[i];
std::cout << size;
if(inputnum[i] == '.') {
break;
}
}
return 0;
}
(in my case with the following output:)
a
0a
1s
2d
3f
4g
5.
6Argento:Desktop marinos$
Your code seams OK as long as you're testing char against char in your loop and not something else.. Could it be that inputnum is some integral value ? if so, then your test clause will always evaluate to false unless inputnum matches the numerical value '.' is implicitly casted to..
EDIT
Apparently you are indeed trying to put char in a int[]. Try the following:
#include <iostream>
int main() {
using namespace std;
int size = 0;
int inputnum[50];
char inputchar[50];
for(int i=0;i<50;i++,size++) {
cin >> inputchar[i];
inputnum[i] = static_cast<int>(inputchar[i]); // or inputnum[i] = (int)inputchar[i];
cout << size << endl; // add a new line in the end
if(inputchar[i] == '.') break;
}
return 0;
}
Then again this is probably a lab assignment, in a real program I'd never code like this. Tat would depend on the requirements but I'd rather prefer using STL containers and algorithms or stringstreams. And if forced to work at a lower-level C-style, I'd try to figure out to what number '.' translates to (simply by int a = '.'; cout << a;`) and put that number directly in the test clause. Such code however might be simple but is also BAD in my opinion, it's unsafe, implementation specific and not really C++.

Using an ASCII value as a condition

The following program should read some integer values from input and store them into an array until the user presses "Esc" key, but i cannot figure out how to do that. I have tried to use it's ASCII value as a condition but it doesn't work, or I'm doing something wrong.Could somebody please help me? Here is the code :
void main(){
int i=0, a[MAX];
cout <<"Please enter several integer numbers and press Esc when you want to finish" << endl;
while ((i != char(27)) && (i < MAX)) {
cin >> a[i];
i++;
}
There are several problems here. The first, and most important,
is that most systems will do line oriented input, which means
that they will pick up a lot of control characters (including,
probably, ESC) and do something with them internally, rather
than returning them to you; it might not even be possible to
ever see an ESC in the input.
For the rest, there are several problems with your code. The
first is that you're testing against the index into the array
(where you'll put the next character), not against anything
you've read. The second is that you're inputting int, so you
won't see any individual characters; just the results of the
conversion of your input. (In fact, if an ESC character does
get through, you'll end up with std::cin in a error state.)
The third is that you never test whether the input has
succeeded.
A better solution would be to adopt some other convention for
the input: say one number per line, with an empty line signaling
the end. In that case, you could write something like:
std::vector<int> a;
std::string line;
std::cout << "..." << std::endl;
while ( std::getline( std::cin, line ) && !line.empty() ) {
std::istringstream parse( line );
int value;
parse >> value >> std::ws;
if ( !parse ) {
std::cout << "That wasn't an integer, try again" << std::endl;
} else if ( parse.get() != EOF ) {
std::cout << "Extra garbage at end of line, ignoring it" << std::endl;
} else {
a.push_back( value );
}
}
(You'll note that I've used std::vector, since you don't know
up front how many inputs you'll get.)
If you really want to use ESC, you'll probably need a third
party library, along the lines of curses, to do raw input,
reading one character at a time, and collecting the digits into
a string, for conversion using std::istringstream.
Do not do this use James method its much better and will run on evrything but just for the sake of answering a question you can do this. This will not work on all platforms It works on visual c++ compiler.
# include <iostream>
# include <conio.h>
# include <vector>
using namespace std;
int main()
{
char key;
vector<int> a;
int temp = 0;
while ((key = getch()) != 27)
{
cin >> temp;
a.push_back(temp);
}
for (int i = 0 ; i < a.size() ; i++)
{
cout << a.at(i) << endl;
}
printf("Exit");
cout << endl;
system("Pause");
return 0;
}
Edit: Programs clearer now. Note this program should not be used it is very platform and compiler dependant.

Validating a double in c++

I'm completely new to coding, so please keep this in mind before commenting.
So I've been trying to get into coding for a while, and today I went to the library
and picked up a book called "programming in c++". I've written some basic programs,
but I have gotten stuck at one point, I have no idea how to create a function that
makes sure that when the user is prompted for a double, what they enter is valid.
(If the user enters a character like 'k', the program just breaks).
I searched here and on the net, and there are some answers, but they are more along
the line of "here's a line of code that works, insert x, y, z, into it". And I don't
have enough experience to know what to do. So here is a sample that is a mix of code
from another question, and me failing to try to make it work in my program:
#include <iostream>
#include <stdio.h>
using namespace std;
double GetDouble () {
double x;
cin >> x;
int valid = 0;
while (valid == 0) {
if (x == double) {
return x;
break;
} else if (x != double) {
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
while (cin.get() != '\n') ; // empty loop
}
}
return x;
}
Now what I want it to do is to use "cin << x" to get a user input for x, and
then make sure that x is a double, and I'm failing quite hard at this. If
someone could explain this to in a manner that clarifies each operation,
I would be truly grateful. For example, I don't know what the break function does,
and what the cin.clear(), and cin.get() do. (I know this is a duplicate, but the
answers on the other question does not at all address what I'm confused about,
thank you for taking time to read & answer this! :)
This seems a close analog to your code that (mostly) works:
double GetDouble () {
double x;
cin >> x;
// ver1: while( cin.fail() ) // or !cin.good() no trailing char check.
while( cin.fail() || (cin.peek() != '\r' && cin.peek() != '\n'))
{
cout << "Invalid Input! Please input a numerical value." << endl;
cin.clear();
while( cin.get() != '\n' ); // or cin.ignore(1000, '\n');
cin >> x;
}
return x;
}
First of all, double is a keyword so you don't need to use it in a conditional statement.
Secondly, you can use the cin>>x in a while loop and then process x , a sample code is given below:
while(cin>>x)
{
//process
}
whenever you use anything in a while statement, it first checks it's validity.
if for example user enters a character the condition will evaluate to false and you can then tell this to the user. In this way you can run the loop till the time user enters correct input.
As for the function of break keyword, it gets you out of a loop, for ex
for(int i=10; i>0; i++)
{
// do something
}
will keep on running forever, but suppose you rewrite the code as:
for(int i=10; i>0; i++)
{
if(i==15)
break ;
}
the loop will end as soon as the value of i reaches 15
Something like so:
double getDouble(const string& askMessage = "Please Enter a number: ",const string& errorMessage = "Please enter a valid number: ", const int numberOfTrials = 10){
double userInput = 0.0;
bool isValidInput = false;
int trials = 0;
do{
cout << endl << askMessage;
if(cin >> input) break;
else{
cin.clear(); //EDIT thanks ebyrob, forgot about this.
std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
std::cout << errorMessage;
}
}while(!isValidInput || trials < numberOfTrials);
return userInput;
}
use it like so
const double d1 = getDouble();
const double d2 = getDouble("Please Enter a number: ", "Error! Enter a valid number: ", 1000);
Break breaks out of a loop (in this case, a while)
cin.clear() clears the cin buffer of all chars.
cin.get() gets a single character from cin (probably standard in).