Как заставить fscanf читать из файла .csv, читая каждый раздел между запятыми и каждой строкой в ​​строке? - PullRequest
0 голосов
/ 13 мая 2019

Я пишу программу для чтения карты из файла .csv, и я хочу прочитать каждый раздел файла, а затем записать информацию из него в соответствующую структуру в 2D-массиве. Я использую fscanf, чтобы получить количество строк и столбцов, чтобы распределить массив по структурам, и могу прочитать первое значение до запятой и разобраться с ним. Тем не менее, также могут быть пустые поля, которые появляются в строке, например, 1 коза, 2 кошка Моя программа читает «1» и «козел» и справляется с этим, но затем сканируется только кошка. Я хочу, чтобы он прочитал 2 запятые, узнал, что в них ничего нет, а затем перешел к коту и прочитал его, прежде чем перейти к следующей строке

Я не знаю, как сделать правильные спецификации формата для fscanf. В настоящее время у меня есть fscanf(fp, "%[^,]", animal);

/*scans file until comma, writes the scanned text into array*/

              fscanf(fp, "%[^,]", animal);
              printf("Scanned in string for y (%d) and x %d = (%s)\n", j, k, anima;l);
              if (strcmp(animal, "") != 0)
              {   
                  /*if first character is lowercase, change to upper)*/
                  if(animal[0]>90)
                  {
                      animal[0]=animal[0]-32;
                  }
                  /*Checks if item is cat goat or mouse by checking 1st letter of the scanned in array is C G or M*/                     
                  if(strncmp(animal,"C", 1) == 0)             
                  {
                      /*copies name of the animal into the struct*/
                      strcpy(animalarray[j][k].name, "Cat");

                      /*write animal name into struct*/
                      token =strtok(animal, spaceDelimeter);
                      /* The 1 is already dealt with, can be moved past*/
                      token = strtok(NULL, commaDelimeter);
                      printf("token = %s\n", token);


                      animalarray[j][k].number= atoi(token); 


                      printf("Animal is %s, number is %d\n", animalarray[j][k].name, animalarray[j][k].number);
                  }  

Входной файл ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2,3 1 коза ,, 2 кота 3 мыши, 5 коз,

Выход при запуске

rows  2, columns  3 
Scanned in string for row 0 and column 0 = 1 goat
token = goat
Animal is goat, number is 1
Scanned in string for row 0 and column 1 = 2
token = (null)
Segmentation fault (core dumped)

должно быть

...
Scanned in string for row 0 and column 1 = "blank"
Scanned in string for row 0 and column 1 = 2 cat
...

1 Ответ

1 голос
/ 13 мая 2019

fscanf не может сканировать пустые строки, но вы можете использовать возвращаемое значение, чтобы определить, было ли что-либо отсканировано вообще:

FILE *f = fopen(filename, "r");
char buf[80];
int row = 0;
int col = 0;

while (1) {
    int n = fscanf(f, "%79[^,\n]", buf);

    if (n == EOF) break;
    if (n == 0) *buf = '\0';

    printf("[%d, %d] '%s'\n", row, col, buf);

    if (fgetc(f) == ',') {
        col++;
    } else {
        col = 0;
        row++;
    }
}

Если ничего не было обработано, n равно 0 - в этомВ этом случае код явно очищает входную строку, записывая нулевой терминатор в первом символе.Строки и столбцы определяются по тому, была ли прочитана запятая или новая строка.(Следующим символом может быть только запятая, новая строка или конец файла.)

Другая возможность состоит в том, чтобы прочитать строку ввода с помощью fgets, а затем отсканировать каждую строку.Функция сканирования строк sscanf имеет те же ограничения, что и fscanf, поэтому может быть лучше использовать строковые функции, такие как strchr.Здесь я использовал strcspn из <string.h>, который считает символы в строке до тех пор, пока не будет найден какой-либо из заданных символов или конец строки.Это делает его очень похожим на формат %[^n ...] в fscanf:

FILE *f = fopen(filename, "r");
char line[80];
int row = 0;

while (fgets(line, sizeof(line), f)) {
    int col = 0;
    int offset = 0;

    while (line[offset]) {
        int next = strcspn(line + offset, ",\n");

        printf("[%d, %d] '%.*s'\n", row, col, next, line + offset);
        offset += next + 1;

        col++;
    }

    row++;
}

Опять же, обнаружение столбцов и строк происходит по контексту.

...