2

I'm trying to create a dynamic list, which should read an input string and save every string into a new node of the lis. The program will print every node, after that i want to add a function to delete a node, but i'm getting a lot of errors, mostly because i'm not so good at using pointers and i'm new to data structures, can someone please help me?

EDIT: I corrected the code, now i'm not getting the errors anymore but the program seems to print for each node a single character, instead a string for each node, this is the current output:

// Inserting and deleting nodes in a list
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// self-referential structure                       
struct listNode {                                      
   char *data; // each listNode contains a character 
   struct listNode *nextPtr; // pointer to next node
}; 
typedef struct listNode ListNode; // synonym for struct listNode
typedef ListNode *ListNodePtr; // synonym for ListNode*

// prototypes
void insert(ListNodePtr *sPtr, char *value);
int isEmpty(ListNodePtr sPtr);
void printList(ListNodePtr currentPtr);
void instructions(void);
int main(void)
{ 
   ListNodePtr startPtr = NULL; // initially there are no nodes
   char item; // char entered by user
   instructions(); // display the menu
   printf("%s", "? ");
   unsigned int choice; // user's choice
   scanf("%u", &choice);
   // loop while user does not choose 3
   while (choice != 3) { 
      switch (choice) { 
         case 1:
            printf("%s", "Enter a character: ");
            scanf("%c", &item);
            insert(&startPtr, &item); // insert item in list
            printList(startPtr);
            break;

         default:
            puts("Invalid choice.\n");
            instructions();
            break;
      } // end switch
      printf("%s", "? ");
      scanf("%u", &choice);
   } 
   puts("End of run.");
} 
// display program instructions to user
void instructions(void)
{ 
   puts("Enter your choice:\n"
      "   1 to insert an element into the list.\n"
      "   2 to delete an element from the list.\n"
      "   3 to end.");
}

// insert a new value into the list in sorted order
void insert(ListNodePtr *sPtr, char *value)
{ 
   ListNodePtr newPtr = malloc(sizeof(ListNode)); // create node

   if (newPtr != NULL) { // is space available
      newPtr->data= malloc(strlen(value)+1);
      strcpy(newPtr->data, value);
      newPtr->nextPtr = NULL; // node does not link to another node
      ListNodePtr previousPtr = NULL;
      ListNodePtr currentPtr = *sPtr;
      // loop to find the correct location in the list       
      while (currentPtr != NULL && value > currentPtr->data) {
         previousPtr = currentPtr; // walk to ...               
         currentPtr = currentPtr->nextPtr; // ... next node 
      }                                          
      // insert new node at beginning of list
      if (previousPtr == NULL) { 
         newPtr->nextPtr = *sPtr;
         *sPtr = newPtr;
      } 
      else { // insert new node between previousPtr and currentPtr
         previousPtr->nextPtr = newPtr;
         newPtr->nextPtr = currentPtr;
      } 
   } 
   else {
      printf("%s not inserted. No memory available.\n", value);
   } 
} 

int isEmpty(ListNodePtr sPtr)
{ 
   return sPtr == NULL;
}


// print the list
void printList(ListNodePtr currentPtr)
{ 
   // if list is empty
   if (isEmpty(currentPtr)) {
      puts("List is empty.\n");
   } 
   else { 
      puts("The list is:");
      // while not the end of the list
      while (currentPtr != NULL) { 
         printf("%s --> ", currentPtr->data);
         currentPtr = currentPtr->nextPtr;   
      } 
      puts("NULL\n");
   } 
} 

Here is a sample of the output currently:

    ./test
Enter your choice:
   1 to insert an element into the list.
   2 to delete an element from the list.
   3 to end.
? 1
Enter a character: The list is:

 --> NULL

? Test
Enter a character: The list is:

 --> T --> NULL

? Enter a character: The list is:

 --> T --> e --> NULL

? Enter a character: The list is:

 --> T --> e --> s --> NULL

? Enter a character: The list is:

 --> T --> e --> s --> t --> NULL

? 

Where i want it to be, for example: Word One -> Word Two etc.

Gerard22
  • 353
  • 2
  • 7
  • 14
  • Please explain what errors you are seeing and what have you done so far to debug it. SO is not a debugging service. See [How to ask a good question?](https://stackoverflow.com/help/how-to-ask). It is also a good time to start learning about debugging techniques. Have a look at [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –  Jul 11 '18 at 17:47
  • I added a paragraph with all the errors i got, i debugged it – Gerard22 Jul 11 '18 at 17:50
  • I did read every comment here, and i wouldn't have posted here if i didn't try everything i could until this moment, it's just that this is my current level of programming, i know it's a complete disaster but i'm trying to improve – Gerard22 Jul 11 '18 at 17:57
  • 1
    On a side note, if you are unfamiliar with pointers, it may be a good idea to make their use more explicit: try to avoid `typedef ListNode *ListNodePtr;` and use `ListNode *` (or `ListNode **`) directly. – Bob__ Jul 11 '18 at 18:14
  • Thanks, i am indeed not really familiar with pointers, so i should just follow your advice – Gerard22 Jul 11 '18 at 18:17

1 Answers1

3

To get user input you are using

scanf("%c", &item); 

This will only get one character from their input. If you want to get a string, you could update item to be a character array:

char item[20];

I also believe that fgets is better for getting user input strings, as described here. So using the following would probably make your program a bit more durable:

fgets(item, sizeof(item), stdin);

After these changes, here is the output:

Enter your choice:
1 to insert an element into the list.
2 to delete an element from the list.
3 to end.
? 1
Enter a character: The list is:

--> NULL

? Testing
Enter a character: The list is:

--> Testing
--> NULL

? What
Enter a character: The list is:

--> Testing
--> What
--> NULL

? About
Enter a character: The list is:

--> Testing
--> What
--> About
--> NULL

? This
Enter a character: The list is:

--> Testing
--> What
--> About
--> This
--> NULL

? 

EDIT: The following has already been addressed in the question's code.

newPtr->data is a char, however it seems you would like it to be a string. You should change the struct definition so that data is a char * instead.

If you are trying to print a string instead of a single character, you should replace:

printf("%c not inserted. No memory available.\n", value);
// as well as
printf("%c --> ", currentPtr->data);

With:

printf("%s not inserted. No memory available.\n", value);
// and
printf("%s --> ", currentPtr->data);

The %c is used for formatting a single character, but %s is used for printing a string, and must be matched with a char *

Jacob Boertjes
  • 963
  • 5
  • 20
  • I did NOT change %c to %s, but it still keeps saving one character per node, instead of a string, i don't know why – Gerard22 Jul 11 '18 at 18:26
  • @Bob__ Thanks, I missed that, have edited accordingly – Jacob Boertjes Jul 11 '18 at 18:26
  • Thank you! One last thing: where should i put fgets(item, sizeof(item), stdin); ? – Gerard22 Jul 11 '18 at 18:37
  • @Gerard22 inder `case 1` in your `main` function, the line was `scanf("%c", &item);` but should instead be `fgets(item, sizeof(item), stdin);` – Jacob Boertjes Jul 11 '18 at 18:39
  • I got this error with fgets: warning: passing argument 2 of ‘insert’ from incompatible pointer type [-Wincompatible-pointer-types] insert(&startPtr, &item); // insert item in list – Gerard22 Jul 11 '18 at 18:42
  • @Gerard22 This is because you updates `item` from a `char` to a `char` array. If you change `insert &startPtr, &item);` to `insert &startPtr, item);` it will work. If you want to know why an array behaves like a pointer (which it is in this case) check this out! https://stackoverflow.com/questions/4607128/in-c-are-arrays-pointers-or-used-as-pointers – Jacob Boertjes Jul 11 '18 at 18:53
  • Ok! I tried this: fgets(item, sizeof(item), stdin); / insert(&startPtr, item); but still got the error! Thanks for the source, i'm checking it right now. – Gerard22 Jul 11 '18 at 19:12
  • @Gerard22 Here is a link to my version of the working code https://pastebin.com/qnuqvTg6 Hope it helps! – Jacob Boertjes Jul 11 '18 at 19:56
  • Of course it helps, thank you a lot for your contribution @jacob! – Gerard22 Jul 11 '18 at 22:32