1

I've written a linked list program and want to take input with spaces but it's not working.It works fine when I simply use "scanf" with %s but since I want to take input with multiple spaces I tried using "gets" and "puts" I've also tried using scanf("%[^\n]*c"); but on the console it gives me random garbage value for scanf("%[^\n]*c"); and for "gets" it reads blank space, now let me tell you guys some info about the code and how it works createNode(); function basically just creates a new node to store in the list and returns the address of this newly created node to the insertend(); function where it aligns the new node at the end of the list and in start=t=newnode start is the head pointer which points to the very first node and t is used to traverse the list until t's value becomes NULL,As you could see in the else part of the insertend(); function we're using another pointer t and storing the value of start in it so that we can traverse the list without losing the the address of the first node which is originally kept in the start pointer. here's the code ->

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct Node
{
    char first[20];
    struct Node* next;
};
struct Node* start=NULL;
struct Node* t,*u;
int i=1;
struct Node* createNode() //this function creates a newnode everytime it's called
{
    struct Node* create=(struct Node*)malloc(sizeof(struct Node));
    return create;
}
int length() //to measure the length of the list.
{
 int count = 0;
 struct Node* temp;
 temp=start;
 while(temp!=NULL)
 {
    count++;
    temp = temp->next;
 }
 return count;
}
void insertend() //to insert a node at the end of the list.
{
    int l;
    struct Node* newnode = createNode();
    printf("Enter Name : ");
    fgets(newnode->first,sizeof(newnode->first),stdin);
    if(start==NULL)
    {
        start=t=newnode;
        start->next=NULL;

    }
    else
    {
        t=start;
        while(t->next!=NULL)
            t=t->next;
        t->next=newnode;
        t=newnode;
        t->next=NULL;
        printf("%s successfully added to the list!",newnode->first);
    }

    l=length();
    printf("The length of the list is %d",l);
}
void display() //to display the list
{
    struct Node* dis;
    dis=start;
    if(start==NULL)
    {
        system("cls");
        printf("No elements to display in the list");
    }
    else
    {
        system("cls");
        for(int j=1;dis!=NULL;j++)
        {
            printf("%d.) %s\n",j,dis->first);
            dis=dis->next;
        }
    }
}
int menu() //this is just a menu it returns the user input to the main function
{
    int men;
    printf("Please select a choice from the options below :-\n\n");
    printf("1.) Add at the end of the list\n");
    printf("2.) Display list\n");   
    printf("3.) exit\n");
    printf("  Enter your choice : ");
    scanf("%d",&men);
    return men;
}
int main()
{
    while(1)
    {
        system("cls");
        switch(menu())
        {
            case 1 : insertend();
            break;                      
            case 2 : display();
            break;
            case 3: exit(0);
            default : system("cls"); printf("Ivalid choice!Please select an appropriate option!");
            fflush(stdin);
            break;
        }
        getch();
    }
     return 0;
}
ansme
  • 413
  • 2
  • 11
  • 4
    Please provide a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). For example, we don't know the definition of `struct Node` and `createNode`. There may (or may not) be errors in either one. – kaylum Mar 10 '20 at 10:46
  • 1
    Read the description for the [tag:gets] tag and heed the warning. – Caleb Mar 10 '20 at 10:48
  • 2
  • 2
    There is no longer a function `gets` in the C language. You need to replace your current source of learning with one that has been updated during the past 20 years. – Lundin Mar 10 '20 at 11:47
  • Welcome to Stack Overflow! Please [edit] your code to reduce it to a [mcve] of your problem. Your current code includes much that is peripheral to your problem - since you're asking about `scanf()`, you don't need to burden us with any of the linked-list code. – Toby Speight Mar 10 '20 at 15:43
  • Hello, @TobySpeight I've added the linked list code so that they better understand if there's anything else wrong within the "insertend()" function itself and I've also added the struct node code including the definition of createNode as asked my kaylum, So please reopen the question for answers if anything else is needed to be edited let me know. Thanks! – ansme Mar 11 '20 at 09:56

1 Answers1

2

gets is not to be used, it has been removed from C standard due to it's lack of security.

If you want to know more read Why is the gets function so dangerous that it should not be used?

If you use [^\n] it should work, though it's also problematic since this specifier does not limit the lenght of the stream to be read only that it must stop when finding a newline character.

I suspect the problem might be in the container rather than in the reading, maybe uninitialized memory, If you provide the struct code it'll be easier to diagnose.

You can try:

fgets(newnode->first, sizeof(newnode->first), stdin)

There is a caveat:

  • If the inputed stream is larger than the container, the extra characters will remain in the input buffer, you might need to discard them.

EDIT:

So the main problem was the fact that through your code you have lingering characters in the buffer, in the particular case of your fgets input it would catch a '\n' left in the buffer, so it would read it before the inputed stream, leaving it, again, in the buffer.

I added a function to clean up buffer, note that fflush(stdin) leads to undefined behaviour so it's a bad option.

I also added a few small tweaks.

- Note that conio.h is windows specific as is system("cls") and getch()(ncurses.h in Linux systems) so I commented it for this sample.

Live sample here

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

struct Node
{
  char first[20];
  struct Node *next;
};

struct Node *start = NULL;
struct Node *t, *u;

void clear_buf(){ //clear stdin buffer
  int c;
  while((c = fgetc(stdin)) != '\n' && c != EOF){}
}

struct Node *createNode() //this function creates a newnode everytime it's called
{
  struct Node *create = malloc(sizeof(struct Node));
  return create;
}

int length() //to measure the length of the list.
{
  int count = 0;
  struct Node *temp;
  temp = start;
  while (temp != NULL)
  {
    count++;
    temp = temp->next;
  }
  return count;
}
void insertend() //to insert a node at the end of the list.
{
  int l;
  struct Node *newnode = createNode();

  printf("Enter Name : ");

  clear_buf(); //clear buffer before input

  fgets(newnode->first, sizeof(newnode->first), stdin);
  newnode->first[strcspn(newnode->first, "\n")] = '\0'; //remove '\n' from char array

  if (start == NULL)
  {
    start = t = newnode;
    start->next = NULL;
    printf("%s successfully added to the list!", newnode->first);
  }
  else
  {
    t = start;
    while (t->next != NULL)
      t = t->next;
    t->next = newnode;
    t = newnode;
    t->next = NULL;
    printf("%s successfully added to the list!", newnode->first);
  }

  l = length();
  printf("The length of the list is %d", l);
}

void display() //to display the list
{
  const struct Node *dis;
  dis = start;
  if (start == NULL)
  {
    system("cls");
    printf("No elements to display in the list");
  }
  else
  {
    system("cls");
    for (int j = 1; dis != NULL; j++)
    {
      printf("%d.) %s\n", j, dis->first);
      dis = dis->next;
    }
  }
}
int menu() //this is just a menu it returns the user input to the main function
{
  int men;
  printf("\nPlease select a choice from the options below :-\n\n");
  printf("1.) Add at the end of the list\n");
  printf("2.) Display list\n");
  printf("3.) exit\n");
  printf("  Enter your choice : ");
  scanf("%d", &men);
  return men;
}
int main()
{
  while (1)
  {
    system("cls");
    switch (menu())
    {
    case 1:
      insertend();
      break;
    case 2:
      display();
      break;
    case 3:
      exit(0);
    default:
      system("cls");
      printf("Ivalid choice!Please select an appropriate option!");
      clear_buf();
      break;
    }
    getch();
  }
  return 0;
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • 1
    "If you use [^\n] it should work" --> `scanf("%[^\n]*c")` have many problems too, including no width limit, the key problem with `gets()`. – chux - Reinstate Monica Mar 10 '20 at 14:00
  • @anastaciu I tried using fgets(newnode->first, sizeof(newnode->first), stdin) but still It's taking blank input. I've also added the struct code please check it out the question is currently closed I've edited it and requested to reopen it, Once it's open please provide the answer! thanks in advance – ansme Mar 11 '20 at 10:13
  • @ansme, there are still many questions about the code you posted, for instance, what does `createNode();` do, what is `start=t=newnode;` supposed to do, where are the declarations of all those variables, this is why it's important to post a reproducible piece of code, one that somemone can copy to a compiler and reproduce the problem as described. – anastaciu Mar 11 '20 at 11:42
  • @anastaciu Hi, I've updated the question and have added the code and it can be compiled by just copying and pasting. I've also added comments in front of every function to explain what they do, but still the `createNode();` function basically just creates a new node to store in the list and returns the address of this newly created node to the `insertend();` function where it aligns the new node at the end of the list and in `start=t=newnode` `start` is the head pointer which points to the first node and `t` is used to traverse the list until t's value becomes NULL. – ansme Mar 11 '20 at 14:22
  • @ansme the problem was mainly the clearing of the buffer, I edited in a solution to my answer, with code, and **live sample**, pay atention, not only to the code, but also to the description and note for some specifics. – anastaciu Mar 11 '20 at 16:43
  • 1
    @anastaciu Thank you so much for taking time to explain in so much detail and fixing my problem, I understood everything that you've explained and the plus point is that I've learned how to clean buffer without using fflush(stdin). I'm kinda new to the community and not much experienced but still it feels amazing just because of guys like you! So I would like to thank you again and have a wonderful day! :) – ansme Mar 12 '20 at 07:53
  • @ansme, glad to help, welcome to the community and thank you for your kind words, a wonderful day for you too. – anastaciu Mar 12 '20 at 13:33