将指针传递给C中的递归函数

时间:2009-01-21 16:46:39

标签: c memory-leaks recursion

我刚刚开始学习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”以添加另一本书时,会发生mem错误。

发生错误的任何想法?

提前致谢!

9 个答案:

答案 0 :(得分: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));
}

答案 1 :(得分:2)

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

答案 2 :(得分:2)

在main中,您在堆栈上分配了一个包含指向Book Structure的100个指针的数组。我相信你打算分配100个结构,然后将地址传递给结构块以获取getUserInput

将main更改为:

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

编辑:OOPS错过了前一篇文章中提到的单一书籍malloc。那些正确的第一本书。如果你编辑如上并消除 如果(book_shelf [0] ...)检查,您将完成预期的结果

答案 3 :(得分:1)

  1. 您只为第一本书分配空间,而不为其他人分配空间(主要的malloc)

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

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

  4. 使用not recursion但循环进行此类重复

答案 4 :(得分:1)

对于这个问题来说,递归可能有点过头了,其中一个简单的do {...} while(用户一直回答是)会这样做。但是你遇到的问题主要在于你的Book * book_shelf [100]。有几种方法可以解决这个问题。

首先将它更改为像's sillills这样的Book数组:

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操作符的道具(我看到那个经常被滥用的东西让我眼睛流血)。

答案 5 :(得分: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

答案 6 :(得分:0)

非常感谢你的回复!

我意识到我没有malloc-ed足够的内存来处理结构数组的一个元素(正是Josh所说的)。基本上是这样的:

Book * book_shelf;

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

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

再次感谢!

答案 7 :(得分:0)

看起来你仍然做错了:

Book * book_shelf;

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

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

喜欢

Book book_shelf [100];

Book * book_shelf [100];

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

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

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

答案 8 :(得分: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();

}