Reading a Tab-Delimited Spreadsheet File

Say that I wanted to read the numbers off a tab-delimited spreadsheet file, such as from SomeFile.txt:
1
2
3
4
5
1    1
2    4
3    9
4    16
5    25


How could I write this?

I know how to use ifstream.getline() to get the text in the line, but I'm not sure how to turn a string that says "453" into an integer value of 453.

I also don't know if there might be a more efficient way of doing it then reading a string and turning it into a number.

The code that I have so far would be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <fstream>

using namespace std;

void main(){
    char lineText[100];
    ifstream in("C:\\SomeFile.text");

    while(!in.eof()){
        in.getline(lineText, 99);
        //How do I get the numbers out of the line?
    }
    in.close();
    return;
}
Last edited on
1
2
3
4
5
6
ifstream f( "filename.txt" );
int i;
while( f >> i )
{
    // do something with i
}
Does it just skip whatever it encounters that's not an integer?
Just read them as numbers. Something like:

1
2
3
4
5
6
7
8
9
std::ifstream ifs("SomeFile.txt");

std::vector<int> vec;

int n;
while(ifs >> n)
{
	vec.push_back(n);
}

Of course, you should read them into an appropriate structure, the vector is just an example.
operator>> skips whitespace.
What happens if it sees, say, the letter 'a' instead of an integer?

For example, if the file was actually:
1
2
3
4
5
1    1    a
2    4
3    9
4    16
5    25
Last edited on
I believe it will be read as an integer. You could read each character into a char, determine whether they're numbers by using isdigit(), and put them back into the stream by using ifstream.unget(), but that might be overkill.
Last edited on
If input validation is necessary, I would use an approach similar to this one (consider it pseudo-code):

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
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;

typedef std::pair<int,int> int_pair;

int main()
{
  ifstream file("file.txt");
  try
  {
    vector<int_pair> content;
    foreach(line,file)
    {
      vector<string> parts;
      split(parts,line,is_any_of("\t"));
      if (parts.size()!=2)throw 0;
      content.push_back(int_pair(lexical_cast<int>(parts[0]),lexical_cast<int>(parts[1])));
    }
  }
  catch(...)
  {
    cout << "Invalid input file format." << endl;
    return 1;
  }
}


Note that the main point of interest here is that lexical_cast throws an exception if it fails (that is, if the string given is not a valid integer).
Last edited on
stringstream could also be useful here:

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
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
    int temp1, temp2;
    string input;
    ifstream fin;
    bool error;

    fin.open("in.txt");
    error=false;

    while (true)
    {
        getline(fin,input);
        if (!fin) break; //check for eof

        istringstream buffer(input);
        buffer >> temp1 >> temp2;

        //check for non numerical input
        //and less/more input than needed
        if (!buffer || !buffer.eof())
        {
            error=true;
            break;
        }

        //do what you want with temp1 and temp2
        cout << temp1 << '\t' << temp2 << endl;
    }

    if (error)
        cout << "file is corrupted..." << endl;

    cout << "hit enter to quit...";
    cin.get();
    return 0;
}
Last edited on
Topic archived. No new replies allowed.