简体   繁体   中英

C - Loading from file with fgets and sscanf

In a function of my program I am trying to load data from a file into this struct array:

/* database struct */
typedef struct node {
    char       name[MAX];
    char       address[MAX];
    long int   number;
}record_type;

record_type record[100];

The function is as follows:

/* load database from disk */
void load_database() {
    char line[128];

    /* Set up database */
    database = fopen("database.txt", "r+w+a+");
    if(database == NULL) {
        printf("\n\tWARNING: No database found.");
        exit(1);
    }

    /* Get database file from disk */
    while(fgets(line, sizeof(line), database) != NULL) {
        sscanf(line, "%s %s %lu", record[rec_num].name,
            record[rec_num].address, &record[rec_num].number);

        /* keeps track of array size */
        rec_num++;
    }
}

The issue I am having is inconsistencies with sscanf. If I include first and last name I cannot put a space between them or it places the first name in name[] and the last name in address[].

Here is a sample of the data I am trying to input from:

1.  Name: james manes       Address: 220 test addr      Number: 5558889999

I need to get the "james manes" into the name[] field, 220 test addr into the address[] field and 5558889999 into the number field of the struct. Is this possible at all?

Is there a more efficient way of managing this type of input?

scanf("%s"... parses a whitespace delimited string in your input, so if you have spaces in the strings you want to parse, it won't work.

While you could use regexes to get what you want, since you use fixed strings as your markers, you could instead use strstr to pull out your strings:

while(fgets(line, sizeof(line), database) != NULL) {
    char *Name = strstr(line, "Name:");
    char *Address = strstr(line, "Address:");
    char *Number = strstr(line, "Number:");
    if (Name && Address && Number) {
        Name += strlen("Name:");
        *Address = '\0';
        Address += strlen("Address");
        *Number = '\0';
        Number += strlen("Number:");
        strcpy(record[rec_num].name, Name);
        strcpy(record[rec_num].address, Address);
        sscanf(Number, "%lu", &record[rec_num].number);
        rec_num++; } }

Note that this will also pull in all the whitespace around the name and address -- you can trim off leading and trailing whitespace if you want it cleaner.

First of all, you might want to take another look at http://www.cplusplus.com/reference/cstdio/fgets/ . Here you will see that the str argument is a pointer to a buffer (which you provided correctly) and then num is the amount of bytes you want to read max , which you did not provide correctly.

The problem with the amount of bytes passed to fgets in you piece of code is the incorrect use of the sizeof operator. The sizeof operator 'returns', as you probably know, the size of the give type . The type you are passing to sizeof is a pointer type (since an array in C for 99% the same as a pointer). The size of a pointer depends on the system you are running on (32 bits on Intel x86, 64bits on AMD64, 16bits on ATmega AVR, etc). So lets asume that you have a 64 bit machine, you will allow fgets to 'get' 64 bits (ie 8 bytes) of data, which is not what you want. What would be the correct statement then?

while(fgets(line, sizeof(*line)*128, database) != NULL) {
    ...

What I'm doing here is dereferencing the char pointer to a char and multipling by the size of this array.

Then, secondly, your question about if this is possible: yes it is. I would like to ask a question myself now too. Is it necessary to do this in C (ie platform does not support anything different, learning purposes, etc) or can you also implement this in C#, Java, Python. If so I highly suggest you do.

And last but not least you are asking us about the usefulness of your code. That answer is really simple: no. Not in its current or fixed state. The problem you are having and much more complicated are fixed using a 'real' database (like MySQL) + its API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM