0

I'm writing a program to create a linked list node. After that, i add some functions (insert,search,update,and print). The linked list contains number, name, and quantity on hand.

The main function prompts users to enter an operation code, then calls a function requested actions.

    main()
{
        char code;
        int c;
        for(;;)
        {
            printf("i: insert\ns: search\nu: update\np: print\n");
            printf("Enter operation code: ");
            scanf("%c",&code);
            while((c=getchar() )!= '\n'&& c!=EOF);
            switch(code)
                {
                    case 'i': insert();
                        break;
                    case 's': search();
                        break;
                    case 'u': update();
                        break;
                    case 'p': print();
                        break;
                    case 'q':return 0;
                    default: printf("Illegal code\n");
                        break;
                }
            printf("\n");   
        }
}

All function work correctly. However, in the insert function, I use fgets statement to get the string input from the user. (NAME_LEN = 25)

void insert()
{
    node *previous,*current,*new_node;
    new_node = malloc(sizeof(node));
    printf("Enter part number: ");
    scanf("%d",&new_node->number);
    for(current = inventory,previous=NULL;
        current != NULL&& new_node->number > current->number;
        previous = current,current = current -> next);
    if(current != NULL && new_node ->number == current->number)
    {
        printf("Part already exists.\n");
        free(new_node);

        return;
    }
    printf("Enter name part: ");
    fgets(new_node->Name,NAME_LEN+1,stdin); // i use fgets to input string name
    printf("Enter quantity on hand: ");
    scanf("%d",&new_node->on_hand);
    new_node -> next = current;

    // move to the next node 
    if(previous == NULL)
    inventory =new_node;
    else
    previous->next = new_node;

}

Unfortunately, this code doesn't work. The program shows that

i: insert
s: search
u: update
p: print
Enter operation code: i
Enter part number: 2
Enter name part: Enter quantity on hand: 3

As you can see that, the name part was missed.

Moreover, after inserting a new node, the program automatically shows the default case in the switch.

i: insert
s: search
u: update
p: print
Enter operation code: i
Enter part number: 2
Enter name part: Enter quantity on hand: 3

i: insert
s: search
u: update
p: print
Enter operation code: Illegal code

Can you explain to me what happens, pls?.

  • 1
    You understood what is going wrong? – user2736738 Dec 24 '17 at 05:32
  • 1
    use fgets instead of scanf, scanf leaves stuff in the inbuffer – AndersK Dec 24 '17 at 06:20
  • 1
    Hint: Any time you start a question with *"Why doesn't (insert C library function name) function work?"* -- it's usually not the function that is the problem. – David C. Rankin Dec 24 '17 at 08:51
  • I'm so sorry, I forget to input the insert function which I use the fgets function. And I know that I have some mistakes before using fgets string, but i can't find them (maybe in the). Can you show me where I'm wrong, pls? – Vũ Đức Dũng Dec 24 '17 at 11:57

1 Answers1

5

Well the thing is fgets is consuming the \n that is left in stdin from previous input. Easy way would be to use dummy getchar() or using fgets until you get a non-whitespace input.

Do one thing, after scanf put a getchar().

scanf("%c",&code);
getchar(); 
^^^^
Will consume the `\n`.

To give you a more clear explanation suppose you enter iEnter

Then i is stored into the variable code. But what about the \n. fgets() when starts reading input from stdin finds that \n and it stops. By using the getchar() you have consumed the \n. Now all non-whitespace characters will be consumed by fgets until it finds a \n or EOF or buffer gets full.

The most portable and clean way to flush the stdin would be (To be correct the stdin must have atleast the \n character otherwise it will go on eating other charcaters as well (maybe your valid inputs)).

int c;
while ((c = getchar()) != '\n' && c != EOF);

This you can use whenever you encounter some garbage input or clear the stdin.

Also to really understand whether fgets function works or not you need to check what it returns. Does it return NULL? If not then check it and then try to understand. Simply because you didn't see any output when printed the buffer doesn't mean fgets failed.


Edit

The question at first posted mentioned that there is fgets right after the scanf("%c",&code). Here it is clear on the edit that scanf("%d",&new_node->number); is there before fgets but that doesn't change the scenario. Now the \n after the entered number (you input 2ENTER) is still there and fgets consumes it. So we need to place dummy getchar() over there or stdin flushing technique shown above.

scanf("%d",&new_node->number);
getchar();
^^^^
This consumes the stray `\n` 
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • The `while` loop here is the canonical way to clear the input stream, but it is worth noting that there must at least be a newline character in the input stream for this to work as expected. – ad absurdum Dec 24 '17 at 05:53
  • Thank you very much, but I forget to add insert function. I just edited now. Moreover, I follow your advice and I can fix the illegal number problem. However, I have to add 2 getchar() functions at the end of the insert function to make the program run. I don't understand what happens. Can you explain to me, pls? – Vũ Đức Dũng Dec 24 '17 at 12:04
  • what 's about the `fgets` function in the insert function? should I write a `getchar()` before to consume the `\n` ? – Vũ Đức Dũng Dec 24 '17 at 14:17
  • I know, but is there any flexible way to limit doing it? You know it makes the program slow and very heavy. – Vũ Đức Dũng Dec 24 '17 at 14:39
  • You need to flush the stdin whatever way possible. Alternatively you can read each line and tokenize everything and process them. But again not sure how fast it would be and how fast you want it to be. @VũĐứcDũng – user2736738 Dec 24 '17 at 14:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161900/discussion-between-v-dc-dng-and-coderredoc). – Vũ Đức Dũng Dec 24 '17 at 14:49
  • 1
    You can ask me here...I am using mobile. So it's hard for me to be in chat. @VũĐứcDũng – user2736738 Dec 24 '17 at 14:50
  • Sorry, i think i should code and modify my program before asking you :D, thank you very much :D – Vũ Đức Dũng Dec 24 '17 at 14:53