Reputation: 3
So, i'm trying to write a program that can read data from a file. The file consists of integers, chars and doubles. And i have to be able to assign them to different variables for further calculation (this is actually just a part of a bigger program). I've searched around the web (here also), and i've seen different solutions. stringstream, vectors and whatnot. The one i got furthest with, was using "skipws" when reading. But i can't seem to read the integers properly.
I would prefer a solution that requires the use of as few methods (streams, gets etc) as possible. But if i need more, i can live with it.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace::std;
int main()
{
int j = 0, kill = 0, i;
char initials[10];
int results[10];
double avg;
ifstream read("P1.txt");
if (!read) //test to see if file can be opened.
{
cerr << "Error" << endl;
exit(1);
}
while(kill != 1) //kill = 1 same as eof. Just my weird way of coding.
{
switch (j)
{
case 0: //read the first line of data, which is the chars.
read >> skipws >> initials;
j++;
break;
case 1: //read the second line of data, which is 10 integers and whitespace
for (i=0;i<10;i++)
read >> skipws >> results[i];
j++;
break;
case 2: //read the last line which is a single double.
read >> skipws >> avg;
j++;
break;
case 3: //check for end of file.
if(read.eof() == 0)
kill = 1;
break;
}
}
//the 3 lines below are just writing the contents of the file to the prompt.
//It's to check that values are stored correctly for further use.
cout << initials << endl;
cout << results << endl;
cout << avg << endl;
return 0;
}
I know exactly what y input file, "P1.txt", will look like, because i create it myself in another part of the program. It looks like this:
ccs
2 4 5 3 1 4 6 1 1 1
2.8
Those 3 lines gives me the initials of a player, his results of 10 games and his average score. In short, the data of one player. In the final program, i need to be able to read values for maybe 10 players.
I'm expecting the 3 cout lines in the end to show this:
ccs
2453146111
2.8
Now, this is as far as i have gotten. If i declare results[10] as char i can get this in my console:
ccs
2453146111ccs
2.8
If i declare it as int i get this
ccs
0x7fff5fbff6c0
2.8
Obviously, i can see that values aren't stored properly and something is out of hand, but i need another persons eyes on this. I'm out of clues.
I know this is a messy way to do it and that it can be done in less space, but i'm new to C++, so this made sense to me, and made it fairly easy for me to locate my mistakes, until now.
I tried to explain it as well as i could. This is my first post here, so please tell me if you need more info.
Thanks in advance!! Chris.
Upvotes: 0
Views: 2456
Reputation: 11130
This problem is made significantly easier by the fact that your data takes a known format. Don't let this go to waste.
string initials;
vector<int> r(NUM_SCORES);
double avg;
Now to get the data:
ifstream infile;
infile.open(...);
while(infile >> initials){ // i.e. "while there's another player"
for(int i=0; i<r.size(); i++) infile >> r.at(i);
infile >> avg;
}
Job done.
cout << "Player " << intials << " scored:" << endl;
for(int i=0; i<r.size(); i++) cout << r.at(i);
cout << endl << "giving him an average of " << avg << endl;
Upvotes: 1
Reputation: 526
Don't re-invent the wheel, you can use Boost::tokenizer to tokenize the string and use Lexical_cast to convert strings to numbers.
If you want to use plain c you can use strtok for tokenizing the string
Upvotes: 1
Reputation: 264
Also when you read in a value from a file, it is not an "int" data type. you cannot just push it back to a array of int's and expect it to work, you will probably need to convert it to an int using something like std::stoi
Upvotes: 1
Reputation: 11911
I would suggest the following if you are using C++:
stringstream
sstringstream
stringstream
is called ss
):
ss >> c
(with c
your character)ss >> i
(with i
your integer)ss >> d
(with d
your double)Some code:
string s[3] = {"ccs",
"2 4 5 3 1 4 6 1 1 1",
"2.8"
};
stringstream ss[3];
/*
Open file, get the first line into s[0], second into s[1] and third into s[2]
*/
ss[0] << s[0];
ss[1] << s[1];
ss[2] << s[2];
char c;
int i;
double d;
vector<char> initials;
vector<int> scores;
vector<double> averages;
while (ss[0] >> c) {
cout << c << " ";
initials.push_back(c);
}
cout << endl;
while (ss[1] >> i) {
cout << i << " ";
scores.push_back(i);
}
cout << endl;
while (ss[2] >> d) {
cout << d << " ";
averages.push_back(d);
}
cout << endl;
Upvotes: 1
Reputation: 467
when results is int[10] and you make cout << results << endl it will print the array memory address you should make loop that print result[i] in each iteration.
for(i=0;i<10;i++){
cout<< result[i];
}
and it will give the correct result
Upvotes: 1