Как использовать get и put со связанным списком с помощью указателей - PullRequest
1 голос
/ 10 марта 2020

Я написал программу со связанным списком и хочу получать ввод с пробелами, но он не работает. Это нормально, когда я просто использую "scanf" с% s, но так как хочу получить ввод с несколькими пробелами, я попытался использовать " получает "и" ставит "Я также пытался использовать scanf ("% [^ \ n] *c "); но на консоли это дает мне случайное значение мусора для scanf ("% [^ \ n] *c"); и для «get» он читает пустое пространство, теперь позвольте мне рассказать вам некоторую информацию о коде и о том, как он работает. createNode(); Функция в основном просто создает новый узел для хранения в списке и возвращает адрес этого вновь созданного узла в функция insertend();, где она выравнивает новый узел в конце списка, а в start=t=newnode start указатель заголовка, который указывает на самый первый узел, а t используется для обхода списка, пока значение t не станет NULL, как вы могли видеть в части else функции insertend();, мы используем другой указатель t и сохраняем в нем значение start, чтобы мы могли пройти по списку, не теряя адрес первого узел, который изначально находится в указателе start. вот код ->

#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;
}

1 Ответ

2 голосов
/ 10 марта 2020

gets не должен использоваться, он был удален из C стандарта из-за отсутствия безопасности.

Если вы хотите узнать больше, прочитайте Почему функция get так опасно, что его не следует использовать?

Если вы используете [^\n], это должно работать, хотя это также проблематично c, так как этот спецификатор не ограничивает длину потока, который должен быть прочитан, только оно должно прекратиться при поиске символа новой строки.

Я подозреваю, что проблема может быть в контейнере, а не в чтении, возможно, в неинициализированной памяти. Если вы предоставите код структуры, это будет легче диагностировать.

Вы можете попробовать:

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

Существует предупреждение:

  • Если вводимый поток больше контейнера, дополнительные символы останутся во входном буфере вам, возможно, понадобится их отбросить.

РЕДАКТИРОВАТЬ:

Таким образом, основная проблема заключалась в том, что через ваш код в буфере остаются задерживающиеся символы, в частном случае из вашего fgets ввода он поймал бы '\n' слева в буфере, так что он прочитал бы его перед входным потоком, оставив его снова в буфере.

Я добавил функцию для очистки буфер, обратите внимание, что fflu sh (stdin) приводит к неопределенному поведению , так что это плохой вариант.

Я также добавил несколько небольших настроек.

- Обратите внимание, что conio.h имеет значение windows, специфицирует c как system("cls") и getch() (ncurses.h в Linux системах), поэтому я прокомментировал его для этого образца.

Живой образец здесь

#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;
}
...