Recognizing End Of File (Mixed Text And Numbers)

All - This is NOT for a class assignment. I have written some C code to read a file of orbital information from a Russian site. I have figured out how to get it to read the first line only :-( of about 2800 lines. Sigh. I have looked at several books and some web sites.

Can anyone help me get a While loop working? So far it reads in the first of the lines, about 16 columns separated by commas. I have tried about a hundred variations of how to recognize the end of the file. Apparently the feof function is needed but I read in about 17 quantities from each line and cannot get the code to go past line 1. Grrr.

The code reads from an input file and creates and writes to an output file. I read into a structure.

I could provide code of course. This is vanilla C code on a Unix (Macintosh) box.
Last edited on
It won't let me post my code since it is too long (about six pages).
Normally you don't need feof or EOF.
If you use fscanf or fgets you can check its return value.

Maybe you can show us the code to read and some lines from the input file.
Is this too long???

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// OrbitManager.c
// copyright Charles Phillips
//  2018 may 12  cut out function to read from keyboard and printing
//
// this is the one that reads ISON orbits from a file and puts out to a file

#include <stdio.h>

#include <string.h> // strtok, strcpy stuff not even used yet
#include <stdlib.h> // atoi, atof not used yet
#include <math.h>  // math functions

#define MU  398600.4418  // gravitational parameter
#define min_per_day  1440  // minutes per day
#define sec_per_day  86400   //seconds per day
#define PI		3.141592653589
#define Two_Pi  6.28  // 2 times Pi (for use in finding semi-major axis)

typedef struct Satellite  // set up structure to accept parameters
{
    int sequence_number; // sequential number in their system - not needed?

    int    number;  // ISON number
    float  first_seen;  // date it was first seen
    
  //  char   international_designator[12];  // not currently used
    
    double epoch;   // epoch time
    float epoch_minutes;  // darn them they have a space in epoch
    int gap;    // gap in days between something and something else
    float semi_major;    // semi major axis column 5
    float  inclination;  // column 6
    float  RAAN;  // column 7
    float  eccentricity;  // column 8

    float  argument_latitude;  // ISON has this number column 9
    
    float  argument_perigee; // column 10
    
    float  magnitude;  // not needed column 11
    float uncertainty;  // not needed
    int  blah1;  // some number, not needed
    int blah2; // some number, not needed
    int blah3; // some other not needed number
    
    float  apogee;   // calculated later
    float  perigee;  // calculated later

}Satellite;

// none of those are initialized with values, it is just the structure
// functions:

void readFile (Satellite *sat);  // read information from keyboard

void inputFile (FILE* input, Satellite *sat1);   // read from file

void printParameters (FILE* output, Satellite *sat1);  // print to display, file

void calculateApogeePerigee (Satellite *sat1);  // find apogee, perigee

int main(void)
{
    
    char answer = 'x';  // this is the answer to the first while loop
    Satellite sat1;      // start a Structure called sat - need sat1, sat2,...sat(n)
                    // or are the fields numbered? indexed?
                        // increment sat number and then refer to the right number in every later line

    FILE* input; // input points to file to read from

	FILE* output; // output points to file to write to

    // these next two lines are specific to my directories - a user will have to change them!!
    
    input = fopen("/Users/Charles/Documents/1_OrbitManager_data/ison_data.txt", "r");  // read data from right place

	output = fopen("/Users/Charles/Documents/1_OrbitManager_data/satellite_data.txt", "w");  // put satellite in right place
    
    
    while (answer != 'q') {
        printf("\nWhat do you want to do? Enter the letter for your response.\n\n");
        printf(" c) Enter orbital information\n");
        
        printf(" q) Quit\n\n");
        
        scanf(" %c", &answer);  // get answer from keyboard
        
        switch (answer) {
            
           
            case 'c':
                printf("I will take input from a file\n");
                inputFile (input, &sat1);
                // later add international designator as well
                // need error check - did open input??
                printf("now call calculate apogee and perigee\n");  // debug step, this does not show up

                calculateApogeePerigee (&sat1);
                printf("\nfor test, immediately print what was just input\n\n");
              //  printParameters (output, &sat1);
                printf("I got the values and you can choose another option\n");
                break;
            case 'q':
                printf("You said to quit so I will quit\n");
                break;
            default:
                printf("Invalid selection. Try again.\n");
                break;
        }
    }
    
	fclose(output);  // close file we put output into
    fclose(input);  // close file we get input from

    
    return 0;
}


void inputFile (FILE* input, Satellite *sat1)  // read from input file
{
    
  // put the check back here to see if input is there
    
    printf("While loop is next");  // never gets here
    // used to have each fscanf separately and that worked

    while ( fscanf(input, "%d,%d,%f,%lf,%f,%d,%f,%f,%f,%f,%f,%f,%f,%f,%d,%d,%d",&sat1->sequence_number,&sat1->number,&sat1->first_seen,&sat1->epoch,&sat1->epoch_minutes,&sat1->gap,&sat1->semi_major,&sat1->inclination,&sat1->RAAN,&sat1->eccentricity,&sat1->argument_latitude,&sat1->argument_perigee,&sat1->magnitude,&sat1->uncertainty,&sat1->blah1,&sat1->blah2,&sat1->blah3) !=EOF)
           
            {
    
  // fscanf(input, "%f", &sat1->mean_anomaly);  ISON does not supply this
    
   // fscanf(input, "%f", &sat1->mean_motion); ISON does not supply this
    
    
      calculateApogeePerigee (sat1);  // why not &sat1?
   
            } }

void calculateApogeePerigee (Satellite *sat1)   // calculate apogee, perigee
{
    // sat number will have to be fixed
    
    float a;   // a is semi-major axis, the formula didn't like the reference
    a=sat1->semi_major;
 
    sat1->apogee = (a * (1 + sat1->eccentricity)) - 6378.135;
    sat1->perigee = (a * (1 - sat1->eccentricity)) - 6378.135;
    
}
Last edited on
One problem is that sat1 is a pointer so you don't need the & in front.
Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void inputFile (FILE* input, Satellite *sat1)  // read from input file
{
    printf("While loop is next");  // never gets here
    // used to have each fscanf separately and that worked

    while ( fscanf(input, "%d,%d,%f,%lf,%f,%d,%f,%f,%f,%f,%f,%f,%f,%f,%d,%d,   
                          %d",sat1->sequence_number,
                          sat1->number,sat1->first_seen,sat1->epoch,
                                     sat1->epoch_minutes,sat1->gap,sat1->semi_major,sat1->inclination,
sat1->RAAN,
sat1->eccentricity,sat1->argument_latitude,sat1->argument_perigee,
sat1->magnitude,sat1->uncertainty,sat1->blah1,sat1->blah2,sat1->blah3) == 17)
  {
     /* maybe print some data to see if read correctly, maybe with a small test file first */
     calculateApogeePerigee (sat1);  // why not &sat1?
  } 
}

Sorry for the poor formatting. Just have a little tablet at the moment. :(
I will try it, but the &sat1 etc worked before. Now it seems that the code never gets to the while loop at all. I used to NOT have while in there, just did fscanf for each quantity.

What is the == 17??? Not EOF?
Last edited on
You have 17 format specifier in your fscanf. == 17 means 17 fields read.
BTW Didn't you mention you want to read 16 somewhere else?
Anyway please show us some lines of the input so we can run it and see better where the problem is.
Thomas - 16 columns but one has a space in it and I couldn't figure out how to handle it, so I read it as another column. When I get to it I'll find a better solution. As you can see I try to solve one problem at a time.

02052017 001351 is in column 4

Input:

1, 12500, 26122008, 02052017 001351, 5, 8297.9, 45.000, 30.000, 0.00321, 308.2, 120.000, 1.23, 14.40, 17.5, 0.1, 22
2, 12501, 26122008, 02052017 001351, 5, 8297.9, 45.000, 30.000, 0.00321, 308.2, 120.000, 1.23, 14.40, 17.5, 0.1, 22

Here is the first 20 lines of the file:

1, 12500,26122008,02012018 000306, 15, 8297.9, 63.354,312.962,0.088984,359.9,300.273,1.23e-02, 17.5, 0.2, 69
2, 12700,18022009,01012018 235809, 4, 8408.1, 63.217,199.813,0.070974, 0.1,122.640,2.87e-02, 17.1, 0.2, 58
3, 12801,23122016,01012018 225518, 4, 8292.0, 63.321, 26.530,0.191239,359.9,349.855,8.49e-02, 16.5, 1.6, 8
4, 12900,06032016,02012018 001312, 219, 8477.0, 63.507, 49.465,0.104272,359.9,290.608,1.80e-01, 14.7, 4.0,342
5, 13000,20032017,02012018 003229, 4, 8382.4, 61.885, 88.146,0.202657,360.0, 66.555,7.64e-02, 17.9, 1.3, 15
6, 13400,06122016,01012018 225629, 3, 8471.4, 64.709,100.520,0.206007, 0.0, 81.176,2.44e-01, 17.3, 1.3, 18
7, 13500,29082015,02012018 000252, 504, 7138.7, 61.563,113.179,0.036259, 0.0,328.144,9.85e+00, 15.9, - , -
8, 13600,11102008,01012018 234917, 5, 8795.0, 63.316,109.242,0.106877, 0.0,160.758,7.58e-02, 16.4, 0.1, 55
9, 13601,21072017,01012018 232810, 147, 8065.0, 49.038, 27.288,0.183406,359.9,110.042,4.31e-02, 17.0, 0.1, 22
10, 13700,14022015,01012018 224931, 165, 8415.0, 56.970,319.680,0.192938,359.9,307.132,1.93e-01, 17.0, - , -
11, 14100,20092016,01012018 234015, 9, 8994.4, 56.883, 11.285,0.239333,359.9,147.794,4.23e-01, 17.0, 0.2, 56
12, 14101,05122017,02012018 004347, 20, 8864.7, 20.912,299.214,0.257883,359.9,166.942,7.59e-02, 17.0, - , 64
13, 14500,16032015,01012018 225350, 894, 8736.3, 56.905,285.744,0.215318,360.0,185.333,2.33e-01, 16.8,25.6, -
14, 14600,03112015,02012018 010507, 4, 9208.0, 65.125, 86.769,0.204460,360.0, 49.109,1.26e+00, 17.0, 1.6,604
15, 14800,21122012,02012018 005138, 4, 9307.7, 28.274,326.600,0.238101,359.8,145.239,9.41e-03, 10.1, 0.1, 1
16, 14801,01072015,01012018 235530, 20, 9209.5, 56.937,200.606,0.253695, 0.1, 85.716,3.22e-01, 15.3, 1.6,254
17, 14900,06082015,02012018 003135, 281, 9308.5, 56.992,339.633,0.261509,359.9,351.498,2.16e-01, 16.8,89.3, -
18, 14901,07092015,01012018 231330, 219, 9271.2, 57.076, 85.357,0.260775,360.0,321.926,2.46e-01, 16.6, - ,917
19, 14902,21012016,01012018 232819, 706, 9302.0, 19.729,351.098,0.231832,359.7,211.667,1.65e+00, 15.3, - , -
20, 15101,19062016,01012018 234520, 4, 9202.8, 62.910,307.613,0.269420,359.9, 12.630,1.20e-01, 17.0, 3.5, 15
Also, if I take the & out before "sat1" - compile fails. They have to be &sat1; input is a pointer
Last edited on
> One problem is that sat1 is a pointer so you don't need the & in front.
`sat1' is a pointer
`sat1->sequence_number' is an integer
the scanf family expects pointers to the arguments, so you do need to write &sat1->sequence_number

the compler should have warned you about the mistake.

> Is this too long???
yes, it is.
your problem is with reading a file, your code has a menu and a function `calculateApogeePerigee()' that are irrelevant to the issue (or that they may be the issue while we focus on the other part)
strip your code to the bones.

> printf("While loop is next"); // never gets here
¿so you never pass the menu part?
get a debugger, run step by step and watch the variables

> 16 columns but one has a space in it and I couldn't figure out how to handle it
¿is the space always there?
then instead of %f,%fwrite %f %f
if not, you'll have to figure out what does that mean.

I see that you have some `-' in the columns (perhaps missing values)
maybe you should read always as string and then trying to convert to number
see atoi(), atof()

PS: learn to indent (I use clang-format)
ne555 - I took the menu selection out so that I could paste the important code here, that also messed up my indentation some. This entire code is too long and this site refuses to let me put it all in. I also took out a big function to print the satellite information, input from the keyboard, etc. All of that works just fine.

The code runs the menu but does not get to the function to read the "input" file. The code does not seem to get to that printf you mentioned. I have a version of this code, very similar, that does successfully read the first line of a test input file.

I need to read the input file and then add some things like apogee, perigee, mean motion - etc. These are parameters that each satellite has but that the ISON file assumes that you will calculate them yourself from the included parameters.

I'll try that %f %f to try to read that one column with the space - I just had not gotten to that yet. And yes the input file has some dashes and I will get around to them.

I use XCode which is a very capable IDE but I thought that my problem was that the books talk about EOF and feof and I thought that I needed to put in what was the actual end of file marker.

I guess I could just make sure the file had a blank line at the end and search for a blank line?
Last edited on
I had a closer look at your code and would recommend a different approach.
Since you don't want all the data it would be easier to read it into a string first and read only the columns you need.
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
98
99
100
101
102
103
104
105
106
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

typedef struct Satellite  // set up structure to accept parameters
{
	int sequence_number; // sequential number in their system - not needed?

	int    number;  // ISON number
	float  first_seen;  // date it was first seen

											//  char   international_designator[12];  // not currently used

	double epoch;   // epoch time
	float epoch_minutes;  // darn them they have a space in epoch
	int gap;    // gap in days between something and something else
	float semi_major;    // semi major axis column 5
	float  inclination;  // column 6
	float  RAAN;  // column 7
	float  eccentricity;  // column 8

	float  argument_latitude;  // ISON has this number column 9

	float  argument_perigee; // column 10

	float  magnitude;  // not needed column 11
	float uncertainty;  // not needed
	float  blah1;  // some number, not needed
	float blah2; // some number, not needed
	float blah3; // some other not needed number

	float  apogee;   // calculated later
	float  perigee;  // calculated later

}Satellite;

int CreateSatellite(const char *txt, Satellite *satelite);
void PrintSatellite(const Satellite *satellite);
void PrintLine(char ch, size_t size);

int main()
{
	char line[256] = { 0 };
	FILE* src = fopen("input.txt", "r");
	Satellite sat = {0};

	if (src == NULL)
	{
		perror(NULL);
		return 1;
	}
	while (fgets(line, sizeof(line), src))
	{
		CreateSatellite(line, &sat);
		PrintSatellite(&sat);
	}

	fclose(src);

	system("pause");
	return 0;
}

int CreateSatellite(const char *txt, Satellite *satellite)
{
	assert(txt != NULL);
	assert(satellite != NULL);

	int field_count = sscanf(txt, " %d, %d, %f, %lf %f, %d, %f, %f, %f, %f, %f, %f", 
													&satellite->sequence_number, &satellite->number, 
													&satellite->first_seen, &satellite->epoch, 
													&satellite->epoch_minutes, &satellite->gap, 
													&satellite->semi_major, &satellite->inclination, 
													&satellite->RAAN, &satellite->eccentricity, 
													&satellite->argument_latitude, 
													&satellite->argument_perigee);
	
	return field_count;
}

void PrintSatellite(const Satellite *satellite)
{
	printf("Sequence_number: %d\n", satellite->sequence_number);
	printf("Number: %d\n", satellite->number);
	printf("First seen: %f\n", satellite->first_seen);
	printf("Epoch: %lf\n", satellite->epoch);
	printf("Epoch minutes: %f\n", satellite->epoch_minutes);
	printf("Gap: %d\n", satellite->gap);
	printf("Semi Major: %.1f\n", satellite->semi_major);
	printf("Inclination: %.3f\n", satellite->inclination);
	printf("RAAN: %.3f\n", satellite->RAAN);
	printf("Eccentricity: %.6f\n", satellite->eccentricity);
	printf("Argument_latitude: %.1f\n", satellite->argument_latitude);
	printf("Argument_perigee: %.3f\n", satellite->argument_perigee);
	PrintLine('=', 60);
}

void PrintLine(char ch, size_t size)
{
	while(size-- > 0)
		putchar(ch);

	putchar('\n');
}
Thomas1965 - that looks like a good solution, so your function at line 65 reads the columns that I need.

Doesn't this task - read a file until the end - seem like a very very basic task? I thought that I was just using feof and EOF wrong and that I would get like 18 replies that told me how to do it. I still plan to figure that out. The books that I have read just don't show how this works.
Doesn't this task - read a file until the end - seem like a very very basic task?

Yes it is. There are a few basic tasks with reading text files. Read char by char, read words or read lines.

What books have you read?

The definite guide is
https://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/ref=sr_1_1?ie=UTF8&qid=1526282371&sr=8-1&keywords=dennis+ritchie

Another must read (IMO) is
https://www.amazon.com/Writing-Solid-Code-Microsoft-Programming/dp/1556155514/ref=sr_1_3?s=books&ie=UTF8&qid=1526282447&sr=1-3&keywords=steve+maguire
Thomas - I will look up that first book but I am going to stay with Unix programming. There are plenty of Windows programmers.
Sorry I should have mentioned it. The books has nothing to do with windows.
The code examples are general and should work on Unix or Mac.
The author worked(works?) for Microsoft but also worked on the Office for Mac projects.
Topic archived. No new replies allowed.