Home > Mobile >  Load string containing words from file
Load string containing words from file

Time:09-30

I need to load strings from file into a struct array.

CORRECT OUTPUT:

4
Sarajevo,345123
Tuzla,123456
Mostar,101010
Banja Luka,234987

MY OUTPUT:

1
Sarajevo 345123
Tuzla 123456
Mostar 101010
Banja Luka 234987,544366964

Code:

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

struct City {
  char name[31];
  int number_of_citizen;
};

int load(struct City cities[100], int n) {
  FILE *fp = fopen("cities.txt", "r");
  int i = 0;
  while (fscanf(fp, "%[^,]s %d\n", cities[i].name, &cities[i].number_of_citizen)) {
    i  ;
    if (i == n)break;
    if (feof(fp))break;
  }
  fclose(fp);
  return i;
}
int main() {
  int i, number_of_cities;
  struct City cities[10];
  FILE* fp = fopen("cities.txt", "w");
  fputs("Sarajevo 345123", fp); fputc(10, fp);
  fputs("Tuzla 123456", fp); fputc(10, fp);
  fputs("Mostar 101010", fp); fputc(10, fp);
  fputs("Banja Luka 234987", fp);
  fclose(fp);
  number_of_cities = load(cities, 10);
  printf("%d\n", number_of_cities);
  for (i = 0; i < number_of_cities; i  )
    printf("%s,%d\n", cities[i].name, cities[i].number_of_citizen);
  return 0;
}

Could you explain me how to fix this? Why my program only loaded 1 city?

CodePudding user response:

The fscanf() conversion string is incorrect: instead of "%[^,]s %d\n" you should use:

while (i < n && fscanf(fp, "0[^,],%d",
                       cities[i].name,
                       &cities[i].number_of_citizen) == 2) {
    i  ;
}

Or better:

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

int load(struct City cities[], int n) {
    char buf[200];
    int i = 0;
    char ch[2];
    FILE *fp = fopen("cities.txt", "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", "cities.txt",
                strerror(errno));
        return -1;
    }
    while (i < n && fgets(buf, sizeof buf, fp)) {
        if (sscanf(buf, "0[^,],%d%1[\n]",
                   cities[i].name,
                   &cities[i].number_of_citizen, ch) == 3) {
            i  ;
        } else {
            fprintf(stderr, "invalid record: %s\n", buf);
        }
    }
    fclose(fp);
    return i;
}

Also change your main function to output commas between the city names and population counts:

int main() {
    int i, number_of_cities;
    struct City cities[10];
    FILE *fp = fopen("cities.txt", "w");
    if (fp) {
        fputs("Sarajevo,345123\n", fp);
        fputs("Tuzla,123456\n", fp);
        fputs("Mostar,101010\n", fp);
        fputs("Banja Luka,234987\n", fp);
        fclose(fp);
    }
    number_of_cities = load(cities, 10);
    printf("%d\n", number_of_cities);
    for (i = 0; i < number_of_cities; i  )
        printf("%s,%d\n", cities[i].name, cities[i].number_of_citizen);
    return 0;
}

EDIT: since there are no commas in the database file, you must use a different parsing approach:

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

int load(struct City cities[], int n) {
    char buf[200];
    int i = 0;
    FILE *fp = fopen("cities.txt", "r");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", "cities.txt",
                strerror(errno));
        return -1;
    }
    while (i < n && fgets(buf, sizeof buf, fp)) {
        /* locate the last space */
        char *p = strrchr(buf, ' ');
        if (p != NULL) {
            /* convert it to a comma */
            *p = ',';
            /* convert the modified line */
            if (sscanf(buf, "0[^,],%d",
                       cities[i].name,
                       &cities[i].number_of_citizen) == 2) {
                i  ;
                continue;
            }
        }
        fprintf(stderr, "invalid record: %s", buf);
    }
    fclose(fp);
    return i;
}
  • Related