Текстовый файл языка C в массив структур

У меня есть текстовый файл, который содержит номера учеников, имя и точку построчно. Я пытаюсь добавить эти строки в массив структур.

Пример данных в data.txt

723269,Lincoln Burgess,32
543256,Amayah Burnett Bush,63
751201,Robert Downey Jr,73
...
...

Мой код

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

#define STUDENT_SIZE 273

typedef struct {
  int stNo, points;
  char name[40];
} Student;

int readTxtFile(const char *filename, Student *students) {
  FILE *fin = fopen(filename, "r");
  if (!fin) {
    printf("Can't open file: %s\n", filename);
    return 0;
  }
  int i = 0;
  while (fscanf(fin, "%d,%s,%d",
                &students[i].stNo,
                students[i].name,
                &students[i].points) == 10)
    ++i;

  fclose(fin);
  return i;
}

void printArray(Student *students, int size) {
  for (int i = 0; i < size; i++) {
    Student *st = &students[i];
    printf("%d,%s,%d\n", st->stNo, st->name, st->points);
  }
}

int main() {
  Student students[STUDENT_SIZE];
  char myFile[] = "/Users/can/clang/practice/data.txt";
  int size = readTxtFile(myFile, students);
  printArray(students, size);
  return 0;
}

Код не выдает ошибку, но ничего не выводит на консоль.


c
person bomi    schedule 02.12.2020    source источник
comment
Формат %s с scanf читает только слова, разделенные пробелами. Вам нужен другой способ чтения ввода, содержащего пробелы.   -  person Some programmer dude    schedule 02.12.2020
comment
Почему == 10? Вы делаете только 3 конверсии, поэтому вам следует проверить == 3.   -  person G. Sliepen    schedule 02.12.2020
comment
поскольку fscanf работает только для слов, разделенных пробелами, вы можете использовать getline и разберите строку в свою структуру   -  person IrAM    schedule 02.12.2020
comment
fscanf никогда не возвращает 10, поэтому цикл while никогда не выполняется. я остается на нуле. Ничего не печатается. Также %s немного не подходит для чтения вашего ввода. Вместо этого попробуйте while(fscanf(fin, "%d,%[^,],%d", ...) == 3)   -  person L. Scott Johnson    schedule 02.12.2020


Ответы (1)


Если вы можете использовать вызовы POSIX в своей системе, вы можете использовать функцию getline.

getline очень удобно, если нам нужно прочитать строки из файла. Затем мы должны проанализировать строку в соответствии с нашим требованием.

Ниже я добавил то, что работает для вашего требования.

со страницы руководства getline вам придется использовать эти макросы в начале.

Since glibc 2.10:
   _POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
   _GNU_SOURCE

нравится #define _POSIX_C_SOURCE 200809L


int readTxtFile(const char *filename, Student *students) {
  FILE *fin = fopen(filename, "r");
  if (!fin) {
    printf("Can't open file: %s\n", filename);
    return 0;
  }
  int i = 0;
  
  char *lineptr = NULL;
  size_t size = 0;
  /*
  ssize_t getline(char **lineptr, size_t *n, FILE *stream);
  while (fscanf(fin, "%d%s %d",
                &students[i].stNo,
                students[i].name,
                &students[i].points))
                */
                
                
    while(getline(&lineptr, &size,fin) != -1)
    {
        parse_line_to_struct_members(lineptr, &students[i].stNo, students[i].name,&students[i].points);
        i++;
    }
  free(lineptr);
  lineptr = NULL;
  fclose(fin);
  return i;
}

void parse_line_to_struct_members(char* line, int *num, char* name, int *points)
{
    char* tok = NULL;
    
    // stNo
    tok = strtok(line, ",");
    if(tok)
        *num = atoi(tok);

    //name
    tok = strtok(NULL, ",");
    if(tok)
        strcpy(name, tok);
    
    //points
    tok = strtok(NULL, ",");
    if(tok)
        *points = atoi(tok);
}
person IrAM    schedule 02.12.2020