Invalid input for std::cin - c++

The following code is intended to concatenate words entered by the user.
#include <iostream>
#include <string>
int main() {
// insert code here...
std::string s;
std::string concString;
while (std::cin >> s)
{
concString = concString + s;
}
std::cout << concString << std::endl;
return 0;
}
I am stuck in this while loop during execution because of which I am not able to print the concatenated string. How do I exit this loop? What is an invalid input for std::cin?

Typically, a loop like that is stopped by end of file, rather than invalid input.
In a *nix environment, you can usually send an end of file to the terminal with CTRL+d, and at a windows console, CTRL+z.
See https://stackoverflow.com/a/16136924/1084944
You could, however, implement your own additional way to signify end of input. For example, having your users enter a blank line when done, or the word quit or such. Once you've chosen one, you should communicate that to the user, and you will have to structure your loop to be able to detect these conditions and exit.

Related

Should I handle multiple instances of cin / stdin?

Below is a little program in C++ which is supposed to act as the cat linux binutil: it gets one or several inputs as detailed in the command line arguments (possibly specifying stdin via '-') and copy them onto the standard output. Unfortunately, it shows an unintended behaviour that I cannot understand the root causes of...
Upon the following command
./ccat - test.text
I hit CTRL-D directly without passing any character. I would expect the program to display anyway the content of test.txt, but instead, the program exits without passing any more characters onto the standard output stream.
Any idea on how I should correct my code below to have the correct behaviour in this situation? Should I handle multiple instances of the standard streams (cin, cout...)? If so, do you know how this can be achieved in C++?
Thank you in advance.
/**** ccat.cpp ****/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char **argv) {
if (argc <= 1) {
cout << cin.rdbuf();
} else {
vector<string> inputs;
for (int i=1; i<argc; ++i) inputs.push_back(argv[i]);
for (auto &in: inputs) {
if (in == "-" || in == "--") {
cout << cin.rdbuf();
}
else {
ifstream *fd = new ifstream(in);
if (!fd->is_open()) cerr << "Cannot open file \'" << in << "\'\n";
else cout << fd->rdbuf();
delete fd;
}
}
}
return 0;
}
I tried the following commands in sequence:
$ ./ccat > test.txt
Let's try this text.
I would expect a correct behaviour.
$ ./ccat - test.txt # I hit CTRL-D directly without passing any character first
$ ./ccat - test.txt
But when I add some characters before hitting CTRL-D... This works fine.
But when I add some characters before hitting CTRL-D... This works fine.
Let's try this text.
I would expect a correct behaviour.
As the example shows, I would expect in any of the two cases (last two shell prompts) that test.txt gets displayed onto the standard output, but this occurs only if I inject characters through the standard input first. Hitting CTRL-D straight away makes the program exit prematurely.
That's overload 10 here;
basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb );
and it says
If no characters were inserted, executes setstate(failbit).
In other words, cout is now in an error state and will not output anything.
Doing
cout.clear();
first of all in the else branch, or last of all in the if branch, should do it.
Note that sending end-of-file to standard input is usually not something you can recover or "restart" from, so you might only be able to use one standard input "section".

Getline stuck on infinite loop

I run the following snippet of code expecting that when i hit the new line (Enter key), the program will halt, but it does not do that, any idea what's the problem ? Thanks.
#include <bits/stdc++.h>
using namespace std;
int main() {
string s ;
while(getline(cin ,s)){
cout << s << endl ;
}
}
Hitting the Enter key ends a line. If there’s no other text on the line it’s an empty line, but a line nonetheless.
There are a couple of ways you can handle this.
First, depending on your OS, either ctrl-D or ctrl-Z will act like end-of-file, and the call to getline will fail, ending the loop.
Second, if you want an empty line to end the loop, just check for it:
while (getline(cin, s) && s.length() != 0)
std::cout << s << '\n';
Pressing enter is like entering an empty line, you didn't put any condition for your program to exit. It will stay in infinity unless you forcefully exit it. Implement an exit condition in the while(), so that when it is not met, the loop will exit, and obviously put the getline() inside to keep asking prompting for input.

Stop new line for C++ cin

In C++, iostream automatically puts in a new line after cin. Is there a way to get rid of this?
I want use iomanip to format information into a table, like so:
cin cout
0.078125 3DA00000
-8.75 C10C0000
23.5 41BC0000
(random numbers)
example code:
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num; //now a new line.
cout << num << endl;
return 0;
}
You presumably pressed the return key to send your input from the command line to your program's standard input. That's where the newline is coming from. You can't read your number from cin before this newline appears in the console, because the newline is what causes the console to hand your input over to the program in the first place. You could, as a user, configure your console (or whatever is running your program) to act differently, but there's no way for the program itself to force such behavior.
If you really want to have your input and your output on the same line, you need to find a way to "write to the previous line". How that works depends on your console (see also How to rollback lines from cout?). There is no standard way to do this because cin and cout are in no way obligated to be attached to a console or anything resembling one, so it is not clear that "writing to the previous line" even means anything.
'endl' makes a new line just don't use it.
cout << num;

Getting more lines from input in C++

I need to read lines from standard input, but I dont really know, how many it will be.
I tried to do it with getline() and cin combined with a while loop, but it led to an infinite loop:
string line;
while( getline(cin, string) ){...}
or
string word;
while( cin >> word ){...}
it doesnt stops at the end of the input( the lines are coming at one time, so the user is hitting just one time the Enter key ).
Thanks for your help.
Reading your comments you have a misunderstanding of "end of input".
When you start your program it waits for input from console, and if input is available it reads it. Initially your copy some strings to your console so your program takes this as input. But your program still keeps reading from the console because there was no "end of input". The program is still connected to the console.
You need to signal "end of input" to your program. On Windows you do this by pressing Ctrl+Z. On Linux you need to press Ctrl+D.
Your problem is reading from the console.
As your console does not put an EOF(end of file) when you enter an empty line.
You should try pipeing the input from a file to your program. This should end, when there is no more input.
Otherwise, just check if the string is empty, and break out of the loop, if it is empty.
The way you run your program, your input doesn't end, since the console can always provide more input. Your program behaves correctly, though perhaps not in the way you desire. That's because you have misunderstood your own desires.
What you are looking for is perhaps (but I can't be sure) for the program to end when either the input ends or when the input contains a blank line. This can be coded as follows:
int main()
{
for (std::string line; std::getline(std::cin, line); )
{
if (line.empty())
{
std::cout << "Got blank line, quitting.\n";
return 0;
}
// process line
}
std::cout << "End of input, quitting.\n";
return 0;
}

getline causes infinite loop when redirecting file to standard input

The following code simply echoes the standard input to the standard output. If I run the program like so ./a.out, I can type anything and the program works fine. However, if I run it like this ./a.out < input.txt I get an infinite loop, regardless of the content of input.txt.
#include <iostream>
using namespace std;
int main() {
string input;
while (true) {
cout << "Type your input: ";
getline(cin, input);
cout << input << endl;
}
return 0;
}
What am I doing wrong?
EDIT: To clarify, I expect that after the input from the input file is finished, getline waits for more input from stdin. Instead, it continues to read when nothing is there.
You don't have a terminating condition for your loop: while (true) is an infinite loop in any case - that is, without a break/exit/etc. in the loop body.
I'm guessing that when using your program to echo stdin you end it by pressing Ctrl-C. Run your program using ./a.out, and type Ctrl-D (EOF): you'll also get an infinite loop.
Look over the docs for getline: use the return value to end your loop:
while (getline(cin, input))
Your loop has no terminating condition, be it a break, or right inside the while part. Instead, you probably want this:
while (getline(cin, input))
That will end when the input fails, most likely resulting from having reached EOF.
What you're doing wrong is that you ignore the result of an input operation, in this case getline.
You must never ignore the result of an input operation. It is always a programming error to do so. You cannot know or make assumptions about the state of external data, so you must always check whether an input operation succeeded. If it does not, then it is generally an error to access the purported input variable for reading, so you really need to check every time, and before accessing the result.
In the present case, std::getline returns a reference to the stream object, and you can evaluate the stream as a boolean. It evaluates as true if and only if the extraction succeeded; otherwise, you must not use the result (and presumably stop reading).
All in all, the code should go like this:
for (std::string line; std::getline(std::cin, line); )
{
// use "line"
}