在 C 中读取和管理文件中的数据

问题描述 投票:0回答:0
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define MAX_TITLE 100
#define MAX_AUTHORS 60
#define MAX_PUB_NAME 100
#define SIZE_ISBN 15
#define MAX_BOOKS 2000


typedef struct book {
    char title[MAX_TITLE];
    char isbn[SIZE_ISBN];
    char authors[MAX_AUTHORS];
    char publisher[MAX_PUB_NAME];
} BookData;

typedef struct {
    BookData books[MAX_BOOKS];
    BookData isbn_index[SIZE_ISBN];
    int count; // quantidade de elementos preenchidos
} Collection;

char *splitField(char *str) { //função splitField da série de exs anterior
    char *strtst = strchr(str, ';');
    if (strtst != NULL) {
        *strtst = '\0';
        strtst++;
    }
    return strtst;
}

int fillBookData(BookData *b, FILE *f ){
    char line[450];
    if (fgets(line, 450, f) == NULL) { // lê uma linha do arquivo
        return 0; // retorna 0 se não há dados para ler
    }
    // separa os campos da linha com a função splitField
    char *title = splitField(line);
    char *isbn = splitField(NULL);
    char *authors = splitField(NULL);
    char *publisher = splitField(NULL);
    // copia os campos relevantes para a estrutura BookData
    strncpy(b->title, title, MAX_TITLE-1);
    strncpy(b->isbn, isbn, SIZE_ISBN-1);
    strncpy(b->authors, authors, MAX_AUTHORS-1);
    strncpy(b->publisher, publisher, MAX_PUB_NAME-1);
    return 1; // retorna 1 em caso de sucesso
}

void fillCollection(Collection *col, FILE *f){
    char line[450];
    int i=0;
    while(i<MAX_BOOKS && fgets(line, 450, f)!=NULL){ //enquanto i/count for menor que MAX_BOOKS e o fgets ler uma linha
        if(fillBookData(&col->books[i], line)==1) //se a funcao fillBookData conseguir preencher os dados na struct BookData
            i++; //incrementa o valor de livros encontrados no ficheiro
    }
    col->count=i; //o count sera o numero de livros lidos no ficheiro
}

int comparator(const void *book1, const void *book2) {
    const BookData *b1 = (const BookData *)book1;
    const BookData *b2 = (const BookData *)book2;
    return strcmp(b1->title, b2->title); //compara os titulos e retorna o resultado
}

void collSortTitle(Collection *col) {
    qsort(col->books, col->count, sizeof(BookData), comparator);
}   //col->books: ponteiro para o array de livros na colecao
    //col->count: quantidade de livros na colecao
    //sizeof(BookData): tamanho do tipo de dado BookData em bytes
    //comparator: funcao de comparacao utilizada para determinar a ordenacao

void collRefIsbn( Collection *col ){
    qsort(col->isbn_index, col->count, sizeof(BookData*), comparator); //compara os titulos e retorna o resultado
}
    //col->isbn_index: ponteiro para o array de livros na colecao
    //col->count: quantidade de livros na colecao
    //sizeof(BookData): tamanho do tipo de dado BookData em bytes
    //comparator: funcao de comparacao utilizada para determinar a ordenacao

void BookSearch(Collection *col, const char *isbn){
    BookData temp; // cria uma variável temp do tipo BookData
    strncpy(temp.isbn, isbn, SIZE_ISBN-1); //copia o valor de isbn para o campo isbn dessa struct
    temp.isbn[SIZE_ISBN-1] = '\0';

    // utiliza a função bsearch para pesquisar pelo valor de temp no array isbn_index na struct Collection
    BookData *p = (BookData*)bsearch(&temp, col->isbn_index, col->count, sizeof(BookData), comparator);

    // verifica se a pesquisa retornou um ponteiro não nulo
    if(p != NULL){
        // caso tenha retornado um ponteiro não nulo, dá print em stdout das informações do livro correspondente a esse ISBN
        printf("Title: %s\nISBN: %s\nAuthors: %s\nPublisher: %s\n", p->title, p->isbn, p->authors, p->publisher);
    }
}


int strcmp_ic(const char *str1, const char *str2) {
    int i = 0;
    while (str1[i] != '\0' && str2[i] != '\0') { // Loop while para correr as duas strings ate o seu fim
        char string1 = tolower(str1[i]); // Converte para minusculas todos os caracteres da string 1
        char string2 = tolower(str2[i]); // Converte para minusculas todos os caracteres da string 2
        if (string1 != string2) { // Corre o if caso string 1 seja diferente da string 2
            return string1 - string2; // Retorno da diferenca entre as duas strings
        }
        i++; // Incremento de i para percorrer as strings por completo
    }
    return strcmp(str1, str2); // Retorno da funcao strcmp que compara alfabeticamente as duas strings
}

int main(){
    Collection *cl; //representa a colecao
    FILE *f;
    char input;
    char *str;
    char isbn[SIZE_ISBN];

    f=fopen("dados.csv", "r"); //abre o ficheiro no modo leitura
    if(f==NULL){
        printf("Erro ao abrir o ficheiro\n");
        return -1;
    }

    fillCollection(&cl, f);//preenche a colecao com os dados do ficheiro
    fclose(f);//fecha o ficheiro

    do {
        printf("Digite o comando: ");
        scanf("%c %s", &input, &str); //guarda o input do user na variável input e name/isbn caso seja o comando "a" ou "i"
        if (input == 'l') { //verifica se o input foi 'l'
            collSortTitle(&cl); //ordena a coleção
            for(int i=0; i<cl->count; i++){ //dá print aos livros ordenados
                printf("Título: %s\n", cl->books[i].title);
                printf("Autor: %s\n", cl->books[i].authors);
                printf("Editor: %s\n", cl->books[i].publisher);
                printf("ISBN: %s\n", cl->books[i].isbn);
            }
        }
        if (input == 'a' && str[0]!='\0') { // verifica se o input foi 'a'
            collSortTitle(&cl); // meter já os livros por ordem pois quando da print eles teem de estar por ordem
            for(int i=0; str[i]!='\0'; i++)
                str[i]=toupper(str[i]); // torna o nome do autor em maiusculas
            for(int i=0; i < cl->count; i++) { // corre os livros todos
                BookData *book = &cl->books[i];
                char temp[255];
                strcpy(temp, book->authors); // salva na variavel temp os autores presentes
                for(int i=0; temp[i]!='\0'; i++)
                    temp[i]=toupper(temp[i]); // torna o nome do autor tambem em maiusculas para poder ser comparado
                char *author = strtok(temp, ";"); // função que separa em tokens delimitados por ; os autores vindos da estrutura
                while (author != NULL) {
                    if(strcmp_ic(&str, &author) == 0) // verifica se o nome do autor que é procurado coincide com o nome do autor vindo da estrutura
                        printf("Title: %s\nISBN: %s\nAuthors: %s\nPublisher: %s\n", book->title, book->isbn, book->authors, book->publisher); // caso coincida, apresenta em standard output as informacoes do livro
                }
                author = strtok(NULL, ";");  // encontra o próximo token
            }
        }
        if(input == 'i' && str[0]!='\0'){
            strcpy(isbn, str);
            BookSearch(&cl, isbn); //procura e da print as informacoes do livro com o isbn indicado pelo comando
        }
    } while (input!='q'); //caso input nao tenha sido 'l' verifica se foi 'q' e caso seja termina o programa
    //enquanto input nao for 'q' o programa continua a correr
    return 0;
}

我做了这个程序,它应该从文件中读取书籍的详细信息,但它甚至没有到达第一个 printf 语句。 我知道错误是当我第一次调用

fillCollection
函数时因为我已经删除了它并且它到达了第一个 printf 但我需要该函数否则程序什么都不做因为这是从中获取书籍数据的函数文件。

文件这一行供参考:

C 编程语言;0131103628;9780131103627;Brian W. Kernighan,Dennis M. Ritchie;Prentice Hall;语言,编程;272;1988-04-01;平装本;67.00 美元

每当我尝试运行它时,我都会收到此消息:

Process returned -1073741819 (0xC0000005)   execution time : 0.849 s
Press any key to continue.

我已经在 VSC 中进行了调试,并且在行中出现了“Segmentation Fault”

if (fgets(line, 450, f) == NULL) { // lê uma linha do arquivo

fillBookData
功能。

根据我的研究,它似乎与内存分配有关,但我似乎无法解决它。

c struct memory-management
© www.soinside.com 2019 - 2024. All rights reserved.