I am trying to read a string of three number using sstream but when I try to print them, I am getting a wrong output with four numbers.
Code:
#include <iostream>
#include <sstream>
using namespace std;
int main() {
string a("1 2 3");
istringstream my_stream(a);
int n;
while(my_stream) {
my_stream >> n;
cout << n << "\n";
}
}
Output:
1
2
3
3
Why I get four numbers in the output compared to three numbers in input string?
Here
while ( my_stream )
my_stream is convertible to bool and returns true if there's no I/O error.
See: https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool
So, after the last reading, there's no I/O error yet, so it iterates again and there's an error and nothing is read into n in this statement:
my_stream >> n;
And, std::cout prints the last extracted value again i.e. 3.
The solution could be to directly check I/O error after reading in while (preferred):
while ( my_stream >> n )
{
std::cout << n << '\n';
}
or, print only if the reading is successful using an if:
while ( my_stream )
{
if ( my_stream >> n ) // print if there's no I/O error
{
std::cout << n << '\n';
}
}
Example (live):
#include <iostream>
#include <sstream>
int main()
{
std::string a { "1 2 3" };
std::istringstream iss{ a };
int n {0};
while ( iss >> n )
{
std::cout << n << '\n';
}
return 0;
}
Output:
1
2
3
Relevant: Why is "using namespace std;" considered bad practice?
You are printing the data before checking if readings are successful.
while(my_stream) {
my_stream >> n;
should be
while(my_stream >> n) {
Related (doesn't seem duplicate because eof() isn't used here):
c++ - Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? - Stack Overflow
Related
I would like to print integer values in a file by reading it.
The code:
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while(trainfile >> temp)
cout << temp << " ";
trainfile.close();
dfg.txt: 1 2 we er rf 5
output: 1 2
The problem is that it does not print 5.
Read to a temporary string first and then use std::stoi to try to parse an integer from it, and if it succeeds, output it:
std::string temp;
while(trainfile >> temp) {
try {
std::cout << std::stoi(temp) << " ";
}
catch(const std::invalid_argument&) {
// not a valid number
}
}
while(trainfile >> temp)
cout << temp << " ";
The above sets the failbit on trainfile on encountering any character that isn't whitespace or a digit. That terminates the loop. This is one reason I tend not to use formatted I/O that can fail on a input stream. I find it better to read text as text (not numbers) and then process the string that was just read. For example, see zenith's answer.
If you insist on doing everything from the input stream, you'll need an outer loop that clears the stream's failbit. For example,
while (! std::cin.eof())
{
while (std::cin >> temp)
{
std::cout << temp << " ";
}
std::cin.clear();
std::cin.ignore();
}
Given an input file containing 1 2 we er rf 5, the above will print 1 2 5. If the input file contains 1 2 abc345def 6, the above will print 1 2 345 6. Note that zenith's approach will print 1 2 6. Whether that 345 sandwiched between abc and def counts as an integer is up to you.
I'd recommend using zenith's solution over mine.
Update:
The above interprets abc345def as representing the integer 345. Both Zenith's solution and the above interpret 345def as representing the integer 345. To me, both abc345def and 345def should be rejected as representing an integer. So should 6.1 , but there's nothing wrong with 0x abc345def. There's nice tool in the C standard library, strtol, that nicely parses integers. It also indicates what made the parse stop. For a valid integer, it should stop at the end of the input string. With that,
#include <iostream>
#include < fstream>
#include <string>
#include <cstdlib>
int main ()
{
std::ifstream trainfile("dfg.txt");
if (!trainfile)
{
std::cerr << "Cannot open file!\n";
exit(1);
}
std::string s;
while(trainfile >> s)
{
char* end;
long num = std::strtol (s.data(), &end, 0);
if (!*end)
{
std::cout << num << " ";
}
}
trainfile.close();
std::cout << "\n";
}
string temp;
if( '0' <= temp[0] && temp[0]<='9' )
cout << temp << " ";
it will work i suppose.
Here is another way you can consider-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ifstream trainname("dfg.txt",ios::in);
string temp;
getline(trainname,temp);
stringstream str;
str<<temp;
int extract_int;
while(getline(str, temp,' '))
{
if(stringstream(temp)>>extract_int)
cout<<extract_int<<" ";
}
return 0;
}
Or according to David Hammen's answer, you can solve it the following way-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while (!trainfile.eof())
{
while (trainfile>>temp)
cout<<temp<< " ";
trainfile.clear();
trainfile.ignore();
}
return 0;
}
I have a text file with words and integers. The task is to read only integers from it ignore words. This is an example of such file:
seven 7
I declare an int variable and try to read the ifstream into it (echoing the state of ifstream):
#include <iostream>
#include <fstream>
int main() {
int num = -1;
std::ifstream ifs("file.in");
std::cout << ifs << std::endl;
ifs >> num;
std::cout << ifs << std::endl;
if ( ifs.fail() )
ifs.clear();
std::cout << ifs << std::endl;
ifs >> num;
std::cout << ifs << std::endl;
std::cout << num << std::endl;
return 0;
}
To which I get an output:
1
0
1
0
-1
It's obvious that 'ifs' fails when trying to read a word into an int variable. My question is why does it fail the second time after being cleared?
The first failure doesn't advance the stream position, so the second tries again with exactly the same results. You'll need to skip over the unwanted word, either reading it into a string or using ignore.
I was in a programming competition yesterday and we had to read in input of the form
n
a1 a2 ... an
m
b1 b2 ... bm
...
where the first line says how many inputs there are, and the next line contains that many inputs (and all inputs are integers).
I know if each line has the same number of inputs (say 3), we can write something like
while (true) {
cin >> a1 >> a2 >> a3;
if (end of file)
break;
}
But how do you do it when each line can have a different number of inputs?
Here's a simple take using just standard libraries:
#include <vector> // for vector
#include <iostream> // for cout/cin, streamsize
#include <sstream> // for istringstream
#include <algorithm> // for copy, copy_n
#include <iterator> // for istream_iterator<>, ostream_iterator<>
#include <limits> // for numeric_limits
int main()
{
std::vector<std::vector<double>> contents;
int number;
while (std::cin >> number)
{
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip eol
std::string line;
std::getline(std::cin, line);
if (std::cin)
{
contents.emplace_back(number);
std::istringstream iss(line);
std::copy_n(std::istream_iterator<double>(iss), number, contents.back().begin());
}
else
{
return 255;
}
}
if (!std::cin.eof())
std::cout << "Warning: end of file not reached\n";
for (auto& row : contents)
{
std::copy(row.begin(), row.end(), std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
}
See it live on Coliru: input
5
1 2 3 4 5
7
6 7 8 9 10 11 12
Output:
1 2 3 4 5
6 7 8 9 10 11 12
you can do it this way
#include<vector>
...
...
std::vector<sometype> a;
sometype b;
std::cin >> b;
while(std::cin)
{
a.push_back(b);
std::cin >> b;
}
you can input any number of items and when you are finished send in the EOF signal.
Your Algorithm will look something like this:
1. read the 'number' of inputs, say n1
2. set up a loop to read the n1 inputs
3. check if the user has more inputs to give
if YES repeat the steps 1,2 and 3 till all inputs are taken and stored.
else move on...
You can use a for or while loop and store the inputs into an array.
Hope this helps!
Because people were complaining how I called my first answer "a simple take", here's a proper version using Boost Spirit:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
int main()
{
typedef std::vector<std::vector<double>> data_t;
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It first(std::cin), last;
bool ok;
data_t contents;
{
using namespace boost::spirit::qi;
static rule<It, data_t(), blank_type, locals<int>> file;
static rule<It, std::vector<double>(int number), blank_type> row;
_a_type number; // friendly alias
file %= -(omit [int_[number=_1]] > eol > row(number)) % eol;
row = repeat(_r1) [ double_ ];
ok = phrase_parse(first, last, file, blank, contents);
}
if (ok) for (auto& row : contents)
{
std::copy(row.begin(), row.end(), std::ostream_iterator<double>(std::cout," "));
std::cout << "\n";
}
if (first!=last)
std::cout << "Warning: end of file not reached, remaining unparsed: '" << std::string(first, last) << "'\n";
}
It's obviously far superior
it uses far fewer include lines :)
it takes ~10x as long to compile (with no optimizations), another 16% longer with optimizations
it requires about 5 years of study in meta-programming to grok it (joking, the spirit docs/tutorials are quite ok)
on the serious account: it is much more flexible
can be extended to parse other structural elements, more complicated
can implement semantics on the fly
will parse NaN and +/-infinity correctly
etc.
See it Live on Coliru as well
Given the format you are specifying, here is what I would do.
for (int n; std::cin >> n; )
{
if (n == 0) // Test for end of input
break;
for (int i = 0; i != n; ++i)
{
int x;
std::cin >> x;
if (!std::cin)
break;
// Valid input x. Now do something with x like
// v.push_back(x) where v is some vector of ints
}
}
// Did we succeed?
if (!std::cin)
{
// Something went bad.
std::cerr << "Error reading input" << std::endl;
return EXIT_FAILURE;
}
Simple, use a for loop and array.
int a[MAX]; // programming problems usually specify a max size
for(i=0;i<n;i++)
cin>>a[i];
A simple solution using arrays and dynamic memory allocation for taking variable number of inputs of a predefined type.
#include<iostream>
using namespace std;
int main(){
int n;
cout<<"Enter the number of elements"<<endl;
cin>>n;
int *c=new int[n];
for(int k=0;k<n;k++)
cin>>c[k];
delete c;
}
I have a text file with 2 columns and many rows. each column is separated by spaces. i need to read them to a 2D array for further calculations.
my data file looks like
0.5 0.479425539
1 0.841470985
1.5 0.997494987
2 0.909297427
2.5 0.598472144
3 0.141120008
3.5 -0.350783228
4 -0.756802495
4.5 -0.977530118
5 -0.958924275
And my feeble attempt is
#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <ctype.h>
using namespace std;
int main () {
char line,element;
std::ifstream myfile ("C:\\Users\\g\\Desktop\\test.txt");
if (myfile.is_open())
{
while ( myfile.good() )
{
getline(myfile,line);
cout << line<<endl;
_getch();
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
The problem is I'm not able to read them correctly.... its either reading the whole line... if I specify the delimiter as 'space' then, its not reading the next row.
Pls point out whats wrong. and what should i do to store the data into 2d array for further calculations.
Thank you
#include <fstream>
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
int main(int argc, char** argv) {
std::ifstream f(argv[1]);
std::string l;
std::vector<std::vector<double> > rows;
while(std::getline(f, l)) {
std::stringstream s(l);
double d1;
double d2;
if(s >> d1 >> d2) {
std::vector<double> row;
row.push_back(d1);
row.push_back(d2);
rows.push_back(row);
}
}
for(int i = 0; i < rows.size(); ++i)
std::cout << rows[i][0] << " " << rows[i][1] << '\n';
}
The last for loop shows how to use the values in the "array". The variable rows is strictly speaking not an array, but a vector of vectors. However, a vector is much safer than c-style arrays, and allows access to its elements using [].
[As I posted this I saw a very similar program posted as a response. I wrote mine independently.]
You can read the whole line into a std::string, then use std::istringstream to extract the values from the line.
A complete working program:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
int main()
{
std::ifstream file("C:\\Users\\g\\Desktop\\test.txt");
std::string line;
// Read a line of input from the file
while (std::getline(file, line))
{
// `istringstream` behaves like a normal input stream
// but can be initialized from a string
std::istringstream iss(line);
float value;
// The input operator `>>` returns the stream
// And streams can be used as a boolean value
// A stream is "true" as long as everything is okay
while (iss >> value)
{
std::cout << "Value = " << value << '\t';
}
// Flush the standard output stream and print a newline
std::cout << std::endl;
}
}
Given the contents in the file being as in the question, the first three lines of output should be:
Value = 0.5 Value = 0.479425539
Value = 1 Value = 0.841470985
Value = 1.5 Value = 0.997494987
For a 2d-array, I would use a std::vector of std::array:
#include <vector>
#include <array>
...
std::vector<std::array<float, 2>> array;
...
float value1, value2;
if (iss >> value1 >> value2)
{
std::cout << "Values = " << value1 << ", " << value2;
array.emplace_back(std::array<int, 2>{{value1, value2}});
}
Now the first line values are array[0][0] and array[0][1], and the last lines values are array[array.size() - 1][0] and array[array.size() - 1][1].
As C++ has evolved over the years, below is a Modern C++ version.
It uses auto where possible
Uses std::pair to hold 2 values (A std::pair is a specific case of a std::tuple with two elements)
Does not close file (destructor does that at end of block)
Does not read line by line, as the stream uses <space> and <enter> as delimiters
The variables have meaningful names, so the program "reads" easily,
Uses a range for loop to output the data.
Doesn't bring the whole std namespace into the code - Why is “using namespace std” considered bad practice?
.
#include <fstream>
#include <iostream>
#include <vector>
#include <utility>
int main( int argc, char** argv )
{
if ( argc < 1 )
return -1;
const auto fileName = argv[ 1 ];
std::ifstream fileToRead( fileName );
typedef std::pair< double, double > DoublesPair;
std::vector< DoublesPair > rowsOfDoublesPair;
DoublesPair doublePairFromFile;
while ( fileToRead >> doublePairFromFile.first >> doublePairFromFile.second )
{
rowsOfDoublesPair.push_back( doublePairFromFile );
}
for ( const auto row : rowsOfDoublesPair )
std::cout << row.first << " " << row.second << '\n';
}
Consider the following C++ program:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main (void)
{
string l1, l2;
int n1, n2;
stringstream ss;
getline(cin, l1);
getline(cin, l2);
cerr << l1 << " " << l2 << endl;
ss.str(l1);
ss >> n1;
ss.str(l2);
ss >> n2;
cerr << n1 << " " << n2 << endl;
return 0;
}
Sample input:
2
3
Corresponding output:
2 3
2 0
But I was expecting:
2 3
2 3
If I insert a call ss.clear() before the second call to ss.str(), the output is what I expected. Is this really necessary? And why?
It is necessary, because the first input from the stringstring hits end of file. Calling str() does not clear any error flags that are already set on the stringstream.
ss.str(l1);
ss >> n1; // Reads the entire buffer, hits the end of buffer and sets eof flag
ss.str(l2); // Sets the string, but does not clear error flags
ss >> n2; // Fails, due to at EOF
You can use clear before the second str() or after, just as long as it's before you attempt to read more data.