-1

I am creating a music library program in C using linked lists. Users should be able to create a node containing: song name, artists, and genre. These nodes should be sorted alphabetically by song name.

I am having trouble, however, creating new nodes without affecting my current head node. The picture below will illustrate this better. I call a line of code that is meant to receive a new value from the user and it resets the song name value in the head node and I have no clue why. Any help is appreciated.

(Problem occurs between Test Point 1 and Test Point 2 printf statements, I intend for Test Point 2 to display "zz" instead of "aa").

Code Output

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';
}
Eric Geerts
  • 259
  • 2
  • 6

1 Answers1

1

This is one example of what's wrong:

current->genre = newGenre;

You saving the value of the pointer newGenre (which is pointing to input3). So all nodes will end pointing to same object, i.e. when changing input3 all nodes will point the new value.

Try:

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

and then do:

strcpy(current->genre, newGenre);

to copy the value into the node.

Alternatively, you can keep the pointers and use dynamic memory allocation.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63