read comma delimited text file into an array

I need to read a comma delimted text file into an array.

The file contents will be like this: (85 rows actual by 9 columns)

1,2,4,4,0,30,15,7.6,5
1,2,4,5,0,0,0,0,0
1,3,2,1,0,40,29,14,9.6
1,3,2,2,0,0,19,9.4,6.2


I have no problem reading the file and seeing it with cout using this:

1
2
3
4
5
6
7
8
9
10
11
12
13
ifstream infile;
		infile.open ("test.txt");
		if (infile.is_open())
		{
			while (infile.good())
				cout << (char) infile.get();
			infile.close();
		}
		else
		{
			cout << "Error opening file";
		}
		return 0;


But I need to get it into an array called range without the commas.

Any ideas?

Thanks.

Read each record (line of the file) into a string. Then use a std::stringstream to split on commas.
1
2
3
4
5
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  vector <vector <string> > data;
  ifstream infile( "test.txt" );

  while (infile)
  {
    string s;
    if (!getline( infile, s )) break;

    istringstream ss( s );
    vector <string> record;

    while (ss)
    {
      string s;
      if (!getline( ss, s, ',' )) break;
      record.push_back( s );
    }

    data.push_back( record );
  }
  if (!infile.eof())
  {
    cerr << "Fooey!\n";
  }

Hope this helps.
u have to use getline instead of get method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ifstream infile;
int array[20];
int i=0;
char cNum[10] ;
                infile.open ("test.txt", ifstream::in);
                if (infile.is_open())
                {
                        while (infile.good())
                        {
                                infile.getline(cNum, 256, ',');
                                array[i]= atoi(cNum) ;
                                i++ ;
                        }
                        infile.close();
                }
                else
                {
                        cout << "Error opening file";
                }


which gives array of ints
I'm not sure you'll find this useful or not, but here is an old thread that defines stream iterators for inputting and outputting CSV files.

http://www.cplusplus.com/forum/general/7385/
My data file contains doubles, not integers or characters. One of the examples above butchers the data that contains a decimal, and neither store the file in a bidimensional array (85x9) that I can then query.

If it makes it easier, I could replace the commas with spaces or tabs.

??

Not bitching, just frustrated and searching for this I am so confused with scanf sscanf getline, ifstream, isstream, etc.



This may not be effecient but it is working:

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
double test_array[85][9];
	int r=0;

	ifstream indata;

	double num1;			// variable for input value
	double num2;			// variable for input value
	double num3;			// variable for input value
	double num4;			// variable for input value
	double num5;			// variable for input value
	double num6;			// variable for input value
	double num7;			// variable for input value
	double num8;			// variable for input value
	double num9;			// variable for input value

	indata.open("test.txt");	// opens the file

	if(!indata)			// file couldn't be opened
	{
		cerr << "Error: file could not be opened" << endl;
		exit(1);
	}
	
	indata >> num1 >> num2 >> num3 >> num4 >> num5 >> num6 >> num7 >> num8 >> num9;
	
	test_array[r][0] = num1;
	test_array[r][1] = num2;
	test_array[r][2] = num3;
	test_array[r][3] = num4;
	test_array[r][4] = num5;
	test_array[r][5] = num6;
	test_array[r][6] = num7;
	test_array[r][7] = num8;
	test_array[r][8] = num9;

	while (!indata.eof())		// keep reading until end-of-file
	{
		cout << "The next number is " << num1 << num2 << num3 << num4 << num5 << num6 << num7 << num8 << num9 << endl;
		indata >> num1 >> num2 >> num3 >> num4 >> num5 >> num6 >> num7 >> num8 >> num9;		// sets EOF flag if no value found

		r++;

		test_array[r][0] = num1;
		test_array[r][1] = num2;
		test_array[r][2] = num3;
		test_array[r][3] = num4;
		test_array[r][4] = num5;
		test_array[r][5] = num6;
		test_array[r][6] = num7;
		test_array[r][7] = num8;
		test_array[r][8] = num9;

	}

	indata.close();
	cout << "End-of-file reached.." << endl;
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.
Just in case you were interested in the csv_istream_iterator that I posted a link to, here is an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// insert the csv_istream_iterator here

int main( int argc, char* args[] )
{
    vector<float> linear;

    ifstream fin( "data.csv" );
    if( fin )
    {
        copy( csv_istream_iterator<float>( fin ),
              csv_istream_iterator<float>(),
              insert_iterator< vector<float> >( linear, linear.begin() ) );

        fin.close();
    }

    // linear now contains all floating point values in the comma-delimited
    // data file.  now dump them to the screen to verify:
    copy( linear.begin(), linear.end(), ostream_iterator<float>( cout, " " ) );

    return 0;
}


However, be aware that it requires the lines to also end with a comma (but not the last one). I tested it with this:

1,2,4,4,0,30,15,7.6,5,
1,2,4,5,0,0,0,0,0,
1,3,2,1,0,40,29,14,9.6,
1,3,2,2,0,0,19,9.4,6.2


Then all you would have to do is re-organize the linear data into a 2D container.
Thank you Duoas and moorecm this is great information and will help in my solution.

Thanks again.
Topic archived. No new replies allowed.