【问题标题】:Linked lists Node being overwritten incorrectly链表节点被错误覆盖
【发布时间】:2018-04-04 07:30:41
【问题描述】:

我正在使用链表在 C 中创建一个音乐库程序。用户应该能够创建一个包含:歌曲名称、艺术家和流派的节点。这些节点应按歌曲名称的字母顺序排序。

但是,我在创建新节点而不影响我当前的头节点时遇到了麻烦。下面的图片将更好地说明这一点。我调用了一行代码,旨在从用户那里接收一个新值,它重置了头节点中的歌曲名称值,我不知道为什么。任何帮助表示赞赏。

(测试点 1 和测试点 2 printf 语句之间出现问题,我打算让测试点 2 显示“zz”而不是“aa”)。

Code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>

typedef struct node
{
    char* artist;
    char* songName;
    char* genre;
    struct node* nextNode;
} Node;

const int MAX_LENGTH = 1024;
void inputStringFromUser(char prompt[], char s[], int arraySize);

int main(void)
{
    // Declare the head of the linked list.
    //   ADD YOUR STATEMENT(S) HERE
    Node* head = NULL;

    // Announce the start of the program
    printf("Personal Music Library.\n\n");
    printf("%s",
           "Commands are I (insert), D (delete), S (search by song name),\n"
           "P (print), Q (quit).\n");

    char response;
    char input[MAX_LENGTH + 1];
    char input4[MAX_LENGTH + 1];
    char input2[MAX_LENGTH + 1];
    char input3[MAX_LENGTH + 1];

        inputStringFromUser("\nCommand", input, MAX_LENGTH);

        response = toupper(input[0]);

        if (response == 'I') {
//insert a node code
            char* promptName = "Song name";
            char* promptArtist = "Artist";
            char* promptGenre = "Genre";
            char* newName;
            char* newArtist;
            char* newGenre;
//test points for the songname in the head node
            if (head != NULL) {
                printf("Test Point 1: %s\n", head->songName);
            }
            inputStringFromUser(promptName, input4, MAX_LENGTH);
            newName = input4;
            if (head != NULL) {
                printf("Test Point 2: %s\n", head->songName);
            }
            inputStringFromUser(promptArtist, input2, MAX_LENGTH);
            newArtist = input2;
            inputStringFromUser(promptGenre, input3, MAX_LENGTH);
            newGenre = input3;
            //if it is the first node then just create a node then assign the values to the user input
            if (head == NULL) {
                head = malloc(sizeof(Node));
                head->artist = newArtist;
                head->genre = newGenre;
                head->songName = newName;
            } else {
//sorts through list until it finds the first node where the song name is not alphabetically ahead
//of the current entered name
                Node* current = head;
                while (strcmp(current->songName, newName) == 1) {


                //if the loop goes to the end of the list place the new node at the end
                    if (current->nextNode != NULL) {
                        current = current->nextNode;
                    } else {
                        current->nextNode = malloc(sizeof(Node));
                        current = current->nextNode;
                        current->artist = newArtist;
                        current->genre = newGenre;
                        current->songName = newName;
                        break;
                    }
                }
//if the loop finds the correct place for a node it shifts all the other ones down
//then create a new end node
                char* tempName = "  ";
                char* tempName2 = "  ";
                char* tempArtist = "  ";
                char* tempArtist2 = "  ";
                char* tempGenre = "  ";
                char* tempGenre2 = "  ";

                tempName = current->songName;
                tempArtist = current->artist;
                tempGenre = current->genre;

                current->artist = newArtist;
                current->genre = newGenre;
                current->songName = newName;

                while (current->nextNode != NULL) {
                    current = current->nextNode;

                    tempName2 = current->songName;
                    tempArtist2 = current->artist;
                    tempGenre2 = current->genre;

                    current->songName = tempName;
                    current->artist = tempArtist;
                    current->genre = tempGenre;

                    tempName = tempName2;
                    tempGenre = tempGenre2;
                    tempArtist = tempArtist2;
                }

                current->nextNode = malloc(sizeof(Node));
                current = current->nextNode;
                current->songName = tempName;
                current->artist = tempArtist;
                current->genre = tempGenre;
            }
        } 
}

// Support Function Definitions

// Prompt the user for a string safely, without buffer overflow
void inputStringFromUser(char prompt[], char s[], int maxStrLength)
{
    int i = 0;
    char c;

    printf("%s --> ", prompt);
    while (i < maxStrLength && (c = getchar()) != '\n')
        s[i++] = c;
    s[i] = '\0';
}

【问题讨论】:

  • 这是复制指针而不是复制字符数组。总是这样。
  • 与您的问题无关,但请注意getchar 返回一个int。这是因为它应该与EOF相媲美。
  • 马丁詹姆斯我不知道这是什么意思
  • 您为节点分配空间,但不为 char 数组成员分配空间。所以,你最终只是复制指向本地变量的指针,这一切都变成了 PHP 形状:(
  • 请阅读strcmp 的手册页以查看它返回的值。

标签: c memory linked-list runtime-error dynamic-allocation


【解决方案1】:

这是错误的一个例子:

current->genre = newGenre;

您保存了指针newGenre(指向input3)的值。所以所有节点都将指向同一个对象,即当更改input3时,所有节点都将指向新值。

试试:

typedef struct node
{
    char artist[MAX_LENGTH + 1];
    char songName[MAX_LENGTH + 1];
    char genre[MAX_LENGTH + 1];
    struct node* nextNode;
} Node;

然后做:

strcpy(current->genre, newGenre);

将值复制到节点中。

或者,您可以保留指针并使用动态内存分配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2021-04-15
    • 2014-05-31
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    相关资源
    最近更新 更多