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」と入力して別の本を追加すると、mem エラーが発生します。

エラーが発生している場所はありますか?

前もって感謝します!

4

9 に答える 9

10

メインの最初の本にのみメモリを割り当てました-その後、割り当てられたメモリブロックを指していない配列の次のスロットに書き込もうとし、セグメンテーションフォールトを引き起こします。読みたい本ごとにメモリを割り当てる必要があります。

さらに、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 内で、Book 構造体への 100 個のポインターの配列をスタックに割り当てました。100個の構造を割り当ててから、その構造のブロックにアドレスを渡して getUserInput にすることがあなたの意図だったと思います

メインを次のように変更します。

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

編集: おっと、以前の投稿で言及された単一の 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(user は yes と答え続ける) で済むこの問題では、おそらく再帰はやり過ぎです。しかし、あなたが抱えている問題は主にあなたの本 *book_shelf[100] にあります。この問題を解決する方法はいくつかあります。

まず、samills が示唆するような 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 演算子を正しく使用するための小道具 (よく誤用されて目を出血させます)。

于 2009-01-21T17:02:52.563 に答える
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 に答える
0

返信ありがとうございます!

構造体配列の複数の要素を処理するのに十分なメモリをmallocしていないことに気付きました(まさにJoshが言っていることです)。したがって、本質的に:

本 *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//終了コード

そのため、2 回目にはメモリの問題が発生します。

再度、感謝します!

于 2009-01-21T17:30:36.643 に答える
0

ジョシュの答えのように、次の行をコードに追加すると、機能するはずです。

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

あなたはまだ間違っているようです:

本 *book_shelf;

if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//終了コード

book_shelf はポインターのサイズのみです。malloc を実行すると、一度に 1 つの Book のみが割り当てられます。これは間違っています。配列の 1 つのインスタンス内のすべての Book オブジェクトの配列に連続したメモリを割り当てる必要があります。

お気に入り

本 book_shelf[100];

いいえ

本 *book_shelf[100];

または malloc を使用して、ポインターを使用して、
100*malloc(sizeof(Book)) を使用してインスタンス化された配列をポイントします。

malloc(sizeof(Book)) 呼び出しの間に他のヒープ メモリが割り当てられておらず、メモリ管理システムがデフォルトで連続したメモリを割り当てているという幸運に恵まれるかもしれません。また、 book_shelf は、最初の質問で示した最初の構造ではなく、最後の malloc された Book 構造のみを指します。

また、Josh は一度に十分なメモリを割り当てていません。要素を book_shelf の最後まで 1 つずつ拡張し続ける場合は、リンクされたリストを使用します。

于 2009-01-29T23:13:17.383 に答える