José Salgado
José Salgado

Reputation: 119

Read line by line from a file and save in a list C

My problem is to read from a file with 100 lines, each line with 4 fields(separated by 4 spaces), which looks like this:

0007 0007 NOVO BANCO, SA Bancos

0008 0008 BANCO BAI EUROPA, SA Bancos

0010 0010 BANCO BPI, SA Bancos

etc...

After doing this i have to save it in a linked list.

Atm i have this:

struct list{
    int code1;
    int code2;
    char name[100];
    char type[100];
    struct list *next, *current;    
};

int main()
{

    FILE *fp1;
    struct list iban;

    fp1 = fopen("ibanlist.txt", "r");
    if(fopen == NULL)
    {
         printf("Error!");
    }

    fscanf(fp1, /*what should i do here?*/, iban.code1, iban.code2, iban.name, iban.type);
    //should i use fgets and sscanf instead?

    fclose(fp1);
    return 0;
}

My problem is how to read from the file with the spaces. For example in the third field it has a space after the ','. Also its the first time im using lists, can anyone give me a head start how to do it?

Upvotes: 0

Views: 71

Answers (2)

Weather Vane
Weather Vane

Reputation: 34575

This uses strstr to tokenise the input string. The first delimiter in the data is only 3 spaces, the rest are 4, so in each case I look for 3 and then advance past all consecutive spaces.

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

struct list{
    int code1;
    int code2;
    char name[100];
    char type[100];
};

int main(void)
{
    FILE *fp;
    char str [1000];
    char *aptr, *bptr, *cptr;
    struct list rec;

    if ((fp = fopen("file.txt", "rt")) == NULL)
        return 1;

    while(fgets(str, sizeof str, fp) != NULL) {
        // break the input line
        aptr = strstr(str, "   ");              // isolate first field
        if(aptr == NULL)
            return 1;
        *aptr++ = '\0';
        while (*aptr == ' ')
            aptr++;

        bptr = strstr(aptr, "   ");             // isolate second field
        if(bptr == NULL)
            return 1;
        *bptr++ = '\0';
        while (*bptr == ' ')
            bptr++;

        cptr = strstr(bptr, "   ");             // isolate third field
        if(cptr == NULL)
            return 1;
        *cptr++ = '\0';
        while (*cptr == ' ')
            cptr++;

        cptr [ strcspn(cptr, "\r\n") ] = 0;    // remove trailing newline etc

        // extract the data
        if(sscanf(str, "%d", &rec.code1) != 1)
            return 1;
        if(sscanf(aptr, "%d", &rec.code2) != 1)
            return 1;
        strcpy(rec.name, bptr);
        strcpy(rec.type, cptr);

        // print the result
        printf("%d/%d/%s/%s\n", rec.code1, rec.code2, rec.name, rec.type);
    }
    fclose(fp);
    return 0;
}

Program output:

7/7/NOVO BANCO, SA/Bancos
8/8/BANCO BAI EUROPA, SA/Bancos
10/10/BANCO BPI, SA/Bancos

Upvotes: 1

M Oehm
M Oehm

Reputation: 29126

You could try to tokenise the string at, say, three or more consecutive spaces. You would then convert the ids with strtol or similar functions.

One way to do so is to search for three spaces with strstr and then skip spaces after that.

The following short program implements a variant of strtok hat splits a string at three or more spaces. Like strtok, it modifies your string, so make sure that you pass a modifiable char array.

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

    char *token(char *str)
    {
        static char *p;
        char *res;

        if (str) p = str;
        if (p == NULL) return p;

        while (*p == ' ') p++;
        if (*p == '\0') return NULL;
        res = p;

        p = strstr(p, "   ");

        if (p && *p) {
            *p = '\0';
            p++;
        }

        return res;
    }

    int main()
    {
        char str[] = "0008   0008    BANCO BAI EUROPA, SA    Bancos";
        char *t;

        t = token(str);
        while (t) {
            puts(t);
            t = token(NULL);
        }

        return 0;
    }

Upvotes: 1

Related Questions