如何从c中的文件中读取结构?

时间:2017-01-20 19:43:34

标签: c file struct scanf

我正在创建一个名为“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;
}

5 个答案:

答案 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
        }
    }
}