所以我有一个名为"library"的结构,它存储结构"books"的对象,并由3本书的列表初始化,但当我尝试打印对象的属性时,我会得到一个"分段故障(堆芯倾倒(";错误我知道这意味着我正在尝试访问一些我无法访问的内存,但在这种情况下,我可以正确地访问第一个元素,所以这让我相信我初始化了错误的东西。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXBOOKS 10
typedef struct books
{
char* title;
char* author;
int id;
}book;
typedef struct library
{
int number_of_books;
book* booklist [MAXBOOKS];
}lib;
void storeBook(lib library,book CurrentBook)
{
library.booklist[0] = &CurrentBook;
}
void printLibrary(lib library)
{
for(int i = 0; i < library.number_of_books; i++)
{
printf("Author:%sn",library.booklist[i]->title);
}
}
int main()
{
book b_1 = {"The trial","Kafka",101};
book b_2 = {"The lurking fear","Lovecraft",102};
book b_3 = {"Dora's storytime collection","Valdes",103};
book* list = (book*)malloc(3*sizeof(book));
list[0] = b_1; list[1] = b_2; list[2] = b_3;
lib CurrentLibrary = {3,{list}};
printLibrary(CurrentLibrary);
return 0;
}
booklist1[i] = *(booklist1+i)
,然后是booklist2[i][j] = *(*(booklist2+i)+j)
,如果是j=0
,则是*(*(booklist2+i)+j) = *(*(booklist2+i)+0) = *(booklist2[i]) = *booklist2[i]
booklist2[0]
指向第一行,booklist2[1]
指向第二行,因此,。。。上。
您正在定义一个书本指针数组(2D数组(:book* booklist [MAXBOOKS]
但list
是一个书本数组(1-D数组(。执行此语句后,lib CurrentLibrary = {3,{list}};
list
数组将存储到booklist[0]
行中。但是CCD_ 12的所有其它指针不指向任何元素。但是,您正在访问printLibrary
函数中的booklist[1]
、booklist[2]
和booklist[3]
。这就是Segmentation错误的原因。
要了解更多信息(对于二维阵列(,请打印以下行:
CCD_ 17打印->标题审判CCD_ 18打印->标题潜伏的恐惧printf("Title %sn", library.booklist[0][2].title);
打印-->标题多拉的故事时间收集
但尝试访问时,library.booklist[1][0].title
会抛出分段错误,因为第二行指针并没有指向任何元素。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXBOOKS 10
typedef struct books
{
char* title;
char* author;
int id;
}book;
typedef struct library
{
int number_of_books;
book *booklist; // It should be 1-D array, since you are passing 1-D array of book
}lib;
void storeBook(lib library,book CurrentBook)
{
library.booklist[0] = CurrentBook;
}
void printLibrary(lib library)
{
for(int i = 0; i < library.number_of_books; i++)
{
printf("Title:%sn",library.booklist[i].title);
printf("Author:%sn",library.booklist[i].author);
printf("Book ID:%dn",library.booklist[i].id);
}
}
int main()
{
book b_1 = {"The trial","Kafka",101};
book b_2 = {"The lurking fear","Lovecraft",102};
book b_3 = {"Dora's storytime collection","Valdes",103};
book* list = malloc(3*sizeof(book));
list[0] = b_1; list[1] = b_2; list[2] = b_3;
lib CurrentLibrary = {3,list}; // list is 1-D array of book
printLibrary(CurrentLibrary);
return 0;
}
输出:
Title:The trial
Author:Kafka
Book ID:101
Title:The lurking fear
Author:Lovecraft
Book ID:102
Title:Dora's storytime collection
Author:Valdes
Book ID:103
尝试一下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXBOOKS 10
typedef struct book
{
char *title;
char *author;
int id;
} Book;
typedef struct lib
{
int length;
Book *list[MAXBOOKS];
} Library;
void freeBook(Book *b)
{
free(b->title);
free(b->author);
free(b);
}
void freeLibrary(Library *l)
{
for (int i = 0; i < l->length; i++)
{
freeBook(l->list[i]);
}
free(l);
}
Book* newBook(char* title, char* author, int id){
// param check
if( !title || !author || id<0 ){
return NULL;
}
// allocate memory
Book* b = malloc(sizeof(Book));
b->title = malloc(sizeof(char) * strlen(title) + 1);
b->author = malloc(sizeof(char) * strlen(author) + 1);
// copy data into struct
strcpy(b->title, title);
strcpy(b->author,author);
b->id = id;
// Send back new book
return b;
}
Library *newLibrary()
{
// allocate memory
Library *l = malloc(sizeof(Library));
l->length = 0;
// return new Library
return l;
}
void addBook(Library** library, Book* toAdd){
// Make sure there is a book to add
if (toAdd == NULL){
printf("ERROR: Attempted To Add Invaild Book.n");
}
// check if library is NULL
else if (*library == NULL){
printf("ERROR: Library is NULL.n");
freeBook(toAdd);
}
// Check if library is full
else if( (*library)->length >= 10 ){
printf("nERROR: Library is full. Cannot Store:nnTitle: %snAuthor: %snID: %dnn",toAdd->title,toAdd->author,toAdd->id);
freeBook(toAdd);
}
else
{
(*library)->list[(*library)->length] = toAdd;
(*library)->length++;
}
}
void printLibrary(Library* library)
{
printf("n------LIBRARY------n");
for (int i = 0; i < library->length; i++)
{
printf("nTitle: %snAuthor: %snID: %dn", library->list[i]->title, library->list[i]->author, library->list[i]->id);
}
printf("nn");
}
int main()
{
Library *library = newLibrary();
addBook(&library, newBook("The trial", "Kafka", 101));
addBook(&library, newBook("The lurking fear", "Lovecraft", 102));
addBook(&library, newBook("Dora's storytime collection", "Valdes", 103));
//UNCOMMENT IF WANTING TO SEE MAXED OUT LIBRARY
/*addBook(&library, newBook("The trial", "Kafka", 101));
addBook(&library, newBook("The lurking fear", "Lovecraft", 102));
addBook(&library, newBook("Dora's storytime collection", "Valdes", 103));
addBook(&library, newBook("The trial", "Kafka", 101));
addBook(&library, newBook("The lurking fear", "Lovecraft", 102));
addBook(&library, newBook("Dora's storytime collection", "Valdes", 103));
addBook(&library, newBook("The trial", "Kafka", 101));*/
// UNCOMMENT TO TEST OVER LIBRARY CAPACITY
//addBook(&library, newBook("The trial", "Kafka", 101));
printLibrary(library);
freeLibrary(library);
return 0;
}
编辑:我刚刚看到这是在我发布并刷新页面后得到的回复。不过,该代码是一个有效的解决方案,可以正确管理内存,并处理使用结构处理数据时出现的大多数错误。
好吧,首先要说的是,我试图通过做出最小的更改集,并指出您做出错误(或不可理解(事情的地方,来让您的代码正常工作。首先,您已经在程序上为书籍预订了空间,因为您已经在main中创建并初始化了三个类型为struct book
的实例,所以您可以将它们的引用分配给lib
对象,而无需为它们分配空间,也无需为数组分配空间,因为数组已经在lib
结构中分配了空间,所以当您在main中新建lib
对象时,也可以只使用这些实例的地址初始化数组,方法如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXBOOKS 10
typedef struct books
{
char* title;
char* author;
int id;
}book;
typedef struct library
{
int number_of_books;
book* booklist [MAXBOOKS];
}lib;
void storeBook(lib library,book CurrentBook)
{
library.booklist[0] = &CurrentBook;
}
void printLibrary(lib library)
{
for(int i = 0; i < library.number_of_books; i++)
{
printf("Author:%sn",library.booklist[i]->title);
}
}
int main()
{
book b_1 = {"The trial","Kafka",101};
book b_2 = {"The lurking fear","Lovecraft",102};
book b_3 = {"Dora's storytime collection","Valdes",103};
/* book* list = (book*)malloc(3*sizeof(book)); // no need to call malloc, you have already reserved memory above (and intialized it) */
/* just use the addresses of the books in the library array of pointers */
lib CurrentLibrary = { 3, { &b_1, &b_2, &b_3 }};
/* list[0] = b_1; list[1] = b_2; list[2] = b_3; */
/* lib CurrentLibrary = {3,{list}}; */
printLibrary(CurrentLibrary); /* BEWARE: you are making a copy of the library structure and passing it by value, it is cheaper to pass a reference */
return 0;
}
BEWARE:
注释指出了这样一个事实,即通过值传递lib
结构(将lib
对象复制到函数中,并在函数中使用副本(在printLibrary()
函数中仅声明对对象的引用更有效,方法是将其声明为:
void printLibrary(lib *library)
{
...
然后用调用
...
printLibrary(&CurrentLibrary);
因为这将只复制引用(比你传递的整个东西小,必须复制(
如果你想使用动态分配的内存,调用malloc来完成所有这些,那么你最好使用这种方法:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXBOOKS 10
typedef struct books {
char* title;
char* author;
int id;
} book;
typedef struct library {
int number_of_books;
book* booklist [MAXBOOKS];
} lib;
void panic(char *str)
{
fprintf(stderr, "PANIC: %sn", str);
exit(EXIT_FAILURE);
}
book *createBook(char *title, char *author, int id)
{
/* don't cast the value returned by malloc() */
/* first create the structure */
book *ret_val = malloc(sizeof *ret_val);
if (ret_val == NULL) {
panic("couldn't allocate memory for book");
}
/* strdup makes a dynamic memory copy of the string
* you passed as parameter */
/* allocate memory and copy the string title to it */
ret_val->title = strdup(title);
if (ret_val->title == NULL) {
panic("couldn't allocate memory for book's title");
}
/* allocate memory and copy the string author to it */
ret_val->author = strdup(author);
if (ret_val->author == NULL) {
panic("couldn't allocate memory for book's author");
}
ret_val->id = id;
return ret_val;
}
lib *createLibrary()
{
lib *ret_val = malloc(sizeof *ret_val);
if (ret_val == NULL) {
panic("couldn't allocate memory for library");
}
/* initialize the number of books to 0 */
ret_val->number_of_books = 0;
return ret_val;
}
void storeBook(lib *library, book *book)
{
/* check that we can add more books */
if (library->number_of_books >= MAXBOOKS) {
panic("No space left on library for another book");
}
/* then add it (BEWARE that, as the books are freed as part of the
* library destruction, you have only to add books created by
* createBook() */
library->booklist[library->number_of_books++] = book;
}
void printLibrary(lib *library)
{
for(int i = 0; i < library->number_of_books; i++)
{
/* we are using this reference three times below, so we save it
* to facilitate things and calculations. */
book *b = library->booklist[i];
/* separate the books with an empty line after the first. */
if (i > 0) printf("n");
printf("Id: %dn", b->id);
printf("Title: %sn", b->title);
printf("Author: %sn", b->author);
}
}
void freeBook(book *b)
{
/* first free the references ***INSIDE*** book */
free(b->title);
free(b->author);
/* only after that, we can free() the book instance */
free(b);
}
void freeLibrary(lib *library)
{
/* as above, we need to first free() the references to the books,
* calling freeBook() above, then we are able to free the library
* reference */
for(int i = 0; i < library->number_of_books; i++) {
freeBook(library->booklist[i]);
}
free(library);
}
int main()
{
lib *CurrentLibrary = createLibrary();
/* create the book and store it in a shot */
storeBook(CurrentLibrary,
createBook("The trial", "Kafka", 101));
storeBook(CurrentLibrary,
createBook("The lurking fear", "Lovecraft", 102));
storeBook(CurrentLibrary,
createBook("Dora's storytime collection", "Valdes", 103));
printLibrary(CurrentLibrary);
freeLibrary(CurrentLibrary);
return EXIT_SUCCESS;
}