Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I read a line, parse the information and then attribute it to a struct in C?

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);
}
like image 833
jlyeffx Avatar asked Feb 02 '26 08:02

jlyeffx


1 Answers

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;
}
like image 172
chux - Reinstate Monica Avatar answered Feb 04 '26 01:02

chux - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!