1

リンクされたリストがあり、新しいノードを挿入しようとしていますが、挿入したい場所にノードを挿入することに成功しているようですが、変数は NULL として出力され続けます。誰かが私がこれを引き起こしている場所を指摘できますか?

印刷して挿入する方法は次のとおりです。

void printList(node *head)
{
    node *p;
    p = head;
    if(p->next == NULL)
            printf("No stops currently in the tour.");
    else
    {
            while(p->next != NULL)
            {
                    printf("Tour Stop: %s - Description: %s\n", p->name, p->name);
                    p = p->next;
                            }
    }
}


void insertInOrder(node *head, node *newNode)
{
    printf("What is the stop you want the new stop to come after? Type 'end' to insert at the end of the tour.");
    char key[100];
    scanf("%s", &key);
    getchar();

    node *p;
    p = head->next;
    if(head->next == NULL)
            head->next = newNode;

    else if(key == "end")
    {
            while(p->next != NULL)
                    p = p->next;

            p->next = newNode;
    printf("\nAT 57, newNode->info = %s and newNode->name = %s", newNode->info, newNode->name);
    }

    else
    {
            while(strcmp(p->name, key) != 0)
            {
                    if(p->next == NULL)
                    {
                            printf("Couldn't find the tour stop you requested, inserting at end of tour.");
                            break;
                    }

                    p = p->next;
            }

            p->next = newNode;
    }

そして、これが挿入メソッドに渡すために使用しているcreateNewNodeメソッドです

node* createNewNode()
{
    node *newNode;
    newNode = malloc(sizeof(struct node));

    printf("Enter the name of the new tour stop.\n");
    char newName[100];
    fgets(newName, sizeof(newName), stdin);
    newNode->name = newName;

    printf("Enter information about the tour stop. Max number of characters you can enter is 1000.\n");
    char newDescription[1000];
    newNode->info = newDescription;
    fgets(newDescription, sizeof(newDescription), stdin);
    return newNode;
}
4

3 に答える 3

3

文字列を構造体にコピーしていません。内部のローカル変数にポインタをコピーしているだけですcreateNewNode()

char newName[100];
fgets(newName, sizeof(newName), stdin);
newNode->name = newName;

これは、保存されたポインターが無効になったため、後でアクセスしたときに未定義の動作を意味します。

構造内に文字スペースが必要であり、そこに文字列をコピー (または単に読み取る) して、ノードが存在する限り割り当てられたままにする必要があります。

于 2013-11-05T08:31:05.860 に答える
1

このコードには非常に多くの問題があり、どこから始めればよいかわかりません。

printf("What is the stop you want the new stop to come after? Type 'end' to insert at the end of the tour.");
char key[100];
scanf("%s", &key);
getchar();

文字列を読み取るために scanf を絶対に使用する必要がある場合 (使用しないことをお勧めします)、scanf("%99s", &key) のように、'%s' フォーマット指定子の前に読み取る最大文字数を追加する必要があります。null 終端によって配列がオーバーフローしないように、100 文字ではなく 99 文字を読み取る必要があります。

else if(key == "end")
{
    //code
}

ここでは、キーの内容を const char* "end" と比較する代わりに、単に配列キーのアドレスを const char* "end" のアドレスと比較します。代わりにstrcmpを使用する必要があります 。(またはさらに良いstrncmp

node* createNewNode()
{
    node *newNode;
    newNode = malloc(sizeof(struct node));

    printf("Enter the name of the new tour stop.\n");
    char newName[100];
    fgets(newName, sizeof(newName), stdin);
    newNode->name = newName;

    printf("Enter information about the tour stop. Max number of characters you can enter is 1000.\n");
    char newDescription[1000];
    newNode->info = newDescription;
    fgets(newDescription, sizeof(newDescription), stdin);
    return newNode;
}

ここで、新しいノードの名前と情報ポインターは、 createNewNodeへの呼び出しが返された後に解放されたメモリを指します。これは未定義の動作であり、プログラムがセグメンテーション違反またはさらに悪化する可能性があります。

読み取りバッファーをヒープに割り当てられた新しいものにコピーし、それらを指すようにポインターを設定するか、最初にヒープにバッファーを割り当てる必要があります。

int newDescriptionLength = strlen(newDescription) + 1; //plus 1 for null termination
char* newDescriptionCopy = malloc(newDescriptionLength);
strncpy(newDescriptionCopy, newDescription, newDescriptionLength);
newNode->info = newDescriptionCopy;

strncpyは、ソース文字列 newDescription のすべての文字がコピーされた後、 newDescriptionCopy 文字列が null で終了するようにします。

ノードを解放するときは、割り当てられたバッファを考慮する必要があります。

また、許可されている正確な文字数を指定しても文字列が null で終了しないため、fgets でも 1 文字少なく読み取る必要があります。

プログラムは未定義の動作でいっぱいであり、デバッグ中に仮定を行うのは安全ではないため、問題を深く掘り下げる前に、これらの問題を解決する必要があります。

于 2013-11-05T08:58:23.613 に答える
0

あなたのコードから私が見ることができるもの (リンクされたリストの呼び出し関数または init を出力していない場合) から、最初の要素 (つまり、頭) をチェックしていないようです。したがって、リストが完全に空の場合、head は NULL を指します。したがって、印刷機能を例として使用すると、次のようになります。

void printList(node *head)
{
    node *p;
    p = head;

    // Check if the list contains anything
    if (p == NULL)
    {
        printf("List is empty");
    }
    else
    {
        printf("Tour Stop: %s - Description: %s\n", p->name, p->name); // print first/head element

        // Continue while there are more elements
        while(p->next != NULL)
        {
            printf("Tour Stop: %s - Description: %s\n", p->name, p->name);
            p = p->next;
        }
    }
}

挿入機能でも同じかもしれないので、何も挿入しませんか?

:アンワインドも彼の答えに非常に有効なポイントを持っています

于 2013-11-05T08:43:08.307 に答える