I want to read a line of integers from the user. I'm not sure how to check to see if the input has ended. For example I want to be able to do something like
int x[MAX_SIZE];
int i = 0;
while(cin.hasNext())
{
cin >> x[++i];
}
Example input: 2 1 4 -6
how can I check to see if there's any more for cin to take?
Yo have to do the following
int temp;
vector<int> v;
while(cin>>temp){
v.push_back(temp);
}
also you can check for end of input using
if(cin.eof()){
//end of input reached
}
If cin is still interactive, then there's no notion of "no more input" because it will simply wait for the user to provide more input (unless the user has signaled EOF with Ctrl+D or Ctrl+Z as appropriate). If you want to process a line of data, then get a line from the user (with, say, getline) and then deal with that input (by extracting out of a stringstream or similar).
It is very straightforward. All you need to do is perform the extraction as the condition:
while (i < MAX_SIZE && std::cin >> x[i++])
if the extraction fails for any reason (no more characters left, invalid input, etc.) the loop will terminate and the failure will be represented in the stream state of the input stream.
Considering best practices, you shouldn't be using static C-arrays. You should be using the compile-time container std::array<T, N> (or std::vector<T> if the former is not supported).
Here is an example using std::vector. It also utilizes iterators which does away with having to explicitly create a copy of the input:
std::vector<int> v{ std::istream_iterator<int>{std::cin},
std::istream_iterator<int>{}};
You might want something like this:
int inp;
while(cin >> inp){
....
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
....
}
The while loop runs as long as the I/O is successful. Assuming you want to end input when the line of integers ends, you set the eofbit manually when a \n is encountered. This is checked with the condition if(cin.peek() == '\n'). When the condition is true the while loop terminates. In the example below, I demonstrate how to read a line of integers separated by space into a vector and then print it separated by space
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
int main(){
vector<int> coll;
int inp;
while(cin >> inp){
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
coll.push_back(inp);
}
copy(
coll.cbegin(),
coll.cend(),
ostream_iterator<int>(cout, " ")
);
cout << endl;
}
using fstream you can do something like this
ifstream ifile("input.txt");
while(!ifile.eof())
{
/* do something */
}
you can also use this
if(!ifile.is_open())
{
/* do something */
}
The idea is silimar with this code below so you can try :
int tmp;
while(cin >> tmp != NULL){ // C++ or while(scanf("%d", &tmp) != -1) {} for C
// do something
}
I usually detect end of cpp stream below:
while (cin.peek() != EOF) {
// To do your stuff...
// NOTE: peek() will set failbit when peeking end of stream and return EOF(-1).
}
Related
everyone, here is a function I wrote to read a user input which is a vector of double of unknown size, the input must terminate when 'enter' is pressed:
vector<double> read_array()
{
vector<double> array_in;
double el;
while (!cin.get())
{
cin >> el;
array_in.push_back(el);
}
return array_in;
}
To illustrate it consider the following code:
void init() // the function that calls the read_array function
{
cout << "Enter array X: " << endl;
vector<double> X = read_array();
int l = X.size();
cout << l << endl;
}
A typical input when promted is:
1(space)2(space)3(space)4(enter)
When enter is pressed, the input terminates, and the variable 'l' is initialised but is equal to 0
However, when the enter key is pressed, the array size is 0. Debugging it makes it look like it never makes it into the loop like that.
The same routine works well if the input value is not an array.
Thanks to everyone in advance!
I don't know what you hope std::cin.get() does but based on your comment it seems you hope that it somehow deals with end of lines: it doesn't. It simply reads the next character which is unlikely to do you much good. In particular, if the character is anything but '\0' negating it will result in the boolean value false. That said, the loop should in principle work unless you only input a single digit numeric value followed (possibly after space) by a non-digit or the end of the input.
The easiest approach to deal with line-based input is to read the line into a std::string using std::getline() and then to parse the line using std::istringstream:
std::vector<double> read_array() {
std::vector<double> result;
if (std::string line; std::getline(std::cin, line)) {
std::istringstream lin(line);
for (double tmp; std::cin >> tmp; ) {
result.push_back(tmp);
}
}
return result;
}
As std::cin is only involved while reading lines, std::cin.fail() won't be set when parsing doubles fails. That is, you can read multiple lines with arrays of doubles, each of which can also be empty.
If you don't want to read an auxiliary line, you'll need to understand a bit more about how formatted input in C++ works: it starts off skipping whitespace. As newlines are whitespace you need to rather read the whitespace yourself and stop if it happens to be a newline or non-whitespace. I'd use a function doing this skipping which returns false if it reached a newline (which is still extracted):
bool skip_non_nl_ws(std::istream& in) {
for (int c; std::isspace(c = in.peek()); std::cin.ignore()) {
if (c == '\n') {
return false;
}
}
return true;
}
std::vector<double> read_array() {
std::vector<double> result;
for (double tmp; skip_non_nl_ws(std::cin) && std::cin >> result); ) {
result.push_back(tmp);
}
return result;
}
This approach has a similar property that std::ios_base::failbit won't be set. However, if any of the characters on a line can't be parsed as double the bit will set. That way you can detect input errors. The approach using std::getline() will just go on to the next line.
I want to read a line of integers from the user. I'm not sure how to check to see if the input has ended. For example I want to be able to do something like
int x[MAX_SIZE];
int i = 0;
while(cin.hasNext())
{
cin >> x[++i];
}
Example input: 2 1 4 -6
how can I check to see if there's any more for cin to take?
Yo have to do the following
int temp;
vector<int> v;
while(cin>>temp){
v.push_back(temp);
}
also you can check for end of input using
if(cin.eof()){
//end of input reached
}
If cin is still interactive, then there's no notion of "no more input" because it will simply wait for the user to provide more input (unless the user has signaled EOF with Ctrl+D or Ctrl+Z as appropriate). If you want to process a line of data, then get a line from the user (with, say, getline) and then deal with that input (by extracting out of a stringstream or similar).
It is very straightforward. All you need to do is perform the extraction as the condition:
while (i < MAX_SIZE && std::cin >> x[i++])
if the extraction fails for any reason (no more characters left, invalid input, etc.) the loop will terminate and the failure will be represented in the stream state of the input stream.
Considering best practices, you shouldn't be using static C-arrays. You should be using the compile-time container std::array<T, N> (or std::vector<T> if the former is not supported).
Here is an example using std::vector. It also utilizes iterators which does away with having to explicitly create a copy of the input:
std::vector<int> v{ std::istream_iterator<int>{std::cin},
std::istream_iterator<int>{}};
You might want something like this:
int inp;
while(cin >> inp){
....
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
....
}
The while loop runs as long as the I/O is successful. Assuming you want to end input when the line of integers ends, you set the eofbit manually when a \n is encountered. This is checked with the condition if(cin.peek() == '\n'). When the condition is true the while loop terminates. In the example below, I demonstrate how to read a line of integers separated by space into a vector and then print it separated by space
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
using namespace std;
int main(){
vector<int> coll;
int inp;
while(cin >> inp){
if(cin.peek() == '\n')
cin.clear(ios::eofbit);
coll.push_back(inp);
}
copy(
coll.cbegin(),
coll.cend(),
ostream_iterator<int>(cout, " ")
);
cout << endl;
}
using fstream you can do something like this
ifstream ifile("input.txt");
while(!ifile.eof())
{
/* do something */
}
you can also use this
if(!ifile.is_open())
{
/* do something */
}
The idea is silimar with this code below so you can try :
int tmp;
while(cin >> tmp != NULL){ // C++ or while(scanf("%d", &tmp) != -1) {} for C
// do something
}
I usually detect end of cpp stream below:
while (cin.peek() != EOF) {
// To do your stuff...
// NOTE: peek() will set failbit when peeking end of stream and return EOF(-1).
}
I know how to do this in C but have no idea for a C++ solution. I want the following to be fail safe, but after providing a string or even a char to the input, the program hangs. How to read input stream including \n to free it?
int main() {
int num;
do {
std::cin.clear();
std::cin >> num;
while ( std::cin.get() != '\n' );
} while ( !std::cin.good() || num > 5 );
return 0;
}
Once the stream is in an error state all read operations will fail. This means that, if the cin >> num read fails, the loop with the get() calls will never end: all those get()s will fail. Skipping to the end of the line can only be done after clearing the error state.
To build on top of R. Martinho Fernandes answer, here is a possible C++ alternative to your code:
std::string num;
std::getline(std::cin, num);
// Arbitrary logic, e.g.: remove non digit characters from num
num.erase(std::remove_if(num.begin(), num.end(),
std::not1(std::ptr_fun((int(*)(int))std::isdigit))), num.end());
std::stringstream ss(num);
ss >> n;
The std::getline function extracts characters from cin and stores to num. It also extracts and discards the delimiter at the end of the input (you can specify your own delimiter or \n will be used).
The string::erase function removes all characters but digits from the num string, using std::remove_if with a negative std::isdigit predicate.
The string is then represented as an integer using a std::stringstream (a boost::lexical_cast would have worked as well)
The logic here implemented by the erase function can be any other logic, but this code is probably much simpler to read than the one included in the question.
I would approach it using getline(cin,num) and then catch any fails using cin.fail(). I usually use cin.fail() with ints but theoretically should work with strings and chars also, for example :
string num;
getline(cin,num);
if(cin.fail())
{
cin.clear();
cin.ignore();
}
One way would be to check the state after every input and throw an exception if that happens
for example:
#include<iostream>
using namespace std;
int main(){
int a;
cout<<"Enter a number: ";
cin>>a;
//If a non number is entered, the stream goes into a fail state
try
{
if(cin.fail()){
throw 0;
cin.clear();
cin.ignore();
}
}
catch(int){
cin.clear();
cin.ignore();
}
return 0;
}
After that you can continue with whatever code you wish
To clear input stream, use cin.sync() .
no need to use cin.clear() or cin.ignore().
I used "cin" to read words from input stream, which like
int main( ){
string word;
while (cin >> word){
//do sth on the input word
}
// perform some other operations
}
The code structure is something like the above one. It is compilable. During the execution, I keep inputting something like
aa bb cc dd
My question is how to end this input? In other words, suppose the textfile is just "aa bb cc dd". But I do not know how to let the program know that the file ends.
Your code is correct. If you were interactively inputting, you would need to send a EOF character, such as CTRL-D.
This EOF character isn't needed when you are reading in a file. This is because once you hit the end of your input stream, there is nothing left to "cin"(because the stream is now closed), thus the while loop exits.
As others already answer this question, I would like add this important point:
Since Ctrl-Z on Windows (and Ctrl-D on unix systems) causes EOF to reach, and you exit from the while loop, but outside the while loop you cannot read further input, since the EOF is already reached.
So to enable reading using cin again, you need to clear eof flag, and all other failure flags, as shown below:
cin.clear();
After doing this, you can start reading input using cin once again!
int main() {
string word;
while (cin >> word) {
// do something on the input word.
if (foo)
break;
}
// perform some other operations.
}
Hit Ctrl-Z (Ctrl-D on *nix systems) and hit enter. That sends an EOF and invalidates the stream.
cin >> some_variable_or_manipulator will always evaluate to a reference to cin. If you want to check and see if there is more input still to read, you need to do something like this:
int main( ){
string word;
while (cin.good()){
cin >> word;
//do sth on the input word
}
// perform some other operations
}
This checks the stream's goodbit, which is set to true when none of eofbit, failbit, or badbit are set. If there is an error reading, or the stream received an EOF character (from reaching the end of a file or from the user at the keyboard pressing CTRL+D), cin.good() will return false, and break you out of the loop.
I guess you want to jump out at the end of file.
You can get the value of basic_ios::eof , it returns true at the end of stream.
Take the input from a file. Then you will find that the while loop terminates when your program stops taking input.
Actually cin stops taking input when it finds an EOF marker. Each input file ends with this EOF marker. When this EOF marker is encountered by operator>> it modifies the value of internal flag eofbit into false and consequently the while loop stops.
It helps me to terminate loop by hitting ENTER.
int main() {
string word;
while(getline(cin,word) && s.compare("\0") != 0) {
//do sth on the input word
}
// perform some other operations
}
You can make a check for a special word in input.
F.e. "stop":
int main( ){
string word;
while (cin >> word){
if(word == "stop")
break;
//do sth on the input word
}
// perform some other operations
}
you can try this
string word;
vector<string> words;
while (cin >> word) {
words.push_back(word);
if (cin.get() == '\n')
break;
}
in this way, you don't have to end with CTRL+D(Z). program will quit while sentence end
your program doesn't take in count white spaces. make difference between cin and getline...
here is an example with a trick: the program get input and prints output until you hit twice Enter to quit:
#include <iostream>
#include <string>
using namespace std;
int main(){
char c = '\0';
string word;
int nReturn = 0;
cout << "Hit Enter twice to quit\n\n";
while (cin.peek())
{
cin.get(c);
if(nReturn > 1)
break;
if('\n' == c)
nReturn++;
else
nReturn = 0;
word += c;
cout << word;
word = "";
}
cout << endl;
return 0;
}
I am reading a std::istream and I need to verify without extracting characters that:
The stream is not "empty", i.e. that trying to read a char will not result in an fail state (solved by using peek() member function and checking fail state, then setting back to original state)
That among the characters left there is at least one which is not a space, a tab or a newline char.
The reason for this is, is that I am reading text files containing say one int per line, and sometimes there may be extra spaces / new-lines at the end of the file and this causes issues when I try get back the data from the file to a vector of int.
A peek(int n) would probably do what I need but I am stuck with its implementation.
I know I could just read istream like:
while (myInt << myIstream) {…} //Will fail when I am at the end
but the same check would fail for a number of different conditions (say I have something which is not an int on some line) and being able to differentiate between the two reading errors (unexpected thing, nothing left) would help me to write more robust code, as I could write:
while (something_left(myIstream)) {
myInt << myIstream;
if (myStream.fail()) {…} //Horrible things happened
}
Thank you!
There is a function called ws which eats whitespace. Perhaps you could call that after each read. If that hits eof, then you know you've got a normal termination. If it doesn't and the next read doesn't produce a valid int, then you know you've got garbage in your file. Maybe something like:
#include <fstream>
#include <iostream>
int main()
{
std::ifstream infile("test.dat");
while (infile)
{
int i;
infile >> i;
if (!infile.fail())
std::cout << i << '\n';
else
std::cout << "garbage\n";
ws(infile);
}
}
this is what I did to skip whitespace/detect EOF before the actual input:
char c;
if (!(cin >> c)) //skip whitespace
return false; // EOF or other error
cin.unget();
This is independent of what data you are going to read.
This code relies on the skipws manipulator being set by default for standard streams, but it can be set manually cin >> skipw >> c;
And simple
for(;;){
if(!(myIstream >> myInt)){
if(myIstream.eof()) {
//end of file
}else{
//not an integer
}
}
// Do something with myInt
}
does not work? Why you need to know if there are numbers left?
Edit Changed to Ben's proposition.
The usual way to handle this situation is not to avoid reading from the stream, but to put back characters, which have been read, if needed:
int get_int(std::istream& in)
{
int n = 0;
while(true) {
if (in >> n)
return n;
clean_input(in);
}
}
void clean_input(std::istream& in)
{
if (in.fail()) {
in.clear();
// throw away (skip) pending characters in input
// which are non-digits
char ch;
while (in >> ch) {
if (isdigit(ch)) {
// stuff digit back into the stream
in.unget();
return;
}
}
}
error("No input"); // eof or bad
}