You need to use the STL
streams library to do this stuff. The other stuff posted here will not help you much or is overly confusing for a beginner. Don't worry about nonsense like
scanf() and the like.
A
stream is C++'s way of handing character sequences -- whether it be a disk file (fstream) or a string (stringstream). The
getline() function allows you to read an entire text line from any stream into a
string variable.
In addition, all streams have (or can be given) operations to convert things (integers, floats, etc) to and from strings, including user-defined types. Understanding the STL streams is one of the first hurdles you need to overcome to "get it" in C++.
Given any stream, you can convert the
character sequence "2.9" into the floating-point
value 2.9. Here is an example using a "string stream":
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string s = "1.5";
cout << "I am going to convert the character sequence \"" << s << "\" to it's floating-point value.\n";
stringstream ss( s );
float f;
ss >> f;
if (f == 1.5) cout << "success: ";
else cout << "failure: ";
cout << "f == " << f << ".\n";
return 0;
}
|
Likewise, if you want to convert a
string which represents a number (such as "1.9" or "-3.7") to a floating-point value (such as a
double), you do it the same way.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
typedef vector <double> record_t;
typedef vector <record_t> data_t;
//-----------------------------------------------------------------------------
// Let's overload the stream input operator to read a list of CSV fields (which a CSV record).
// Remember, a record is a list of doubles separated by commas ','.
istream& operator >> ( istream& ins, record_t& record )
{
// make sure that the returned record contains only the stuff we read now
record.clear();
// read the entire line into a string (a CSV record is terminated by a newline)
string line;
getline( ins, line );
// now we'll use a stringstream to separate the fields out of the line
stringstream ss( line );
string field;
while (getline( ss, field, ',' ))
{
// for each field we wish to convert it to a double
// (since we require that the CSV contains nothing but floating-point values)
stringstream fs( field );
double f = 0.0; // (default value is 0.0)
fs >> f;
// add the newly-converted field to the end of the record
record.push_back( f );
}
// Now we have read a single line, converted into a list of fields, converted the fields
// from strings to doubles, and stored the results in the argument record, so
// we just return the argument stream as required for this kind of input overload function.
return ins;
}
//-----------------------------------------------------------------------------
// Let's likewise overload the stream input operator to read a list of CSV records.
// This time it is a little easier, just because we only need to worry about reading
// records, and not fields.
istream& operator >> ( istream& ins, data_t& data )
{
// make sure that the returned data only contains the CSV data we read here
data.clear();
// For every record we can read from the file, append it to our resulting data
record_t record;
while (ins >> record)
{
data.push_back( record );
}
// Again, return the argument stream as required for this kind of input stream overload.
return ins;
}
//-----------------------------------------------------------------------------
// Now to put it all to use.
int main()
{
// Here is the data we want.
data_t data;
// Here is the file containing the data. Read it into data.
ifstream infile( "test.txt" );
infile >> data;
// Complain if something went wrong.
if (!infile.eof())
{
cout << "Fooey!\n";
return 1;
}
infile.close();
// Otherwise, list some basic information about the file.
cout << "Your CSV file contains " << data.size() << " records.\n";
unsigned max_record_size = 0;
for (unsigned n = 0; n < data.size(); n++)
if (max_record_size < data[ n ].size())
max_record_size = data[ n ].size();
cout << "The largest record has " << max_record_size << " fields.\n";
cout << "The second field in the fourth record contains the value " << data[ 3 ][ 1 ] << ".\n";
cout << "Good bye!\n";
return 0;
}
|
I know it is a lot to digest at once. Just read it through a couple of times and look to see how
getline() is used with a
stringstream to separate individual fields out of each line of text (that is, out of each record of the CSV file). Then we use another
stringstream to convert the field to a
double.
Both examples I have given you here return you a bidimensional array which you can query, as I have now illustrated for you in this latest example.
Hope this helps. If you have further questions, please ask.