#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
功能。
根据我的研究,它似乎与内存分配有关,但我似乎无法解决它。