Home > Net >  fgets or fscanf on array struct to read specific format file in c
fgets or fscanf on array struct to read specific format file in c

Time:06-21

How to use fgets and sscanf when there is file like this?

No  Nama Masakan                    Berat (Gram)            Kalori
1   Asinan                              250                 208
2   Toge Goreng                         250                 243
3   Gado - Gado                         150                 295
4   Ketoprak                            250                 153
5   Pempek                              200                 384
6   Rawon                               160                 331
7   Soto Ayam                           100                 101
8   Soto Padang                         100                 127
9   Tongseng                            120                 331
10  Hamburger                           125                 257
11  Kerupuk Palembang                   50                  168
12  Kerupuk Udang                       20                  72
13  Mie Bakso                           200                 302
14  Nasi Tim Ayam                       420                 588
15  Pizza                               125                 163
16  Sate Kambing                        180                 729
17  Sayur Krecek                        175                 249
18  Siomay                              100                 361
19  Soto Betawi                         150                 135
20  Soto Makasar                        150                 525
21  Soto Sulung                         150                 86

So there is 22 line on that file. So how to scanit each format? using fgets or fscanf? I thinking that the solution maybe like this:

while(!feof(fp))
{
 fgets(buffer,100,fp);
 sscanf(buffer,"%d",&struct[i].number);
 sscanf(buffer,"%[^\n]",struct[i].string);
 sscanf(buffer,"%d",&struct[i].gram);
 sscanf(buffer,"%d",&struct[i].calorie);
}

Is what im doing correct? if it's not please tell me so i won't really be curious about how to solve this problem. Sometimes i always the similar problem like this and wanna know how to solve it. Thank you.

CodePudding user response:

Because the name field can contain spaces, parsing is complicated.
Use pointers to save positions in the line. Then parse or copy from those pointers.
This is but one of several parsing strategies.

#include <stdio.h>
#include <string.h>

int main ( void) {
    char buffer[100] = "";
    char string[100] = "";
    char *filename = "file.txt";
    int number = 0;
    int gram = 0;
    int calorie = 0;
    FILE *pf = NULL;

    if ( NULL != ( pf = fopen ( filename, "r"))) {
        fgets(buffer,100,pf); // get header line
        while(fgets(buffer,100,pf)) // get lines until end of file
        {
            char *name = buffer;
            int span = 0;
            if ( 1 != sscanf(buffer,"%d %n",&number, &span)) {
                continue;
            }
            name  = span; // name now points to first character of name field
            char *endfield = NULL;
            if ( NULL != ( endfield = strstr ( name, "   "))) {; // endfield points to three spaces after name field
                span = endfield - name;
                if ( span && span < sizeof string) {
                    strncpy(string,name,span); // copy span characters
                    string[span] = 0; // zero terminate
                    printf ( "%-20s", string);
                }
                if ( 2 == sscanf(endfield,"%d%d",&gram,&calorie)) {
                    printf ( "   gram:=   calorie:=", gram, calorie);
                }
                printf ( "\n");
            }
        }
        fclose ( pf);
    }
    else {
        perror ( filename);
    }
    return 0;
}

Another strategy is to use strtok.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void) {
    char buffer[100] = "";
    char string[100] = "";
    char **token = NULL; // pointer to pointer to store tokens
    char *filename = "file.txt";
    char *whitespace = " \t\r\n";
    int limit = 0;
    int number = 0;
    int gram = 0;
    int calorie = 0;
    FILE *pf = NULL;

    if ( NULL != ( pf = fopen ( filename, "r"))) {
        fgets ( buffer, 100, pf); // get header line
        while ( fgets ( buffer, 100, pf)) {
            char *line = buffer;
            char *item = NULL;
            int count = 0;
            while ( ( item = strtok ( line, whitespace))) {
                if ( count   1 > limit) {
                    char **temp = realloc ( token, sizeof *token * ( count   1));
                    if ( NULL == temp) {
                        fprintf ( stderr, "realloc problem\n");
                        fclose ( pf);
                        free ( token);
                        exit (1);
                    }
                    token = temp;
                    limit = count   1;
                }
                token[count] = item;
                  count;
                line = NULL;
            }

            if ( count < 4) { // too few tokens
                continue;
            }

            number = 0;
            gram = 0;
            calorie = 0;

            if ( 1 != sscanf ( token[0], "%d", &number)) { // the first token
                continue;
            }
            if ( 1 != sscanf ( token[count - 2], "%d", &gram)) { // the next to last token
                continue;
            }
            if ( 1 != sscanf ( token[count - 1], "%d", &calorie)) { // the last token
                continue;
            }

            string[0] = 0;
            for ( int each = 1; each < count - 2;   each) {
                strcat ( string, token[each]);
                if ( each < count - 3) {
                    strcat ( string, " ");
                }
            }

            printf ( "-  %-20sgram:=   calorie:=\n", number, string, gram, calorie);
        }
        fclose ( pf);
        free ( token);
    }
    else {
        perror ( filename);
    }
    return 0;
}
  • Related