0

I am currently having trouble trying to print my doubly linked list out. The problem is either in the getSongInfo function or in the printSongInfo function. I am very new to coding and all the help is greatly appreciated. I also don't know how to use the tail pointer when using a doubly linked list.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#pragma warning(disable : 4996)
#pragma warning(disable : 6387)

#pragma once

//structs 
typedef struct {
    char* title;
    char* artist;
    int rating;
    SongNode* next;
    SongNode* prev;
}SongNode;

//Constants 
#define kInfiniteLoop 1 
#define kStringLength 30

//Prototypes
int getNum(void);
void eliminateEndOfLine(char* buffer);
void printSongInfo(SongNode* head); 
SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating); 

int main() {


    char title[kStringLength];
    char artist[kStringLength];
    int rating = 0;
    SongNode* head = NULL;
    SongNode* tail = NULL;

    printf("Enter Title, Artist and Rating\n");
    printf("Enter'.' to get out of the loop and print list\n");

    while (kInfiniteLoop) {

        printf("Title: ");
        fgets(title, kStringLength, stdin);
        eliminateEndOfLine(title);

        if (strcmp(title, ".") == 0) {
            break;
        }

        printf("Artist: ");
        fgets(artist, kStringLength, stdin);
        eliminateEndOfLine(artist);

        printf("Rating: ");
        while (rating = getNum()) { // error check the rating this will check to make sure the rating is in the range 1-5.

            if (rating < 1 || rating>5) {
                printf("The number you have entered is invaild\n");
                rating = 0;
                printf("Rating: ");
                continue;
            }
            break;

            head=getSongInfo(&head, &tail, title, artist, rating); 
            printf("\n");
        }
    }
    printSongInfo(head);
    return 0;
}
  /*===============================================================================================================*/
  /*FUNCTION   :getNum(void)                                                                                       */
  /*PARAMETERS :void                                                                                               */
  /*RETURNS    :number                                                                                             */
  /*DESCRIPTION:This function is the user input function to get a number rating                                    */
  /*===============================================================================================================*/
  int getNum(void)
  {/* the array is 121 bytes in size; we'll see in a later lecture how we can improve this code */
      char record[121] = { 0 }; /* record stores the string */
      int number = 0;
      /* NOTE to student: indent and brace this function consistent with your others */
  /* use fgets() to get a string from the keyboard */
      fgets(record, 121, stdin);
      /* extract the number from the string; sscanf() returns a number
   * corresponding with the number of items it found in the string */
      if (sscanf(record, "%d", &number) != 1)
      {
          /* if the user did not enter a number recognizable by
           * the system, set number to -1 */
          number = -1;
      }
      return number;
  }
  
  
  
  /*=======================================================================================================*/
  /*FUCNTION      :void eliminateEndOfLine                                                                 */
  /*PARAMETER     :(char* buffer)                                                                          */
  /*RETURNS       :void                                                                                    */
  /*DESCRIPTION   :This function takes a pointer to a string and looks through the string to find the      */
  /*               newline.It takes the new line out of the string.                                        */
  /*=======================================================================================================*/
  void eliminateEndOfLine(char* buffer)
  {
      char* target = strchr(buffer, '\n');
      if (target != NULL)
      {
          *target = '\0';
      }
  }

  SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating)
  {
      SongNode *newBlock = NULL; 
  
      newBlock = (SongNode*)malloc(sizeof(SongNode)); 
      if (newBlock == NULL) {
          
          printf("No memory to be Allocated\n"); 
          return (*head); 
      }
  
      newBlock->title=(char*)malloc(strlen(title) + 1);
      if (newBlock->title == NULL) {
          printf("No memory can be allocated for title\n"); 
          return (*head); 
      }
  
      newBlock->artist = (char*)malloc(strlen(artist) + 1); 
      if (newBlock->rating == NULL) {
          printf("No memory can be alocated for artist\n"); 
          return (*head); 
      }
  
      newBlock->rating = (int)malloc(sizeof(int)); 
      if (newBlock->rating == NULL) {
          printf("No memory can be alllocated for rating \n"); 
          return (*head); 
      }
  
      strcpy(newBlock->title, title); 
      strcpy(newBlock->artist, artist); 
      newBlock->rating = rating; 
  
      newBlock->next = (*head); 
      newBlock->prev = NULL; 
  
      if ((*head) != NULL) 
          (*head)->prev = newBlock; 
  
      (*head) = newBlock; 
  
      return (*head); 
  }
  
  void printSongInfo(SongNode* head) {
      SongNode* ptr;
      ptr = head;
  
      printf("\n");
      printf("%-35s %-35s %-35s\n", "Title", "Artist","Rating");
  
      while (ptr != NULL) {
          printf("%-35s %-35s %-35d\n", ptr->title, ptr->artist);
          ptr = ptr->next;
      }
  }
  • regarding: `typedef struct SongNode{ char* title; char* artist; int rating; SongNode* next; SongNode* prev; };` This does not compile! – user3629249 Jun 19 '21 at 14:18
  • this function: `void eliminateEndOfLine(char* buffer)` already exists in the `string.h` header file as: `buffer[ strcspn( buffer, "\n" ] = '\0'; – user3629249 Jun 19 '21 at 14:26
  • OT: regarding: `fgets(record, 121, stdin);` always check the returned value (!=NULL) – user3629249 Jun 19 '21 at 14:27
  • regarding: `newBlock->artist = (char*)malloc(strlen(artist) + 1); if (newBlock->rating == NULL) {` This 'if' is checking the wrong field! It should be checking: `newBlock->artist` – user3629249 Jun 19 '21 at 14:30
  • regarding statements like: ` printf("No memory to be Allocated\n");` This is not necessarily true. Suggest: `perror( "No memory to be Allocated\n" );` as that will output both your error message and the text reason the system thinks the error occurred to `stderr` – user3629249 Jun 19 '21 at 14:34
  • OT: regarding: `fgets(record, 121, stdin);` When this input is requested by the program, the user has not been prompted as to what they are expected to input at the keyboard. – user3629249 Jun 19 '21 at 14:37
  • regarding: `break; head=getSongInfo(&head, &tail, title, artist, rating); printf("\n")` the assignment of `head` and the call to `printf()` will never be executed due to the `break;` statement will have already exited the `while()` loop – user3629249 Jun 19 '21 at 14:41
  • regarding: `while (rating = getNum())` An assignment always results in a `true`, Not what you want. Suggest adding a set of parens: I.E. `while ( (rating = getNum()) )` so this looks at the result of the assignment. – user3629249 Jun 19 '21 at 14:46
  • regarding: `void printSongInfo(SongNode* head); SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating); ` Neither of these functions are actually implemented in the posted code. This is yet another reason the posted code does not compile. – user3629249 Jun 19 '21 at 14:53

1 Answers1

1

You have a break statement in the while (rating = getnum()) loop that shouldn't be there. It will cause the loop to terminate before getting any song info.

Other problems:

newBlock->rating = (int)malloc(sizeof(int)); will leak memory, because you allocate some but never free it. Because rating is an int, memory does not need to be allocated for it. (Also, see Do I cast the result of malloc?).

getSongInfo should either return the new head, or update the current one, but not both.

Updating tail is similar to updating head, but does not need to be done all the time when inserting at the head (there's a condition that you'll need to check for).

You don't need #pragma once in a C source file. That should be in a header (and is only supported on some compilers).

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56