Reputation: 3
In the function below in my program, I am trying to read numbers from a text file and enter them to arrays of structure x,y,mass accordingly. The text file looks like this:
1 2 3 //first number is x, second is y, and third is mass
1 2 3
1 2 3
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
struct cg {
float x, y, mass;
}masses[MAX];
int readin(void)
{
FILE *file = fopen("test.txt", "r");
int count;
if (file == NULL) {
printf("Error: can't open files.\n");
return 1;
}
else {
while (1) {
char c = fgetc(file);
if (c != EOF) {
if (count == 0) {
masses[count].x = c;
}
else if (count == 1)
{
masses[count].y = c;
}
else if (count == 2)
{
masses[count].mass = c;
}
if (count != 3) {
count++;
}
else { count = 0; }
}
else {
break;
}
}
}
fclose(file);
}
I wrote this so far but i dont know if im going the correct way
Upvotes: 0
Views: 83
Reputation: 84561
If you are just getting started, get started correctly. When you approach a problem that requires reading lines of data, use a line oriented input function to read the data (e.g. fgets
or POSIX getline
). This allows you to validate the read separate and apart from parsing values from the line.
After reading and validating a line of data, you can then parse that data into whatever values you need. There are a great many tools available. sscanf
, strtod
, strtok
or simply walking a pointer over each character in your line buffer comparing character-by-character as you go and taking the needed action.
Here, sscanf
provides a very convenient way to parse 3 floating-point values from a line of text. (and use double
instead of float
for any engineering related work and always use integer values for currency). If you did not know how many values you were reading from each line, then walking strtod
through the buffer would work fine.
Validate, validate, validate. If you read it -- validate what your read. If you convert it -- validate your conversion took place (and if needed that the value is within the expected range).
Putting those pieces together, you can do something similar to the following to read 3-values from each line into an array of struct (up to MAX
elements). The code expects the filename to read as the first argument (or it will read from stdin
by default if no arguments are given):
#include <stdio.h>
enum { NMEMB = 3, MAX = 100, MAXC = 512 };
typedef struct {
double x, y, mass;
} cg;
int main (int argc, char **argv) {
int n = 0; /* masses index */
char buf[MAXC] = ""; /* buffer for each line */
cg masses[MAX] = {{ .x = 0 }}; /* array of cg initialized to 0 */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (n < MAX && fgets (buf, MAXC, fp)) { /* read each line */
cg tmp = { .x = 0 }; /* temporary struct */
/* you should validate complete line read here */
/* parse values into tmp and validate */
if (sscanf (buf, "%lf %lf %lf", &tmp.x, &tmp.y, &tmp.mass) == 3)
masses[n++] = tmp; /* assign tmp to massess, increment n */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (int i = 0; i < n; i++)
printf ("masses[%2d] %5.2f %5.2f %5.2f\n",
i, masses[i].x, masses[i].y, masses[i].mass);
return 0;
}
(note: I have left validating that a whole line was read as an exercise. strlen
and then checking that the last character read is '\n'
will suffice)
Example Input File
$ cat ../dat/int3x20.txt
21 61 78
94 7 87
74 1 86
79 80 50
35 8 96
17 82 42
83 40 61
78 71 88
62 20 51
58 2 11
32 23 73
42 18 80
61 92 14
79 3 26
30 70 67
26 88 49
1 3 89
62 81 93
50 75 13
33 33 47
Example Use/Output
$ ./bin/cg ../dat/int3x20.txt
masses[ 0] 21.00 61.00 78.00
masses[ 1] 94.00 7.00 87.00
masses[ 2] 74.00 1.00 86.00
masses[ 3] 79.00 80.00 50.00
masses[ 4] 35.00 8.00 96.00
masses[ 5] 17.00 82.00 42.00
masses[ 6] 83.00 40.00 61.00
masses[ 7] 78.00 71.00 88.00
masses[ 8] 62.00 20.00 51.00
masses[ 9] 58.00 2.00 11.00
masses[10] 32.00 23.00 73.00
masses[11] 42.00 18.00 80.00
masses[12] 61.00 92.00 14.00
masses[13] 79.00 3.00 26.00
masses[14] 30.00 70.00 67.00
masses[15] 26.00 88.00 49.00
masses[16] 1.00 3.00 89.00
masses[17] 62.00 81.00 93.00
masses[18] 50.00 75.00 13.00
masses[19] 33.00 33.00 47.00
Lastly, always compile with warnings enabled, and do not accept code until it compiles cleanly without warning. To enable warnings add -Wall -Wextra
to your gcc
compile string. (add -pedantic
for several additional warnings). For VS (cl.exe
on windoze), add /Wall
. For clang
, add -Weverything
. Read and understand each warning. They will identify any problems, and the exact line on which they occur.
Upvotes: 1