Reputation: 3829
I'm trying to read from a file, but the only thing I get on working is using getline().
The problem is that reading a whole line doesnt to the job for me.
My input file looks like this:
abc 10 20
bbb 10 30
ddd 40 20
when the first word in each line should be saved as a string, and both number afterwards as ints. The delimiter between the "words" in each line can be either a SPACE or a TAB.
So is the only solution is reading char by char? Or is there another solution?
Upvotes: 0
Views: 3309
Reputation: 5287
To read a file char-by-char, while preserving input text formatting, you can use the following:
if (in.is_open())
char c;
while (in.get(c)) {
std::cout << c;
}
}
where in
is an input stream of type std::ifstream
. You can open such a file, like so: std::ifstream in('myFile.txt');
If you don't mind formatting and would rather print all in one line, then you can follow Dietmar Kühl's advice.
Upvotes: 0
Reputation: 265
I'm not entirely sure what you are asking for.I suppose you want to read a text file and save a string and two ints (at each line) and printing each in a new line.If so try this:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string str;
int a,b;
ifstream file("test.txt");
if(file.is_open() == false)
{
cout << "Error: File can't be loaded" << endl;
exit(1);
}
while(1)
{
if(!file)
break;
file >> str;
file >> a;
file >> b;
cout << str << endl;
cout << a << endl;
cout << b << endl;
}
file.close(); // Close the file to prevent memory leaks
return 0;
}
Upvotes: 0
Reputation: 8143
The idea from @Dietmar of reading with operator>> for each single value is good, but you still have this problem with the endline.
However, you don't have to store the whole line in a temporary string, you can do it streamed and more efficiently with std::istream::ignore():
bool read_it(std::istream& in, std::string& s, int& a, int& b)
{
if (in >> s >> a >> b) // read the values
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // read the newline
return in;
}
Upvotes: 0
Reputation: 490693
For what it's worth, I agree with @Dietmar's answer -- but I'd probably go a bit further. From the looks of things, each line of input represents some sort of logical record. I'd probably create a class to represent that record type, and provide an overload of operator>>
for that class:
class my_data {
std::string name;
int val1, val2;
friend std::istream &operator>>(std::istream &is, my_data &m) {
std::string temp;
std::getline(is, temp);
std::istringstream buffer(temp);
buffer >> m.name >> m.val1 >> m.val2;
return is;
}
};
You might want to do a little extra logic to propagate a failed conversion in the stringstream out to the istream where you read the raw data.
In any case, with this in place, you can (for example) initialize a vector of objects directly from the stream:
std::vector<my_data> whatever(
(std::istream_iterator<my_data>(some_stream)),
(std::istream_iterator<my_data>());
Upvotes: 1
Reputation: 35464
Use fscanf, http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/
fscanf(stream, "%s %d %d", &s, &a, &b);
Upvotes: -1
Reputation: 154035
Supposedly you want something like this:
std::string s;
int v0, v1;
while (in >> s >> v0 >> v1) {
std::cout << "do something with s='" << s << "' v0=" << v0 << " v1=" << v1 << "\n";
}
This doesn't make sure that the values are all on one line, however. If you want to arrange for this you probably want to read a line using std::getline()
and then split this line up as above using an std::istringstream
.
Upvotes: 5
Reputation:
You could use getline()
and have a function return each successive character from the string it received from getline()
.
Upvotes: 1