I have written a code here which reads a input file line by line and creates a vector of vectors which I then use as a matrix, later on, in my homework. This is the code:
vector<vector<int>> inputMatrix;
string line;
while(!file.eof())
{
getline(file, line);
stringstream ss(line);
int num;
vector<int> temp;
while(ss >> num)
{
temp.push_back(num);
}
inputMatrix.push_back(temp);
}
However, some input files may contain non-integer values. I would like to integrate a input check feature for the matrix creation so that when there is a non-integer value in the input file, my program would quit.
How can I achieve this? Would it be possiple to write somewhere in this while loop or somewhere else in the code?
thank you very much in advance.
From cppreference.com:
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.
So you could simply add an if clause after your while loop:
while (ss >> num)
{
temp.push_back(num);
}
if (ss.fail()) // explicitly check for failbit
{
expected_integer_error();
}
I would like to integrate a input check feature for the matrix creation so that when there is a non-integer value in the input file, my program would quit.
The stringstream already does this check for you. You can simply test its state after the while loop. If it failed to parse a non integer value, the failbit will be set to true.
Here's a working demo (with some small improvements):
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
vector<vector<int>> inputMatrix;
string line;
while(getline(cin, line))
{
istringstream iss(line);
int num;
vector<int> temp;
while(iss >> num)
{
temp.push_back(num);
}
if(!iss) {
cout << "Bad input detected!" << endl;
return 1;
}
inputMatrix.push_back(temp);
}
return 0;
}
Input
12 13 46 3
42 2.6 5
Output
Bad input detected!
Related
enter image description here
i have used code ( if (!(cin >> arr[i])) ) to check if input from user is different with type int (like string, char) to stop reading into array (arr1), and then i can't use it twice with the second array (arr2), it didn't read input and go straight to cin.clear and return... Can you help me? Thank you very much from it^^
enter image description here
It seems you mean the following
#include <limits>
//...
if ( not ( std::cin >> arr[i] ) )
{
//...
std::cin.clear();
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
Below is the complete working example in 2 ways. The program given read as many integers as the user enters on the console. For example the user can enter 30 or 300 inputs some which may be integer types and other may be of some other types like string. The array/vector will add only integer type input inside itself as you require.
Solution 1: Using built in array
#include <iostream>
#include <sstream>
#include <string>
int main()
{
std::string line;
//in case of using array, size must be fixed and predetermined
int arr[4] = {0}; //all elements are initialzed to zero. Also you can choose array size according to your needs
int i = 0;//this variable will be used to add element into the array
int count = 0;
getline(std::cin, line);
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof()) {
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
arr[count] = i;
++count;
if(count>=4)
{
break;//break the loop so that you don't go beyond array size
}
}
}
//print out the elements of the array
for(int i: arr)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
Solution 1 can be checked here.
Solution 2: Using std::vector
#include <iostream>
#include <vector>
#include <sstream>
#include <string>
int main()
{
std::string line;
std::vector<int> vec;
int i = 0;//this variable will be used to add element into the array
getline(std::cin, line);
std::istringstream s(line);
//take input(from s to i) and then checks stream's eof flag status
while(s >> i || !s.eof())
{
//check if either failbit or badbit is set
if(s.fail())
{
//clear the error state to allow further operations on s
s.clear();
std::string temp;
s >> temp;
continue;
}
else
{
vec.push_back(i);
}
}
//print out the elements of the array
for(int i: vec)
{
std::cout<<"elem: "<<i<<std::endl;
}
return 0;
}
Solution 2 can be checked here.
Important Note
The advantage of using std::vector over built in array(in this case) is that you don't have know the size of the vector beforehand. That is std::vector's size is not fixed as opposed to built in arrays. So it is preferable because you don't know how many input the user is going to enter. std::vector can handle this accordingly and add only valid(integer type) input. But when using built in arrays you must know/specify the size of the array beforehand. This in turn means you must know beforehand how many integers the user is going to enter, which is not practical.
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'm having a bit of a problem with extracting data from a simple .txt file with the getline command.
The txt file is very simple: a column of 400 numbers. I use a vector to store them with the following code:
int i = 0;
string line;
vector <double> vec;
while (getline(input, line))
{
vec.push_back(i);
N++;
input >> vec[i];
i++;
}
It correctly creates a vector of 400 elements but first line of txt file is ignored (I end up with vec[0] = 2nd line of txt file instead of 1st) and 399th element is 399 instead of the 400th line of txt file.
I tried several other ways to extract this data but it was unsuccessful.
Thank you for your help!
EDIT:
I have edited the code according to some of the remarks:
vector <double> vec;
string line;
double num;
while (getline(input, line))
{
input >> num;
vec.push_back(num);
}
Unfortunately, it still skips the first line of my text file.
EDIT 2 --> SOLUTION:
Thanks to all of your remarks, I realized that I was doing something wrong when using both getline and input >> num;
Here is how the problem was solved:
double num;
vector <double> vec;
while (input >> num)
{
vec.push_back(num);
}
You can read the entire file into a vector just by passing std::istream_iterator to std::vector constructor, without loops:
std::vector<int> v{
std::istream_iterator<int>{input},
std::istream_iterator<int>{}
};
E.g.:
#include <iostream>
#include <iterator>
#include <vector>
#include <exception>
template<class T>
std::vector<T> parse_words_into_vector(std::istream& s) {
std::vector<T> result{
std::istream_iterator<T>{s},
std::istream_iterator<T>{}
};
if(!s.eof())
throw std::runtime_error("Failed to parse the entire file.");
return result;
}
int main() {
auto v = parse_words_into_vector<int>(std::cin);
std::cout << v.size() << '\n';
}
You loose the first line due to reading from the file once more - here:
while (getline(input, line))
// ^^^^^^^ Here you read the first line
{
input >> num;
// ^^^^^^^^ Here you will read the second line
You told you want a vector of doubles - like:
std::vector<double> vec;
So you should use std::stod to convert the line read by getline into a double. Like:
while (std::getline(input, line))
{
// Convert the text line (i.e. string) to a floating point number (i.e. double)
double tmp;
try
{
tmp = stod(line);
}
catch(std::invalid_argument)
{
// Illegal input
break;
}
catch(std::out_of_range)
{
// Illegal input
break;
}
vec.push_back(tmp);
}
Don't do input >> num; inside the loop.
If you really want to use input >> num; then you shall not use getline. That is - you can use either but not both.
Change your while loop like below:-
while (getline(input, line))
{
vec.push_back(line);
//N++;
//input >> vec[i];
//i++;
}
Also try with below option
do{
vec.push_back(i);
//N++;
//i++;
}while (input >> vec[i++]);
You are starting by putting 0 in vector in first iteration:
vec.push_back(i);
then after you read first line you read next string, but stream get pointer from file is already in different place, so you override this 0 and skip first value from stream. What is worse that is oddly converted to double:
input >> vec[i];
This way you will get wrong.
Try this:
while (std::getline(file, line)) {
//In c++11
vec.emplace_back(std::stod(line));
//In c++ 98, #include <stdlib.h> needed
//vec.push_back(atof(line.c_str()));
}
This assumes you will always have proper file.
I am a beginner and I'm trying to limit the user to input a single character only, I do aware of using cin.get(char) and it will only read one character from the input, but I don't want the other characters be left in buffer. Here is a sample of my code using EOF, but it doesn't seem to work.
#include <iostream>
#include <sstream>
using namespace std;
string line;
char category;
int main()
{
while (getline (cin, line))
{
if (line.size() == 1)
{
stringstream str(line);
if (str >> category)
{
if (str.eof())
break;
}
}
cout << "Please enter single character only\n";
}
}
I have used this for digit inputs and the eof works fine.
But for the char category the str.eof() seems to be false.
Can someone explain? Thanks in advance.
The eof flag is only set if you read try to read past the end of the stream. If str >> category read past the end of the stream, if (str >> category) would have evaluated false and not entered the loop to test (str.eof()). If there was one character on the line you would have to attempt to read two characters to trigger eof. Reading two characters is far more effort than testing the length of line to see how long it is.
while (getline (cin, line)) got the whole line from the console. If you don't consume it in the stringstream it doesn't matter, that stuff is gone is gone from cin when you loop back around in the while.
In fact, the stringstream isn't doing you any favours. Once you've confirmed the length of the line that was read, you can just use line[0].
#include <iostream>
using namespace std;
int main()
{
string line; // no point to these being global.
char category;
while (getline(cin, line))
{
if (line.size() == 1)
{
//do stuff with line[0];
}
else // need to put the fail case in an else or it runs every time.
// Not very helpful, an error message that prints when the error
// didn't happen.
{
cout << "Please enter single character only\n";
}
}
}
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).
}