How do I parse user input from the standard input stream? - c++

I'm writing a very simple program where I want to get user input from the standard input stream (keyboard) and then do something based on what input I encountered. However, the problem is that sometimes the input will be a number (double) while othertimes it'll be a string. I'm not sure exactly what methods calls I need in order to parse it properly (perhaps something similar to Integer.parseInt in java).
Here is some pseduocode of what I would like to do:
cin >> input
if(input is equal to "p") call methodA;
else if(input is a number) call methodB;
else call methodC;

I think this is what you need:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void a(string& s){ cout << "A " << s << endl; }
void b(double d){ cout << "B " << d << endl; }
void c(string& s){ cout << "C " << s << endl; }
int main()
{
std::string input;
cin >> input;
if (input == "p")
a(input);
else
{
istringstream is;
is.str(input);
double d = 0;
is >> d;
if (d != 0)
b(d);
else
c(input);
}
return 0;
}
Hope this helps ;)

std::string input;
std::cin >> input;
if(input =="p") f();
else if(is_number(input)) g();
else h();
Now implement is_number() function:
bool is_number(std::string const & s)
{
//if all the characters in s, are digits, then return true;
//else if all the characters, except one, in s are digits, and there is exactly one dot, then return true;
//else return false
}
Implement this function yourself, as it seems to be homework. You can also consider case like the number may begin with sign + or -.

The usual solution I use is to read the input as a line (using
std::getline rather than >>), and parse it as I would in any
language—boost::regex is very useful here; if you are sure that
you can count on C++11, it's std::regex (which I think is almost
identical to Boost). So you end up with something like:
std::string line;
if ( ! std::getline( std::cin, line ) ) {
// Error reading line (maybe EOF).
} else {
if ( regex_match( line, firstFormat) ) {
processFirstFormat( line );
} else if ( regex_match( line, secondFormat) ) {
processSecondFormat( line ) ;
} ...
}

Related

How to make user input numbers only in C++?

So far, this is my code:
while(bet > remaining_money || bet < 100)
{
cout << "You may not bet lower than 100 or more than your current money. Characters are not accepted." << endl;
cout << "Please bet again: ";
cin >> bet;
}
It works fine but I'm trying to figure out how to make it loop if the user inputs anything that isn't a number as well.
When I press a letter or say a symbol/sign, the code just breaks.
Using the function
isdigit()
This function returns true if the argument is a decimal digit (0–9)
Don't forget to
#include <cctype>
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
A good way of doing this is to take the input as a string. Now find the length of the string as:
int length = str.length();
Make sure to include string and cctype. Now, run a loop that checks the whole string and sees if there is a character that is not a digit.
bool isInt = true;
for (int i = 0; i < length; i++) {
if(!isdigit(str[i]))
isInt = false;
}
If any character is not a digit, isInt will be false. Now, if your input(a string) is all digits, convert it back to an integer as:
int integerForm = stoi(str);
Store integerForm in your array.

Input validation for certain test not working as expected

double checkInput() {
double add;
cout << "\n" << endl;
cin >> add;
if (cin.fail()==true)
{
cin.clear();
cin.ignore(INT_MAX, '\n');
cout << "Incorrect input"<<endl;
}
else
{
return add;
}
}
I use this bit of code to filter out character inputs eg "Blarg","bat12cat" and similar inputs where the character/letter come first but when i test with "1gold" ,"0.05cake" etc where number comes first then letters,the program accepts the all numbers up to the first instance of a letter.
My understanding is that it is the cin.ignore() that is causing the issue and is allowing the numbers through.
What would let inputs like"0.05Cats" be ignored/skipped altogether?.
Searching online,people suggest using getline() and stringstream.
Thank you.
When you input something like 1.5dog and then use cin >> some_double; >> is going to extract out a double until it can't read any more. So some_double gets the 1.5 and dog is still in the stream. This is not a failure and as such the failbit is not set. Since it is not set you skip your if statement and return the double value while the rest of the input stays in the stream and will cause you issues the next time you try to read from the stream. My suggestion is to change how you read your inputs. You can take in the input via a std::string and then convert it to the desired type. Then if the conversion fails you you can signal that you had a failure. I would use something like:
bool read_double(std::istream & is, double & number)
{
std::string line;
getline(is, line);
std::size_t pos = 0;
double temp = stod(line, &pos);
if (pos != line.size()) // there is extra content in the streams
return false;
number = temp;
return true;
}
And you can see it working with this Live Example
Usually there is more than one way to do the right thing. Using "c++(11) regex class object" would help you. You can edit regex for your needs (for example to include hex numbers by adding -a,b,c,d,e,f).
#include <iostream>
using namespace std;
#include <string>
using std::string;
#include <regex>
void main()
{
string input;
std::regex reg("[-+]?([0-9]*\.[0-9]+|[0-9]+)");
cout << "Please enter a double type\n";
while (cin >> input)
{
if (std::regex_match(input, reg))
{
std::cout << "Valid input\n";
break;
}
else
{
cout << "Invalid input\n";
cout << "Please enter a double type\n";
}
}
double do_with = std::stod(input,NULL);
cout << "the double is : " << do_with << endl;
cin >> input; // to hold the shell
}

How do you parse a c-string?

Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!
Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.
std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}

C++ - Sanitize Integer Whole Number Input

I currently am using a function I found in another StackOverflow post(I can't find it), that I am using before, named "GetInt". My issue with it is that if the user inputs something like "2 2 2" it puts it into my next two Cin's. I have tried getLine, but it requires a string and I am looking for an int value. How would I structure a check to sanitize for an integer value greater than 2 and throw an error to the 2 2 2 answer.
#include <iostream>
#include <string>
#include <sstream>
#include "Board.cpp"
#include "Player.cpp"
using namespace std;
int getInt()
{
int x = 0;
while (!( cin >> x))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Please input a proper 'whole' number: " << endl;
}
return (x);
}
and my call
do
{
//do
//{
cout << "How many players are there? \n";
numberOfPlayers = getInt();
//} while (isdigit(numberOfPlayers) == false);
} while (numberOfPlayers < 2);
EDIT:
I chose Justin's answer because it was the closest to my original code and solved the issue without major changes.
Integers are delimited by spaces and the input 2 2 2 is just multiple integers. If you want to make sure that just one integer is entered per line you could skip whitespace characters until a newline is found. If a non-whitespace is found prior to a newline you could issue an error:
numberOfPlayers = getInt();
int c;
while (std::isspace(c = std::cin.peek()) && c != '\n') {
std::cin.ignore();
}
if (c != std::char_traits<char>::eof() && c != '\n') {
// deal with additional input on the same line here
}
You were on the right track with std::getline. You read the whole line as a string, then put it into a std::istringstream and read the integer out.
std::string line;
if( std::getline(cin, line) ) {
std::istringstream iss(line);
int x;
if( iss >> x ) return x;
}
// Error
This will have the effect of discarding any fluff that comes after the integer. It will only error if there is no input or no integer could be read.
If you want to have an error when stuff appears after the integer, you could take advantage of the way strings are read from a stream. Any whitespace is okay, but anything else is an error:
std::istringstream iss(line);
int x;
if( iss >> x ) {
std::string fluff;
if( iss >> fluff ) {
// Error
} else {
return x;
}
}
Change your code to this:
int getInt()
{
int x = 0;
while (!( cin >> x))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Please input a proper 'whole' number: " << endl;
}
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return (x);
}
Your code to ignore the rest of the line after receiving the integer is only called if the integer collection fails (for example, you type "h" as the number of players).

How to check if the input is a valid integer without any other chars?

#include <iostream>
#include <limits>
using namespace std;
int main()
{
int x;
cout << "5 + 4 = ";
while(!(cin >> x)){
cout << "Error, please try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
if (x == (5 + 4)){
cout << "Correct!" << endl;
}
else{
cout << "Wrong!" << endl;
}
return 0;
}
How can I check if the user inputs a valid integer? In this program I wrote above, if the user inputs 9, it should be correct, however, if the user inputs 9a for example, it should return an error, but it doesn't for some reason. How can I correct it?
How I did it using cin.peek()
#include <iostream>
#include <limits>
#include <stdio.h>
using namespace std;
int main()
{
int x;
bool ok;
cout << "5 + 4 = ";
cin >> x;
while(!ok){
cin >> x;
if(!cin.fail() && (cin.peek() == EOF || cin.peek() == '\n')){
ok = true;
}
else{
cout << "Error, please try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
if (x == (5 + 4)){
cout << "Correct!" << endl;
}
else{
cout << "Wrong!" << endl;
}
return 0;
}
You could read a string, extract an integer from it and then make sure there's nothing left:
std::string line;
std::cin >> line;
std::istringstream s(line);
int x;
if (!(s >> x)) {
// Error, not a number
}
char c;
if (s >> c) {
// Error, there was something past the number
}
bool isIntegerNumber(const std::string& string){
std::string::const_iterator it = string.begin();
int minSize = 0;
if(string.size()>0 && (string[0] == '-' || string[0] == '+')){
it++;
minSize++;
}
while (it != string.end() && std::isdigit(*it)) ++it;
return string.size()>minSize && it == string.end();
}
You have a line oriented input, so you should probably be using
getline. Something like:
bool
getIntFromLine( std::istream& source, int& results )
{
std::string line;
std::getline( source, line );
std::istringstream parse( source ? line : "" );
return parse >> results >> std::ws && parse.get() == EOF;
}
should do the trick.
Using this, your loop would be:
while ( !getIntFromLine( std::istream, x ) ) {
std::cout << "Error, please try again." << std::endl;
}
Note that this technique also means that you don't have to worry
about clearing the error or resynchronizing the input.
For the reason this happens, take a look at this link:
Extracts and parses characters sequentially from the stream to
interpret them as the representation of a value of the proper type,
which is stored as the value of val. Internally, the function accesses
the input sequence by first constructing a sentry object (with
noskipws set to false). Then (if good), it calls num_get::get (using
the stream's selected locale) to perform both the extraction and the
parsing operations, adjusting the stream's internal state flags
accordingly. Finally, it destroys the sentry object before returning.
Then observe the behavior if you attempt something like this:
int x = 0;
cin >> x;
std::cout << x << std::endl;
std::cout << cin.good() << std::endl;
g++-4.8 -std=c++11 -O3 -Wall -pedantic -pthread main.cpp && echo "900a100" | ./a.out
// Output:
// 900
// 1
If you input "a100" instead, it outputs:
0
0
try this:
std::string input;
std::cin >> input;
if ( std::all_of(input.begin(), input.end(), std::isdigit) )
{
//input is integer
}
Refer this :
C++ Fix for checking if input is an integer
One I have seen that works for some situations is:
Read the input as string. cin >> str
Decode to number: atoi, or sscanf, or stringstream, etc.
print the number into a string (using sprintf or stringstream)
check if its equal to read string. (using strings ==, not char*)
Quick and simple to do. Uses the Cin>>str word breaking rules, accept negative numbers, rejects overflowing numbers. But it does reject "+10", which in somesituations you are happy wiht, and in some you are not.
If you can use C++11 (and your compiler has full regex support), you can also use the <regex> library:
#include <iostream>
#include <limits>
#include <regex>
#include <string>
#include <utility>
int main()
{
std::string line;
std::pair<int, bool> value = std::make_pair(0, false);
std::cout << "5 + 4 = ";
while (!value.second)
{
while (!std::getline(std::cin, line))
{
std::cout << "Error, please try again." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
if (!std::regex_match(line, std::regex("(\\+|-)?[[:digit:]]+")))
{
std::cout << "Error, please try again." << std::endl;
}
else
{
value = std::make_pair(std::stol(line), true);
}
}
if (value.first == (5 + 4))
{
std::cout << "Correct!" << std::endl;
}
else
{
std::cout << "Incorrect!" << std::endl;
}
return 0;
}