Reading data files with values seperated by commas.

OK, so this was quite easy when I programmed it in C, but come trying to do it in C++ and it's turning out to be an absolute nightmare! I'm trying to get more acclimatised to C++ so trying to use this language instead where I can.

Basically I have a file being generated from some analysis software hooked up to a microscope like so:

1
2
3
4
5
6
 0, 183.073,  568.272,	 5.467,	 4.610,	45.593,	32.508,	81.000,
 1, 53.745,   7.337,	 8.318,	 6.489,	92.380,	38.724,	172.000,
 2, 127.006,  11.584,	 6.315,	 4.593,	23.727,	43.329,	89.000,
 3, 154.842,  9.705,	 7.953,	 6.912,	94.801,	29.654,	176.000,
...
(i.e. a file with the variables fibnum, x, y, b, a, phi, theta, area,... for hundreds of lines)


My code so far (which I apologise is probably really bad) is as follows:

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
/* Program to estimate the possible projections of fibres after the second sectioning method */

#include <iostream>
using std::cout;
using std::endl;

#include <fstream> // for file managing
#include <cstdlib> // for exit function

using namespace std;
using std::ifstream;

int main(){
	float fibnum=0; //initial variable in the data file
	float x,y,b,a,phi,theta,area; //the rest of the variables in the data file 
	
	ifstream indata;

	indata.open("sc10.dat");
		if(!indata){
			cout << "Error: file could not be opened" << endl;
			exit(1);
		}
	
		while(!indata.eof()){
                        indata >> fibnum >> x >> y >> b >> a >> phi >> theta >> area;
			cout << "Fibre number is:" << fibnum << endl;
			
		}
		indata.close();
		cout << "EOF Found" <<endl;

	return 0;
}


All I really need to be able to do is read each specific number and then be able to perform operations on each number within the while loop. At current it's throwing a load of rubbish back at me for the 'fibnum', so it's clearly not working.

As a point, with me obviously being reasonably comfortable with C I was using this set of code to read the file, is it just a case of adjusting this a little?

1
2
3
4
5
while ((c=fgetc(finput)) != EOF){
		fscanf(finput, "%d, %f, %f, %f, %f, %f, %f, %f\n",&fibnum,&x,&y,&b,&a,&phi,&theta,&area); //reads data from .dat file
		fprintf(foutput,"%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",fibnum,x,y,b,a,phi,theta,area); //reprints it out into the excel document
....
}


Thanks in advance, hope you can help!
Last edited on
First of all:
1
2
3
4
5
6
7
8

using std::cout; 
using std::endl;

//code...

using namespace std;
using std::ifstream;

If you use "using namespace std", you don't need to declare anything more(like "using std::cout"), since you declared, that you are using this namespace. Either declare each thing you will use, or whole namespace std.

So either:

1
2
3
4
5
6
7

using std::cout; 
using std::endl;

//code...

using std::ifstream;


or

1
2
//code...
using namespace std;


Second thing is, from what I see fibnum is integer, not fraction, so you could simply use an integer type.

And third thing is, that you should try to run your program in your mind, step by step, and debug it by yourself first. You would see then, that you take input only once(so basically you only take one line where you said there would be hundreds of lines).

Good luck! :)
You might try something like:

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
#include <iostream>
#include <fstream>

struct record_type
{
    int fibnum ;
    float x ;
    float y ;
    float b ;
    float a ;
    float phi ;
    float theta ;
    float area ;
};

bool extractRecord(std::istream& is, record_type& record)
{
    char comma;

    is >> record.fibnum >> comma >> record.x >> comma >> record.y >> comma ;
    is >> record.b >> comma >> record.a >> comma >> record.phi >> comma ;
    is >> record.theta >> comma >> record.area >> comma ;

    return is ;
}

bool insertRecord(std::ostream& os, const record_type& record)
{
    const char t = '\t' ;

    os << record.fibnum << t << record.x << t << record.y << t ;
    os << record.b << t << record.a << t << record.phi << t ;
    os << record.theta << t << record.area << '\n' ;
    return os ;
}

int main()
{
    std::ifstream indata("sc10.dat") ;

    if ( !indata.is_open() )
    {
        std::cout << "Error: file could not be opened\n" ;
        return 1 ;
    }

    record_type rec ;
    while ( extractRecord(indata, rec) )
        insertRecord(std::cout, rec) ;
}
Your C and C++ read statements aren't quite the same.

What's c (from while ((c=fgetc(finput)) != EOF))? Are you skipping something in the file? Does your file have some sort of header, and you are skipping a line... so that c just happens to be the newline character?


You say you are getting nonsense for fibnum, but I suspect you are only getting it for the last one? Is that correct?

You are looping on EOF, which even in C is a bad idea. Your read loop should look like this:

1
2
3
4
5
		while(true){
                        indata >> fibnum >> x >> y >> b >> a >> phi >> theta >> area;
			if (!indata) break;
			cout << "Fibre number is:" << fibnum << endl;
		}

What this means is that you have tried to read data (line 2) and only after that do you check to see whether it failed (line 3).

The method you will more typically see is to combine the read and check loop in the while condition:

1
2
3
		while(indata >> fibnum >> x >> y >> b >> a >> phi >> theta >> area){
			cout << "Fibre number is:" << fibnum << endl;
		}

The only issue here is that any read failure causes abort, not necessarily just EOF. For what you are doing that may be acceptable, but for some applications you must be more careful to check the error condition and continue appropriately.

Hope this helps.
Thanks for all your replies guys.

MatthewRock, thanks for helping stream line the code somewhat. I've been trying to learn bits and bobs from various sources and it's all obviously got to the point where I have conflicting methods haha! As for 'fibnum' being an integer or a floating point it doesn't really affect the outcome as you would expect really (at least for my uses that is).

Duoas, no the nonsense I'm getting for 'fibnum' is the same for each and every value (it's like a good 30 characters of nonsense upon each run through).

I imagine the c in that line you quoted is probably related to a character, although I'll be honest it's something one of my lecturers threw at me about 6 months ago so my memory of it is blurred at best. The file is exactly as I posted earlier, no headers, only the values separated by commas.

Cire, is that how you eliminate the factor of comma's separating each value in your code by simply putting in:
1
2
3
4
5
6
7
 char comma;

    is >> record.fibnum >> comma >> record.x >> comma >> record.y >> comma ;
    is >> record.b >> comma >> record.a >> comma >> record.phi >> comma ;
    is >> record.theta >> comma >> record.area >> comma ;

    return is ;

I didn't realise that was how you effectively alerted the program to their presence? So is it not as in C, where you basically use the same format replacing the values with the float variables which it reads in (%f etc.)?
Topic archived. No new replies allowed.