I am currently trying to understand how to go through a .txt file in C and I think I have mostly everything worked out but what I need to do is kind of confusing. I need to create an array of Pointers to point to structs.
Each line in my .txt file should have information corresponding to a single struct. Each line should start with a name followed by some float values.
My question is, when I read the lines and parse them using strtok first, how would I get that information in a struct?
second how would I then make the sample pointer at index i point to the struct?
I tried doing the name seperate from the numbers since the numbers need their own special atof conversion since initially it will be a string. However I think this is probably incorrect since I want to read multiple lines, the code I have before the while loop for obtaining the name will only run once so any following lines will not have the name seperated. I can technically delimit my text file as I choose, so maybe I can just seperate the name with a semicolon and the rest spaces?
If this question seems confusing its probably because I am over thinking
Should I be declaring a struct such as : Sample tmp;
I've been reading examples but I can't figure out how to put the information together. Let me know if I declared my array of pointers incorrectly... Which I think I did. I think my the line that says:
sample arr[SIZE] = {NULL}; might be incorrect but I am not sure. if you can help me work out the logic behind all this I would appreciate it. Thanks.
typedef struct sample{
char* name;
int list_len;
float* value_list;
}sample;
void read_and_parse(){
const int SIZE = 1024;
sample* sample = (sample*)malloc(sizeof(sample); //pointer allocation?
FILE* fin;
fin = fopen("record.txt", "r");
if (fin == NULL) {
printf("record.txt could not be opened \n");
exit(1);
}
else {
int i= 0;
sample arr[SIZE] = {NULL}; //here I try to make the array of pointers
char linebuf[SIZE];
token = strtok(linebuf, " "); //grab the first item
while (fgets(linebuf, SIZE, fin) && i<SIZE) {
arr[i] = malloc(sizeof(sample));
arr[i.name] = token;
token = strtok(NULL, " ");
// now parse the linebuf and fill arr[i] with it
i++;
}
Edited: 11/02/2017 any print statements you see are just silly markers I placed for testing and recognizing what is running when I finally get this code compiled Here is a much better edited version of the code. I think it should work now.
typedef struct sample{
char* name;
int list_len;
float* value_list;
}sample;
void read_and_parse(FILE **fin, sample* arr[]){
const int SIZE = 1024;
if (*fin == NULL) {
printf("record.txt could not be opened \n");
exit(1);
}
else {
printf("successfully opened file\n");
char linebuf[SIZE];
while ( fgets(linebuf, SIZE, fin) ) {
arr[i] = malloc(sizeof(sample));
int floats_per_line = 0;
while(linebuf[i]){
if(linebuf[i] == ' ');
++floats_per_line;
}
arr[i]->list_len = values_per_line;
arr[i]->value_list = (float*)malloc(sizeof(float)*floats_per_line);
arr[i]->name = strdup(strtok(linebuf, ' '));
char* tok;
int j = 0
while(tok = strtok(NULL, ' ')){
arr[i]->value_list[j] = atof(tok);
++j
}
i++;
}
}
fclose(fin);
}
How would I read a line, parse the information and then attribute it to a struct ?
Read with fgets() which converts a line of file input into a string. OP does that well. Then parse the string.
when I read the lines and parse them using strtok first, how (to) get that information in a struct?
Should I be declaring a struct such as : sample tmp;
Pass the string to a helper function to parse it into a sample that can hold any input. So the pointer members of tmp need to point to maximal space.
char name[SIZE];
char f[SIZE/2];
sample tmp = { name, 0, f };
while (i<SIZE && fgets(linebuf, SIZE, fin)) {
if (sample_parse(&tmp, linebuf) == NULL) {
break; // Parsing failed for some reason, perhaps an error message?
}
// Now populate arr[i] with right-sized memory allocations
arr[i].name = strdup(tmp.name); // ToDo: add NULL check
arr[i].list_len = tmp.list_len;
size_t f_size = sizeof *(tmp.value_list) * tmp.list_len;
arr[i].value_list = malloc(f_size); // ToDo: add NULL check
memcpy(arr[i].value_list, tmp.value_list, f_size);
i++;
}
so maybe I can just separate the name with a semicolon and the rest spaces?
Yes. Also allow other white-spaces too.
if I declared my array of pointers incorrectly.
Code does not have an array of pointers anywhere.
Recommend using size_t for array size type.
typedef struct sample {
char* name;
// int list_len;
size_t list_len;
float* value_list;
} sample;
Some untested code for parsing. Parse the line with strtok(). Further parse the number tokens with strtof().
#define sample_NAME_DELIMITER ":"
#define sample_NUMBER_DELIMITER " \n\t\r"
// parse for a name and then 0 or more numbers
static sample *sample_parse(sample *dest, char *linebuf) {
char *s = strtok(linebuf, sample_NAME_DELIMITER);
if (s == NULL) {
return NULL; // no name - TBD on if this is allowed
}
strcpy(dest->name, s);
size_t i = 0;
while ((s = strtok(NULL, sample_NUMBER_DELIMITER)) != NULL) {
char *endptr;
dest->value_list[i] = strtof(s, &endptr);
if (s == endptr || *endptr) {
// conversion failed or extra junk
break;
}
i++;
}
dest->list_len = i;
return dest;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With