I have a .txt file that contains an unknown (each time) number of lines. In every line there are 4 floats separated by the space character.
My problem is that I have no clue how to separate each float from the others in each line and put it in the right place of the matrix.
This is the code I have done so far (it goes through every line for the first time so that I know the number of the lines to declare my matrix, but it only returns just the first of the four values):
#include <stdio.h>
FILE *fr;
main () {
float time, xaxis, yaxis, zaxis;
char line[40];
int n = 0;
fr = fopen ("walk-after-excel.txt", "r");
while (fgets (line, 80, fr) != NULL) {
n++;
}
rewind (fr);
printf ("%u", n);
float values[n][4];
int i;
for (i = 0; i < n; i++) {
values[i][0] = 0;
values[i][1] = 0;
values[i][2] = 0;
values[i][3] = 0;
}
while (fgets (line, 80, fr) != NULL) {
sscanf (line, "%f", &time);
printf ("%f\n", time);
}
for (i = 0; i < n; i++) {
printf ("%f, %f, %f, %f \n", values[i][0], values[i][1], values[i][2],
values[i][3]);
}
printf ("%u", n);
fclose (fr);
}
Any help will be very appreciated.
You've got a few issues here:
main
. This means you should use int main(void) { ... }
.fgets
that your buffer is 80 bytes, this is a huge no-no. You must never specify to functions that your buffer is bigger than it really is, or else you will encounter buffer overflows (which in the real world can become exploitable security holes). Because you are using an array type, you can simply pass sizeof line
to fgets
, and then it won't matter if you change the size of line
, it will always pass the correct value to fgets
.malloc
or calloc
. calloc
is like malloc
except that it automatically zeroes out the allocated memory for you.fr
variable to be global.Since each line of the file represents a “record”, you could declare a structure, like this:
struct record
{
float time;
float xaxis;
float yaxis;
float zaxis;
};
Also, since there are an unknown number of records in the file, there are at least two ways to allocate enough memory to hold all records. One is to count all the lines in the file first, then allocate the memory based on the number of lines. This has the benefit that you will allocate exactly the right amount of memory that you need, but requires that you read the file twice. Another way is to allocate enough memory to hold a decent number of records and then “grow” this memory allocation if it turns out it wasn't big enough. This has the benefit that you only need to read the file once, but you may end up wasting memory.
You're already using the “count number of records first, allocate later” approach, so we just need to fix up the aforementioned issues.
#include<stdio.h>
struct record
{
float time;
float xaxis;
float yaxis;
float zaxis;
};
int main(void)
{
FILE *fr;
char line[80];
int n = 0;
fr = fopen ("walk-after-excel.txt","r");
if (fr == NULL)
{
printf("Couldn't open file!\n");
return 1;
}
while(fgets(line, sizeof line, fr) != NULL)
{
n++;
}
rewind(fr);
printf("%d",n); // use %d for int types
struct record *records = calloc(n, sizeof(struct record));
for (int i = 0; i < n; i++)
{
fgets(line, sizeof line, fr);
sscanf(line, "%f %f %f %f", &records[i].time, &records[i].xaxis, &records[i].yaxis, &records[i].zaxis);
}
// records now contains all the data in the file!
// to access the 5th line's xaxis value, use:
printf("%f\n", records[4].xaxis);
// (remember that arrays in C are 0-based)
// when you are done, free the memory allocated by malloc/calloc with free()
free(records);
fclose(fr);
}