我正在创建一个名为“Book manager”的程序,现在所有需要的是创建从文件中保存和加载Books(结构)的函数。我想知道如何阅读它们。 这是我的结构定义:
typedef
struct book {
char * title;
char * authorName;
char * authorSurname;
int releaseYear;
char * genre;
int flags[10];
} Book;
我已经创建了一个允许我从文件中读取一本书的功能,但它很糟糕,我不知道如何阅读一套书籍。 我想把它读到我的阵列。
Book allBooks[LIBRARY_SIZE];
我想从外观中读取的示例文件:
Christine,Stephen,King,1980,Horror
Harry Potter,J.K,Rowling,2000,Fantasy
有什么想法吗?
编辑:这就是我试图阅读简单的书籍(开始时,profesor说这就足够了)在读这篇文章时不要自杀。
void loadBook(Book * book, FILE * plik){
char jakasTablica[50];
char jakasTablica2[50];
char jakasTablica3[50];
char jakasTablica4[50];
int i = 0;
char znak;
fscanf(plik,"%c",&znak);
while(znak != ','){
jakasTablica[i] = znak;
i += 1;
fscanf(plik,"%c",&znak);
}
jakasTablica[i] = '\0';
strcpy(book->title, jakasTablica);
i = 0;
fscanf(plik,"%c",&znak);
while(znak != ','){
jakasTablica2[i] = znak;
i += 1;
fscanf(plik,"%c",&znak);
}
jakasTablica2[i] = '\0';
strcpy(book->authorName, jakasTablica2);
i = 0;
fscanf(plik,"%c",&znak);
while(znak != ','){
jakasTablica3[i] = znak;
i += 1;
fscanf(plik,"%c",&znak);
}
jakasTablica3[i] = '\0';
strcpy(book->authorSurname, jakasTablica3);
i = 0;
fscanf(plik,"%c",&znak);
while(znak != ','){
jakasTablica4[i] = znak;
i += 1;
fscanf(plik,"%c",&znak);
}
jakasTablica4[i] = '\0';
strcpy(book->genre, jakasTablica4);
i = 0;
int zmienna = 0;
fscanf(plik, "%d", &zmienna);
book->releaseYear = zmienna;
}
答案 0 :(得分:3)
要回答如何阅读每个以逗号分隔的行,请执行以下操作:
#include <stdio.h>
#include <string.h>
int main (void)
{
FILE *fp;
char a[30], b[30], c[30], d[30], e[30];
char line[100];
fp=fopen("./data.txt", "r");
fgets( line, sizeof(line), fp );
sscanf( line, "%29[^,],%29[^,],%29[^,],%29[^,],%29[^,]", a,b,c,d,e );
printf( "%s %s %s %s %s\n", a,b,c,d,e);
fclose( fp );
return( 0 );
}
这将只读取一行,但您可以将其放入循环中,并根据需要一次处理该行一行。这可能不是最快的方法,但只要您知道每行的格式,它就非常简单。
其中包含,
的图书标题怎么样?也许您最好使用CSV parsing library.如果您使用类似的库,则必须将"
放在包含{{1}的任何字段周围在将其写入文本文件之前,以便CSV解析器可以处理它。
您可以直接使用fread()/ fwrite()结构使用二进制文件I / O.您将不得不使用固定大小的结构。下面是一个简单的例子。它没有做所有必要的错误检查,但它应该足以让你开始。
,
答案 1 :(得分:2)
OP希望将逗号分隔文本的行读入自定义struct
。
强烈建议将读数与解析分开。
char buffer[LINE_SIZE];
if (fgets(buffer, sizeof buffer, plik) == NULL) return ...;
然后解析该行并返回一个值,表示1:成功,0:失败或文件结束:EOF
// void loadBook(Book * book, FILE * plik){
int loadBook(Book * book, FILE * plik) {
现在解析buffer[]
。 许多方法有各种优点和缺点。以下内容大量使用"%n"
将扫描的偏移量保存到该点。
#define LINE_SIZE 512
// scan until encountering a comma or linefeed
#define FS "%*[^,\n]%n"
#define FI "%d %n"
int loadBook(Book * book, FILE * plik) {
memset(book, 0, sizeof *book); // zero fill
char buffer[LINE_SIZE];
if (fgets(buffer, sizeof buffer, plik) == NULL) {
return EOF;
}
int n1, n2, n3, n4, n5, i;
n5 = 0;
sscanf(buffer, FS "," FS "," FS "," FI "," FS,
&n1, &n2, &n3, &i, &n4, &n5);
// If scan was incomplete or did not finish on a \n, return 0
if (n5 == 0 || buffer[n5] != '\n') return 0;
// Let us use a check for a sane year as a data qualifier test
// https://wiganlanebooks.co.uk/blog/interesting/
// 10-of-the-oldest-known-surviving-books-in-the-world/
if (i < -600 || i > 2999) return 0;
buffer[n1] = 0; book->title = strdup(buffer);
buffer[n2] = 0; book->authorName = strdup(buffer + n1 + 1);
buffer[n3] = 0; book->authorSurname = strdup(buffer + n2 + 1);
book->releaseYear = i;
buffer[n5] = 0; book->genre = strdup(buffer + n4 + 1);
return 1;
}
strdup()
是一个常见但非标准的函数,它分配内存并复制字符串。 Sample code完成book
后,请确保释放已分配的空间。
答案 2 :(得分:1)
这就是我使用奇美拉代码解决问题的方法。
void readBooks(Book * List){
FILE * plik;
plik=fopen("booksList.txt","r");
int iloscKsiazekDoDodania;
char pom;
pom = fgetc(plik);
while(!feof(plik)){
if(pom == '\n') iloscKsiazekDoDodania += 1;
pom = fgetc(plik);
}
printf("%d\n", iloscKsiazekDoDodania);
fclose(plik);
plik = fopen("booksList.txt","r");
for(int i = 0; i < iloscKsiazekDoDodania; i++){
char a[50], b[50], c[50], d[50];
char line[100];
int x;
fgets(line, 99, plik);
sscanf(line, "%[^,],%[^,],%[^,],%[^,],%d", a,b,c,d,&x);
addRandom(a,b,c,x,d,List);
}
fclose(plik);
}
和我的写作功能:
void saveBooks(Book * List){
FILE * plik;
plik=fopen("booksList.txt","w");
for(int i = 0; i < allBooksSize; i++){
fprintf(plik,"%s,", List[i].title);
fprintf(plik,"%s,", List[i].authorName);
fprintf(plik,"%s,", List[i].authorSurname);
fprintf(plik,"%s,", List[i].genre);
fprintf(plik,"%d\n", List[i].releaseYear);
}
fclose(plik);
}
感谢您的帮助。
答案 3 :(得分:0)
将您的图书定义更改为:
typedef
struct book {
char title[50];
char authorName[50];
char authorSurname[50];
int releaseYear;
char genre[50];
int flags[10];
} Book;
然后在loadBook中:
...
int n;
for (n= 0; n < LIBRARY_SIZE; ++n) {
...
Book[n].title[i] = znak;
...
等。
祝你好运。答案 4 :(得分:-1)
您可以使用以下示例从C中的文件读取结构:
if ( myFile.is_open( ) )
{
while ( getline( myFile, reading ) )
{
stringstream eachline( reading ) ;
while ( eachline( ) )
{
string x = ',';
getline( eachline, StoreData, x ) ;
// read if float or read else word from file
// Increment++ here
}
}
}