csv - Trying to read a list of floats, integers, and strings from a file with sscanf() in C is not working as expected -


i working on program reads large table file, periodic table precise.

struct periodic *createtable(){  char format[] ="%d\t%3s\t \                      %20s\t%f\t \                      %100[^\t]\t%f\t \                      %d\t%f\t%d\t \                      %d\t%d\t%20[^\t]\t \                      %7s\t%17[^\t]\t \                      %d\t%d\t%f\t \                      %40[^\t]\t%7s\n";   struct periodic *tableptr = malloc(sizeof(*tableptr)*num_elements); file *fp; fp = fopen("periodictable.csv","r"); char buff[150];  int i,err; for(i=0;i<num_elements;i++){     if(fgets(buff,150,fp)){         printf("%s\n",buff);         err = sscanf(buff,format,&(tableptr->num),&(tableptr->sym),&(tableptr->name),                &(tableptr->weight),&(tableptr->config),&(tableptr->neg),                &(tableptr->neg),&(tableptr->rad),&(tableptr->ion_rad),                &(tableptr->vdw_rad),&(tableptr->ie_1),&(tableptr->ea),                &(tableptr->oxi_st),&(tableptr->stn_st),&(tableptr->bond_type),                &(tableptr->melt),&(tableptr->boil),&(tableptr->dens),                &(tableptr->type),&(tableptr->year));         printf("\n\nmatches:%d\n",err);         printf("%d\n",tableptr->num);         printf("%s\n",tableptr->sym);         printf("%s\n",tableptr->name);         printf("%f\n",tableptr->weight);         printf("%s\n",tableptr->config);         printf("%f\n",tableptr->neg);         printf("%d\n",tableptr->rad);         printf("%f\n",tableptr->ion_rad);         printf("%d\n",tableptr->vdw_rad);         printf("%d\n",tableptr->ie_1);         printf("%d\n",tableptr->ea);         printf("%s\n",tableptr->oxi_st);         printf("%s\n",tableptr->stn_st);         printf("%s\n",tableptr->bond_type);         printf("%d\n",tableptr->melt);         printf("%d\n",tableptr->boil);         printf("%f\n",tableptr->dens);         printf("%s\n",tableptr->type);         printf("%d\n",tableptr->year);      } }  } 

format[] string containing formatting codes file read , each line put string called buff. buff read , values each line parsed.

from first line, encounter problems.

the first 5 values returned in print statements below.

1 h hydrogen 1.00794 1s1

but next 3 values zero, , there kind of falls apart there. have no idea going wrong , how fix it. appreciated!

diagnosis

as noted in comments, it's been more quarter of century since necessary write multiline strings backslashed newlines (and far many spaces on next line). can use string concatenation:

"this string" " , string" 

will treated same as:

"this string , string" 

even if 2 strings on separate lines no backslash @ end of line. (i exaggerate slightly. standard meant unnecessary on quarter of century old — c89/c90. 5 years before facility relatively available. nevertheless, code written in current millennium can use string concatenation instead of using backslashes @ ends of lines.)

you read 2 values &tableptr->neg because pass twice (but tried read float , int — it's 'make mind up' time). note \t in format same blanks — white space character (not in scanset) in format string matches 0 or more white space characters. also, 150 characters line rather short given config can 100 characters (so member must @ least char config[101];). helpful have structure definition; nuisance having reverse engineer it.

i suggested using more compiler warning flags, or better compiler. however, not entirely helpful. because format string in variable, not constant, warnings aren't available. got around creating macro make constant string format, , hell broke loose because passing &tableptr->sym (which char (*)[4] , not char *) — drop &.

you read year 7-character string try print integer not idea.

revised code

this leads manufactured code:

#include <stdio.h> #include <stdlib.h> #include <string.h>  struct periodic {     int num;     char sym[4];     char name[21];     float weight;     char config[101];     float neg;     int rad;     float ion_rad;     int vdw_rad;     int ie_1;     int ea;     char oxi_st[21];     char stn_st[8];     char bond_type[18];     int melt;     int boil;     float dens;     char type[41];     char year[8]; };  #define format "%d\t%3s\t"                 \                "%20s\t%f\t"                \                "%100[^\t]\t%f\t"           \                "%d\t%f\t%d\t"              \                "%d\t%d\t%20[^\t]\t"        \                "%7s\t%17[^\t]\t"           \                "%d\t%d\t%f\t"              \                "%40[^\t]\t%7s\n"            int num_elements = 120;  struct periodic *createtable(void);  struct periodic *createtable(void) { //    char format[] = "%d\t%3s\t"                 // num, sym //                    "%20s\t%f\t"                // name, weight //                    "%100[^\t]\t%f\t"           // config, neg //                    "%d\t%f\t%d\t"              // rad, ion_rad, vdw_rad //                    "%d\t%d\t%20[^\t]\t"        // ie_q, ea, oxi_st //                    "%7s\t%17[^\t]\t"           // stn_st, bond_type //                    "%d\t%d\t%f\t"              // melt, boil, dens //                    "%40[^\t]\t%7s\n";          // type, year      struct periodic *tableptr = malloc(sizeof(*tableptr) * num_elements);     file *fp;     fp = fopen("periodictable.csv", "r");     char buff[150];      int i, err;     (i = 0; < num_elements; i++)     {         if (fgets(buff, 150, fp))         {             printf("data: %s\n", buff);             err = sscanf(buff, format, &(tableptr->num), (tableptr->sym), (tableptr->name),                          &(tableptr->weight), (tableptr->config), &(tableptr->neg),                          /*&(tableptr->neg),*/ &(tableptr->rad), &(tableptr->ion_rad),                          &(tableptr->vdw_rad), &(tableptr->ie_1), &(tableptr->ea),                          (tableptr->oxi_st), (tableptr->stn_st), (tableptr->bond_type),                          &(tableptr->melt), &(tableptr->boil), &(tableptr->dens),                          (tableptr->type), (tableptr->year));             if (err != 19)             {                 fprintf(stderr, "conversion failure: %d ok\n", err);                 break;             }             printf("\n\nmatches:%d\n", err);             printf("num:    %d\n", tableptr->num);             printf("sym:    %s\n", tableptr->sym);             printf("name:   %s\n", tableptr->name);             printf("weight: %f\n", tableptr->weight);             printf("config: %s\n", tableptr->config);             printf("neg:    %f\n", tableptr->neg);             printf("rad:    %d\n", tableptr->rad);             printf("ionrad: %f\n", tableptr->ion_rad);             printf("vdwrad: %d\n", tableptr->vdw_rad);             printf("ie_1:   %d\n", tableptr->ie_1);             printf("ea:     %d\n", tableptr->ea);             printf("oxi_st: %s\n", tableptr->oxi_st);             printf("stn_st: %s\n", tableptr->stn_st);             printf("bondtp: %s\n", tableptr->bond_type);             printf("melt:   %d\n", tableptr->melt);             printf("boil:   %d\n", tableptr->boil);             printf("dense:  %f\n", tableptr->dens);             printf("type:   %s\n", tableptr->type);             printf("year:   %s\n", tableptr->year);         }     }     return tableptr; }  int main(void) {     struct periodic *tbl = createtable();     free(tbl);     return 0; } 

note parentheses around arguments sscanf() superfluous. line such as:

&(tableptr->weight), (tableptr->config), 

could written without parentheses:

&tableptr->weight, tableptr->config, 

example run

given one-line data file fictitious data hydrogen:

1       h       hydrogen        1.00794 1s1     -1.0001999      2       3.0002999       4       5       6       oxy     stn     bond    -234    -236    1.01e-5 gas     1723 

the program produced output:

data: 1 h       hydrogen        1.00794 1s1     -1.0001999      2       3.0002999       4       5       6       oxy     stn     bond    -234    -236    1.01e-5 gas     1723    matches:19 num:    1 sym:    h name:   hydrogen weight: 1.007940 config: 1s1 neg:    -1.000200 rad:    2 ionrad: 3.000300 vdwrad: 4 ie_1:   5 ea:     6 oxi_st: oxy stn_st: stn bondtp: bond melt:   -234 boil:   -236 dense:  0.000010 type:   gas year:   1723 

having 19 columns in single input painful. helpful use string literal (disguised macro) format string; @ least gcc can error check types.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -