1

我刚开始学习C的道路上,遇到了一些困难:

下面列出的代码给了我以下错误:

附加到程序:`/workfolder/cocoa/c_stuff/bookshelf/build/Debug/bookshelf',进程
1674。
无法访问地址 0xa0df194 的内存 无法访问地址 0xa0df194 的内存

// code start

#define MAX_NAME_LENGTH 200
#define MAX_AUTHOR_LENGTH 200
#define MAX_DESCRIPTION_LENGTH 1000
#define MAX_PUBLISHER 200
#define MAX_ISBN 50


//structures<
typedef struct {
    char title[MAX_NAME_LENGTH];
    char author[MAX_AUTHOR_LENGTH];
    char ISBN[MAX_ISBN];
    char description[MAX_DESCRIPTION_LENGTH];
    char publisher[MAX_PUBLISHER];
} Book;


void getUserInput(Book *s[])
{   
    printf("what is the book's title ?\n");
    fgets(s[book_count]->title, MAX_NAME_LENGTH, stdin);

    printf("what is the author's name?\n");
    fgets(s[book_count]->author, MAX_AUTHOR_LENGTH, stdin);

    printf("what is the ISBN?\n");
    fgets(s[book_count]->ISBN, MAX_ISBN, stdin);

    printf("write a short description\n");
    fgets(s[book_count]->description, MAX_DESCRIPTION_LENGTH, stdin);

    printf("what is the book's publisher\n");
    fgets(s[book_count]->publisher, MAX_PUBLISHER, stdin);

    printf("want to add another book ? Y\\N\n");

    book_count++;

    if(tolower(fgetc(stdin)) == 'y') 
    {
        return getUserInput(s);
    } 
    else 
    {
        return;
    }
}


int main (int argc, const char * argv[]) {
    // insert code here...
    Book *book_shelf[100];

    if((book_shelf[0] = (Book *)malloc(sizeof(Book))) == NULL)
    {
        exit(1);
    }

    getUserInput(book_shelf);

    return 0;
}

代码编译正确,函数第一次运行良好(所有问题都被问到,结构接收数据);但是当用户键入“y”来添加另一本书时,就会发生内存错误。

发生错误的任何想法?

提前致谢!

4

9 回答 9

10

您只为 main 中的第一本书分配了内存 - 之后它尝试写入数组中的下一个插槽,该插槽不指向已分配的内存块,从而给您一个 seg-fault。您将不得不为要阅读的每本书分配内存。

此外,由于 C 不知道数组有多长,因此您必须将该信息传递给函数调用。(而且我看不到您在哪里定义 book_count。)

您可以尝试以下方法:

void getUserInput(Book *s[], int *book_count, int max_book_count)
{
   if (book_count == max_book_count) return; // If we've filled all the slots, we can't add anymore without causing trouble.
   s[book_count] = malloc(sizeof(Book));

   ..

   if(tolower(fgetc(stdin)) == 'y') 
   {
       (*book_count)++;
       getUserInput(s, book_count, max_book_count);
   } 
   return;
}

int main (int argc, const char * argv[]) {
    // insert code here...
    Book *book_shelf[100];

    int book_count = 0;
    getUserInput(book_shelf, &book_count, 100);
    // Make sure to free all the malloc'd data
}

在这种情况下更好的是,只需使用循环并跳过整个递归步骤。

int main (int argc, const char * argv[]) {
    // insert code here...
    Book *book_shelf[100];

    char response = 'y';
    int book_count = 0;
    while (book_count < 100 && response == 'y')
    {
        book_shelf = malloc(sizeof(Book));
        response = getUserInput(book_shelf[book_count++]);
    }
    // make sure to free all the allocated data!
}

char getUserInput(Book *book)
{
   // write input straight to book
   printf("what is the book's title ?\n");
   fgets(book->title, MAX_NAME_LENGTH, stdin);

   ...

   return tolower(fgetc(stdin));
}
于 2009-01-21T16:53:09.713 回答
2

除非我读错了,否则您在将 book_count 用作数组下标之前没有定义它。

于 2009-01-21T16:53:42.193 回答
2

在 main 中,您在堆栈上分配了一个包含 100 个指向 Book Structure 的指针的数组。我相信您的意图是分配 100 个结构,然后将地址传递给该结构块以获取用户输入

将主要更改为:

Book book_shelf[100];
...
getUserInput(book_shelf);
...

编辑:OOPS 错过了前面文章中提到的单 Book malloc。那是正确的第一本书。如果您按上述方式进行编辑并消除 if (book_shelf[0]...) 检查,您将实现预期的结果

于 2009-01-21T16:54:13.253 回答
1
  1. 您只为第一本书分配空间,而不是为其他人分配空间(主中的 malloc)

  2. 我猜缺少一些代码,没有 book_count 的声明和初始化

  3. 您应该使用循环而不是递归

  4. 对于这种重复,不要使用递归,而是使用循环

于 2009-01-21T16:56:45.947 回答
1

对于这个问题,递归可能是矫枉过正的,一个简单的 do { ... } while(用户一直回答是)就可以了。但是,您遇到的问题主要在于您的 Book *book_shelf[100]。有几种方法可以解决这个问题。

首先将其更改为一系列书籍,如 samills 建议的:

Book book_shelf[100];

然后将您的 getUserInput 更改为以下内容:

getUserInput(Book *book_shelf, int offset, int length) {
    if(offset < 0 || offset >= length) {
        return;
    }

    //...

    return getUserInput(book_shelf, offset + 1, length)
}

或者您可以使用现有代码并将 getUserInput 函数更改为如下所示并从 main 中删除 malloc:

getUserInput(Book *book_shelf) {
     book_shelf[book_count] = (Book*)malloc(sizeof(Book));
     // ...
}

正确使用 sizeof 运算符的道具(我看到那个东西经常被滥用,让我的眼睛流血)。

于 2009-01-21T17:02:52.563 回答
0

正如在 Josh 的回答中,通过在您的代码中添加以下几行应该使其工作:

book_count++;

if(tolower(fgetc(stdin)) == 'y') 
{
    if((book_shelf[book_count] = (Book *)malloc(sizeof(Book))) == NULL)
    {
        printf("Cannot allocate memory for Book");
        exit(1);
    }
    return getUserInput(s);
} 
else 
{
    return;
}

但是,我鼓励您不要使用递归函数来获取输入。递归会导致调试困难。您可以考虑改用普通循环。

注意:我假设 book_count 是已初始化为 0 的全局变量

于 2009-01-21T17:01:34.500 回答
0

非常感谢您的回复!

我意识到我没有分配足够的内存来处理结构数组的一个以上元素(正是 Josh 所说的)。所以本质上:

书 *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//退出代码

所以第二次我会遇到内存问题。

再次感谢!

于 2009-01-21T17:30:36.643 回答
0

看起来你仍然做错了:

书 *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//退出代码

book_shelf 只是一个指针的大小。当您执行 malloc 时,您一次只分配一本书。这是错误的。您需要在数组的一个实例中为 Book 对象数组分配连续的内存。

喜欢

书 book_shelf[100];

不是

书 *book_shelf[100];

或使用 malloc,使用指针指向使用
100*malloc(sizeof(Book)) 实例化的数组。

您可能会很幸运,在您的 malloc(sizeof(Book)) 调用之间没有分配其他堆内存,并且内存管理系统默认分配连续内存。此外, book_shelf 将仅指向最后一个分配的 Book 结构,而不是您在原始问题中指出的第一个。

Josh 一次也没有分配足够的内存。如果您想将元素一个接一个地扩展到 book_shelf 的末尾,请使用链表。

于 2009-01-29T23:13:17.383 回答
0

带指针和递归的阶乘

#include<iostream.h>
#include<conio.h>

int show(int *p)

{

int f;

int x=*p;
if(*p==1)  //boundry checking for recursion

return 1;

else

f=x*show(&(--*p)); //this code is similar to f=x*show(n-1); with non-pointers 

return f;

}

void main()

{

int a=6;

int b=show(&a);

cout<<b;

getch();

}
于 2012-01-18T15:47:48.000 回答