如何使用指针对链表使用 gets 和 puts

How to use gets and puts with linked list using pointers

我写了一个链表程序,想用 spaces 获取输入,但它不是 working.It 当我简单地使用 "scanf" 和 %s 时它工作正常但是因为我想使用多个 spaces 输入我尝试使用 "gets" 和 "puts" 我也尝试过使用 scanf("%[^\n]*c");但在控制台上它给了我 scanf("%[^\n]*c"); 的随机垃圾值对于 "gets",它显示为空白 space, 现在让我告诉你们一些关于代码及其工作原理的信息 createNode(); 函数基本上只是创建一个新节点存储在列表中,returns 这个新创建节点的地址到 insertend(); 函数,它将新节点对齐到列表的末尾在start=t=newnode中,start是指向第一个节点的头指针,t用于遍历列表,直到t的值变为NULL,正如您在[=16中看到的那样=] 部分 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;
}

gets 不被使用,由于缺乏安全性,它已从 C 标准中删除。

如果您想了解更多信息,请阅读 Why is the gets function so dangerous that it should not be used?

如果你使用 [^\n] 它应该可以工作,尽管它也有问题,因为这个说明符不限制只读流的长度,它必须在找到换行符时停止。

我怀疑问题可能出在容器而不是读取,可能是未初始化的内存,如果您提供结构代码将更容易诊断。

你可以试试:

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

有一个警告:

  • 如果输入流大于容器,多余的字符将保留在输入缓冲区中,您可能需要丢弃它们。

编辑:

所以主要的问题是,通过你的代码,你在缓冲区中有挥之不去的字符,在你的 fgets 输入的特定情况下,它会捕获缓冲区中留下的 '\n',所以它会在输入流之前读取它,再次将它留在缓冲区中。

我添加了一个清理缓冲区的功能,请注意 fflush(stdin) leads to undefined behaviour 所以这是一个错误的选择。

我还添加了一些小调整。

- 请注意 conio.h 是 windows 特定的 system("cls")getch()(ncurses.h 在 Linux系统)所以我为这个示例评论了它。

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")] = '[=11=]'; //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;
}