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

时间:2022-02-19 21:33:41

I'm just starting on the road the learning C, and ran into some difficulty:

我刚刚开始学习C语言,并遇到了一些困难:

The code listed below is giving me the following error:

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

Attaching to program: `/workfolder/cocoa/c_stuff/bookshelf/build/Debug/bookshelf', process 1674.
Cannot access memory at address 0xa0df194
Cannot access memory at address 0xa0df194

附加到程序:`/ 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;
}

The code compiles properly, and the function runs fine the first time (all the questions get asked and the struct receives the data); but when the user types 'y' to add another book, the mem error occurs.

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

Any ideas where the error is happening?

任何错误发生的想法?

Thanks in advance!

提前致谢!

9 个解决方案

#1


You've only ever allocated memory for the first book in main - after that it tries to write to the next slot in the array, which doesn't point to an allocated block of memory, giving you a seg-fault. You're going to have to allocate memory for each book you want to read in.

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

In addition, since C doesn't know how long an array is, you have to pass that information along into function calls. (And I don't see where you're defining book_count.)

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

You might try something along these lines:

您可以尝试以下这些方面:

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
}

Even better in this situation, would just be using a loop and skipping the whole recursion step.

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

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));
}

#2


Unless I'm reading something wrong, you haven't defined book_count before using it as an array subscript.

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

#3


Within main, you allocated on the stack an array of 100 pointers to the Book Structure. I believe it was your intent to allocate 100 structures and then pass the address to that block of structures to getUserInput

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

Change main to:

将主要更改为:

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

EDIT: OOPS Missed the single Book malloc mentioned in the earlier post. That ones Correct for the first book. If you edit as above and eliminate the if (book_shelf[0]...) check, you'll accomplish your intended results

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

#4


  1. You allocate just space for the firstbook, not for the others (malloc in main)

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

  2. I guess there is some code missing, no declaration and initialization of book_count

    我想有一些代码缺失,没有book_count的声明和初始化

  3. You should use loops instead of recursion

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

  4. Use not recursion but loops for this kind of repetition

    不使用递归,而是循环这种重复

#5


Recursion is probably overkill for this problem where a simple do { ... } while(user keeps answering yes) would do. However the problem you having is in main with your Book *book_shelf[100]. There are several ways you could solve this problem.

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

First change it to an array of Book's like samills suggests:

首先将它更改为一系列书籍,就像萨米尔斯一样:

Book book_shelf[100];

and then change your getUserInput to something like this:

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

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

    //...

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

Or you could use your existing code and change you getUserInput function to look something like this and remove the malloc from main:

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

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

props for correct use of the sizeof operator (I see that thing misused so often it makes my eyes bleed).

正确使用sizeof操作符的道具(我看到那个经常误用的东西让我的眼睛流血)。

#6


As in Josh's answer, by adding the following lines to your code should make it work:

正如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;
}

However, I encourage you not to use the recursive function for getting input. Recursive can lead to difficulties in debugging. You may consider using normal loop instead.

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

Note: I'm assuming the book_count is global variable which has been initialized to 0

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

#7


thanks a lot for the replies!

非常感谢回复!

I realized that I hadn't malloc-ed enough memory to handle more then one element of the struct array (Exactly what Josh is saying). So essentially:

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

Book *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code

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

so the second time around I would hit a memory issue.

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

thanks again!

#8


Looks like your still doing it wrong:

看起来你仍然做错了:

Book *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code

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

book_shelf is only the size of a pointer. When you do the malloc you only allocate one Book at a time. This is wrong. You need to allocate contiguous memory for an array of Book objects all in one instanciation of an array.

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

Like

Book book_shelf[100];

not

Book *book_shelf[100];

or using malloc, use your pointer to point to an array instanciated using
100*malloc(sizeof(Book)).

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

You may get lucky that no other heap memory is allocated in between your malloc(sizeof(Book)) calls and that the memory management system is alocating contiguous memory by default. Also, book_shelf will only point to the last malloced Book structure, not the first one as you indicated you want in your original question.

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

Josh is also not allocating enough memory at one time. Use a linked list if you want to keep extending elements to the end of your book_shelf one-by-one.

Josh也没有同时分配足够的内存。如果要逐个将元素扩展到book_shelf的末尾,请使用链接列表。

#9


factorial with pointer and recursion

带指针和递归的阶乘

#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();

}

#1


You've only ever allocated memory for the first book in main - after that it tries to write to the next slot in the array, which doesn't point to an allocated block of memory, giving you a seg-fault. You're going to have to allocate memory for each book you want to read in.

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

In addition, since C doesn't know how long an array is, you have to pass that information along into function calls. (And I don't see where you're defining book_count.)

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

You might try something along these lines:

您可以尝试以下这些方面:

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
}

Even better in this situation, would just be using a loop and skipping the whole recursion step.

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

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));
}

#2


Unless I'm reading something wrong, you haven't defined book_count before using it as an array subscript.

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

#3


Within main, you allocated on the stack an array of 100 pointers to the Book Structure. I believe it was your intent to allocate 100 structures and then pass the address to that block of structures to getUserInput

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

Change main to:

将主要更改为:

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

EDIT: OOPS Missed the single Book malloc mentioned in the earlier post. That ones Correct for the first book. If you edit as above and eliminate the if (book_shelf[0]...) check, you'll accomplish your intended results

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

#4


  1. You allocate just space for the firstbook, not for the others (malloc in main)

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

  2. I guess there is some code missing, no declaration and initialization of book_count

    我想有一些代码缺失,没有book_count的声明和初始化

  3. You should use loops instead of recursion

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

  4. Use not recursion but loops for this kind of repetition

    不使用递归,而是循环这种重复

#5


Recursion is probably overkill for this problem where a simple do { ... } while(user keeps answering yes) would do. However the problem you having is in main with your Book *book_shelf[100]. There are several ways you could solve this problem.

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

First change it to an array of Book's like samills suggests:

首先将它更改为一系列书籍,就像萨米尔斯一样:

Book book_shelf[100];

and then change your getUserInput to something like this:

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

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

    //...

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

Or you could use your existing code and change you getUserInput function to look something like this and remove the malloc from main:

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

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

props for correct use of the sizeof operator (I see that thing misused so often it makes my eyes bleed).

正确使用sizeof操作符的道具(我看到那个经常误用的东西让我的眼睛流血)。

#6


As in Josh's answer, by adding the following lines to your code should make it work:

正如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;
}

However, I encourage you not to use the recursive function for getting input. Recursive can lead to difficulties in debugging. You may consider using normal loop instead.

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

Note: I'm assuming the book_count is global variable which has been initialized to 0

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

#7


thanks a lot for the replies!

非常感谢回复!

I realized that I hadn't malloc-ed enough memory to handle more then one element of the struct array (Exactly what Josh is saying). So essentially:

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

Book *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code

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

so the second time around I would hit a memory issue.

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

thanks again!

#8


Looks like your still doing it wrong:

看起来你仍然做错了:

Book *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code

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

book_shelf is only the size of a pointer. When you do the malloc you only allocate one Book at a time. This is wrong. You need to allocate contiguous memory for an array of Book objects all in one instanciation of an array.

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

Like

Book book_shelf[100];

not

Book *book_shelf[100];

or using malloc, use your pointer to point to an array instanciated using
100*malloc(sizeof(Book)).

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

You may get lucky that no other heap memory is allocated in between your malloc(sizeof(Book)) calls and that the memory management system is alocating contiguous memory by default. Also, book_shelf will only point to the last malloced Book structure, not the first one as you indicated you want in your original question.

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

Josh is also not allocating enough memory at one time. Use a linked list if you want to keep extending elements to the end of your book_shelf one-by-one.

Josh也没有同时分配足够的内存。如果要逐个将元素扩展到book_shelf的末尾,请使用链接列表。

#9


factorial with pointer and recursion

带指针和递归的阶乘

#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();

}