How to read unknown number of inputs? - c++

I am learning C++ using the book C++ Primer.
In Section 1.4.3, the following example code about reading the unknown number of inputs is given.
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
According to the book, if we give an input of 3 4 5 6, the output will be Sum is: 18
But when I try this on my computer(Windows 10 with MinGW), The code does not end. It just keeps on asking for input even if I enter a newline. It works only when I enter a non-int input like f.
Is this expected? If yes, is there any code that stops after inputting a newline?
I am quite new to c++ and I have already learned python, so getting stuck so early on is quite frustrating.
Thanks and regards.

You need to terminate your input by an End-Of-File-character (i.e. CTRL-Z on Windows, CTRL-D on Mac/Unix), not just by an End-Of-Line (i.e. Enter).
A simple Enter is interpreted as white space, which will be simply ignored by operator>> when reading into an integral data type.
CTRL-Z / End-Of-File, in contrast, makes any operator>> fail with an error.
See also this SO answer.
Note: Entering f will also terminate your loop, since f is not considered a valid integral number; Hence, std::cin >> value with value being of type int and an input like f will fail as well. To be more accurate: operator>> actually returns a reference to the input stream, but if reading in a value fails, failbit is set on the stream, and then interpreting the stream object in a boolean expression (implicitly calling basic_istream::operator bool()) returns false; So maybe the author of the book did not want to explain these details at the respective section in the book :-)

Is this expected?
Yes, as operator>> ignores leading whitespace by default, which includes line breaks.
If yes, is there any code that stops after inputting a newline?
Use std::cin.getline() or std::getline() instead of operator>>. You can then use operator>> with a std::istringstream to parse values from each line, eg:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string line;
int sum, value;
do
{
std::cout << "Enter a set of numbers, or a blank line to exit: ";
if (!std::getline(std::cin, line) || line.empty())
break;
// read until end-of-line, calculating a running total of all values read
std::istringstream iss(line);
sum = 0;
while (iss >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
}
while (true);
return 0;
}
Live Demo

Is this expected?
Yes, Thats what while (std::cin >> value) does. See this answer for more explanations: How is "std::cin>>value" evaluated in a while loop?
is there any code that stops after inputting a newline?
No, as >> simply ignore a white space(also #StephanLechner mentioned it)
What you can do instead is:
Just give a condition; if it satisfies just break the loop. you
can also provide a console out to make it more understandable to the
user. For example:
std::cout << "Enter value to sum or press -1 to exit" << std::endl;
while (std::cin >> value && value != -1) // if value == -1, loop stops.
{
sum += value;
}
You can simply terminate by the end of character:
CTRL-Z on Windows
CTRL-D on Mac/Unix

Related

How to determine in C++ if an element in a text file is a character or numeric?

I am trying to write a code in C++ reading a text file contains a series of numerics. For example, I have this .txt file which contains the following series of numbers mixed with a character:
1 2 3 a 5
I am trying to make the code capable of recognizing numerics and characters, such as the 4th entry above (which is a character), and then report error.
What I am doing is like
double value;
while(in) {
in >> value;
if(!isdigit(value)) {
cout << "Has non-numeric entry!" << endl;
break;
}
else
// some codes for storing the entry
}
However, the isdigit function doesn't work for text file. It seems when I am doing in >> value, the code will implicitly type-cast a into double.
Can anyone give me some suggestion?
Thanks a lot!
Your while loop doesn't do what you think it does.
It only iterates one statement:
in >> value;
The rest of the statements are actually outside the loop.
Using curly braces for the while body is always recommended
I created a small mini script where I would be reading in a file through a standard fstream library object as I was a little unsure on what your "in" represented.
Essentially, try to read in every element as a character and check the digit function. If you're reading in elements that are not of just length 1, a few modifications would have to be made. Let me know if that's the case and I'll try to help!
int main() {
std::fstream fin("detect_char.txt");
char x;
while (fin >> x) {
if (!isdigit(x)) {
std::cout << "found non-int value = " << x << '\n';
}
}
std::cout << '\n';
return 0;
}
Try reading the tokens into string and explicitly parsing it
ifstream infile("data.txt");
string token;
while (infile >> token) {
try {
double num = stod(token);
cout << num << endl;
}
catch (invalid_argument e) {
cerr << "Has non-numeric entry!" << endl;
}
}
Since it looks like the Asker's end goal is to have a double value for their own nefarious purposes and not simply detect the presence of garbage among the numbers, what the heck. Let's read a double.
double value;
while (in) // loop until failed even after the error handling case
{
if (in >> value) // read a double.
{
std::cout << value; // printing for now. Store as you see fit
}
else // failed to read a double
{
in.clear(); // clear error
std::string junk;
in >> junk; // easiest way I know of to read up to any whitepsace.
// It's kinda gross if the discard is long and the string resizes
}
}
Caveat:
What this can't handle is stuff like 3.14A. This will be read as 3.14 and stop, returning the 3.14 and leave the A for the next read where it will fail to parse and then be consumed and discarded by in >> junk; Catching that efficiently is a bit trickier and covered by William Lee's answer. If the exception handling of stod is deemed to expensive, use strtod and test that the end parameter reached the end of the string and no range errors were generated. See the example in the linked strtod documentation

Trying to understand cin behavior

I am writing software that takes a (huge) input stream from stdin and reads it into a vector of floats. I want to capture the case that the stream contains characters like commas, and either fail to accept it, or simply ignore everything that cannot be parsed as float (whichever is easier to implement, I have no preference). I have noticed the following behavior: when I call
echo "1.4, -0.7 890 23e-3" | ./cintest
this version
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
int main ( int argc, const char* argv[] ){
float val;
while (cin >> val) {
cout << val << endl;
}
return 0;
}
prints
1.4
while this version
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
int main ( int argc, const char* argv[] ){
float val;
while (cin) {
cin >> val;
cout << val << endl;
}
return 0;
}
prints
1.4
0
Without the comma, the first one prints
1.4
-0.7
890
0.023
while the second one prints
1.4
-0.7
890
0.023
0.023
Could somebody please explain what is going on here?
The first version of your code
while (cin >> val) {
tries to parse a float, and then checks whether the stream state is good. (Specifically, it calls operator>> to do the extraction, which will set failbit on error, and then uses the bool conversion to test failbit).
So, if the stream state is bad (because it couldn't convert , to a float), the loop body is not entered. Hence it terminates on the first failed conversion.
The second version
while (cin) {
cin >> val;
checks if the stream state is good (which just tells you the previous conversion succeeded), then tries parsing a float, and then assumes this succeeded without checking. It ought to check the stream state after conversion before using the float value, which in this case is left over from the previous iteration.
In a correct implementation, when conversion fails, you should check whether fail() is true but eof() is false (ie, the conversion failed for some reason other than end-of-file). In this case, use ignore() to discard input - you could either require whitespace (and ignore until the next space), or just ignore one character and try again.
Note that the ignore documentation linked above includes sample code with correct error handling. If we choose to skip a single character on failed conversions, your code would become:
for(;;) {
float val;
std::cin >> val;
if (std::cin.eof() || std::cin.bad()) {
break;
} else if (std::cin.fail()) {
std::cin.clear(); // unset failbit
std::cin.ignore(1); // skip next char
} else {
std::cout << val << '\n';
}
}
Your results have to do with when the >> fails.
In both versions, you read your values and reach the comma (or EOF). The read obviously fails, because , and EOF are not valid integers that >> can parse. So >>'s return value (the stream itself) converts to false, and you exit the loop in the first version (this is how it should work).
In the second version (which isn't how you should usually do it), however, you are still printing out whatever value ends up in val. In C++ before C++11, val remains the same; since C++11 >> writes 0 on failure.
TL;DR: Your second version stops the loop to late, and writes one pass of garbage.
It's because in the second one you have a bug.
You should always check to see if the formatted input operator>> actually worked.
So this code:
cin >> val;
cout << val << endl;
Should be written as:
if (cin >> val) {
cout << val << endl;
}
If the operator>> fails. Then it will set one of the fail bits on the stream and not put any value into val. So there is no need to print val because nothing was put into it.
This is why your second version prints garbage when it has no data left to read. The read fails and then you print out a value. Then you try and re-start the loop (which fails).
The first one works correctly.
while (cin >> val) {
cout << val << endl;
}
Because you read a value then check to see if the read works before entering the loop.
std::cin is an instantiation of std::istream
when there is a comma or any invalid data type at any point the operator >> fails. hence your code prints the last known value of 'val'.
Linked here is a reference for 'std::istream >>'
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

Confusion in cin functionality with int dataype

{
int n;
cin>>n;
cout<< n;
}
The output is 0 when any alphabet or special character is given as input.
In C its not the case when I used scanf(); and printf(). It prints the corresponding ASCII value.
Please explain why is this happening?
Please explain why is this happening?
In the documentation of the std::istream& operator>>(std::istream&, int) it's stated (emphasis mine):
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
For c++11 code it seems initialization is guaranteed:
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Assumed you run a debug build of your code, n is probably initialized with 0 automatically, but technically accessing it is undefined behavior, since it wasn't initalized in that case you describe.
You have to check cin's state after input to detect if a failure occured during the number extraction, or if you can safely use the now-initialized value:
int n;
std::cin >> n;
if(std::cin) {
std::cout << n << std::endl;
}
else {
std::cin.clear(); // Clear the streams fail state
std::string dummy;
std::cin >> dummy; // Consume the non numeric input
std::cout << "Wrong input, '" << dummy << "' is not a number."
}
In both C and C++, when inputting an integer, the driver input function will read numeric characters until a character that is not a number is read.
For example, the sequence "123GHI" should return the value 123.

C++ stringstream, if word is numeric, divide by two

I am fairly new to programming and have to create a program which reads the prompt: "I have 8 dollars to spend." It then needs to print out with each word on a separate line, and then if any of the strings is numeric, it needs to be divided by 2. Therefore it should end up printing out as:
I
have
4
dollars
to
spend.
I have managed to do everything, except finding the numeric value and dividing it by 2. So far I have this:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string prompt;
string word;
cout << "Prompt: ";
getline(cin, prompt);
stringstream ss;
ss.str(prompt);
while (ss >> word)
{
cout << word << endl;
}
return 0;
}
After looking through various other posts, I cannot manage to get this to work. I'm assuming its an if/else statement within the while loop along the lines of, if numeric, set int num to num / 2 then cout << num << endl;, else cout << word << endl;, but I can't figure it out.
Thanks in advance.
You can use the stringstream class, which handles conversions between strings and other data types, to attempt to convert a given string to a number. If the attempt is successful, you know
The stringstream object allows you to treat a string as though it is a stream similar to cin or cout.
Incorporate this into your while loop, like so:
while (ss >> word)
{
int value = 0;
stringstream convert(word); //create a _stringstream_ from a string
//if *word* (and therefore *convert*) contains a numeric value,
//it can be read into an _int_
if(convert >> value) { //this will be false if the data in *convert* is not numeric
cout << value / 2 << endl;
}
else
cout << word << endl;
}
The strtol (C++11 version that works on std::string directly: std::stol) function is really good for testing whether a string holds a number, and if so, what the numeric value is.
Or you could continue using iostreams like you have been... try extracting a number (int or double variable), and if that fails, clear the error bit and read a string.
I dont have 50 rep so I cant comment, thats why I'm writing it as answer.
I think you can check it character by character, using Ascii value of each char, & if there are ascii values representing numbers between two spaces(two \n in this case as you've already seperated each word), then you have to divide the number by 2.

Effects on Input Variable after Failed Input Stream

I was working on the following code.
#include <iostream>
int main()
{
std::cout << "Enter numbers separated by whitespace (use -1 to quit): ";
int i = 0;
while (i != -1) {
std::cin >> i;
std::cout << "You entered " << i << '\n';
}
}
I know that using while (std::cin >> i) would have been better but I don't understand a specific occurrence.
If I provide an invalid input, the loop becomes infinite because the Input Stream enters a failbit state. My question is that what happens to the input variable i? In my case, it becomes 0 regardless of the previous value entered. Why does it change to 0 after an invalid input? Is this a predefined behaviour?
You get zero because you have a pre-C++11 compiler. Leaving the input value unchanged on failure is new in the latest standard. The old standard required the following:
If extraction fails, zero is written to value and failbit is set. If
extraction results in the value too large or too small to fit in
value, std::numeric_limits::max() or std::numeric_limits::min()
is written and failbit flag is set.
(source)
For gcc, you need to pass -std=c++11 to the compiler to use the new behavior.