Как использовать fscanf и fgets из текстового файла со строками и строками? - PullRequest
0 голосов
/ 11 мая 2018

Файл примера:

School Name (with spaces)
FirstNameofStudent StudentID
School Name2 (with spaces)
FirstNameofStudent2 StudentID2
School Name3 (with spaces)
FirstNameofStudent3 StudentID3

Кажется, я не могу понять, что делать после использования fgets для первой строки.

Если само по себе, я могу легко получить название школы, используя fgets и вторая строка сама по себе, используя fscanf, затем преобразует studentID в int, используя atoi.

Но как мне объединить fgets и fscanf?

Отсканированная информация будет помещена в массив.

1 Ответ

0 голосов
/ 11 мая 2018

Прежде чем перейти к решению, я хочу отметить, что массив может иметь только один тип. Вы не можете хранить целые числа в массиве символов.

То есть, если вы хотите, чтобы вся эта информация помещалась в одном двумерном массиве, вам необходимо сохранить идентификатор в виде строки. Затем, если вам понадобится целое число, вам нужно будет использовать atoi, как только вы его получите.

Теперь для объединения двух вам понадобится цикл while с fgets в условии, чтобы получить первую строку. Примерно так:

while(fgets(schoolname, 255, fp) != 0){ ... }

Это продолжит извлекать строки до тех пор, пока не произойдет сбой или не достигнет EOF. Однако вы хотите использовать fscanf для второй строки, и для этого вам понадобится строка, подобная этой:

fscanf(fp, "%s %s\n", name, id);

Это означает, что с текущей точки есть две строки, разделенные пробелом и символом новой строки. Сохраните две строки в name и id и сожмите новую строку.

Ключом к переносу новой строки является то, что если вы этого не сделаете, то при следующем запуске fgets будет найден только один символ новой строки.

Что касается хранения элементов в массиве, вам понадобится двухмерный массив строк. Для этого вы можете сделать это фиксированным или динамическим. Для фиксированного, это довольно просто, просто иметь строку типа char students[3][3][80] и просто хранить там вещи, но для динамического, вам нужно будет использовать выделение памяти, указатели и т. Д. С переменной liks char ***students

Вот код, который я использовал для решения вашей проблемы, хотя я предлагаю попробовать сделать это самостоятельно, чтобы освоить его:

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

int main(){
    FILE *fp = fopen("ex.txt", "r");

    if(fp == 0) exit(-1);

    char ***students;

    // Used to check how many students there are
    int studentno = 0;

    // Init students array
    // So far it means 1 ROW, with 3 COLUMNS, each of 80 CHARACTERS
    students = calloc(studentno+1, 3 * 80);

    // Temporary variables for storage
    char schoolname[80];
    char name[20];
    char id[10];

    int i = 0;

    while(fgets(schoolname, 255, fp) != 0){
        studentno++;

        // Retrieve name and id from second line
        fscanf(fp, "%s %s\n", name, id);

        // Cut off newline left from fgets
        schoolname[strlen(schoolname)-2] = 0;

        // Allocate memory for new members of array
        students[i] = malloc(3 * 80);
        students[i][0] = malloc(80);
        students[i][1] = malloc(80);
        students[i][2] = malloc(80);

        // Copy strings received into array
        strcpy(students[i][0], schoolname);        
        strcpy(students[i][1], name);
        strcpy(students[i][2], id);

        // Resize students array for additional students
        students = realloc(students, (size_t) (studentno+1) * 3*80);

        i++;
    }

    // Check students are stored correctly
    for(int i = 0; i < studentno-1; i++){
        printf("%s - %s - %s\n", students[i][0], students[i][1], students[i][2]);
    }
}
...