【问题标题】:Deleting structure from head(or maybe duplicates?) yields weird text when printing从头部删除结构(或者可能是重复的?)在打印时会产生奇怪的文本
【发布时间】:2018-04-24 06:13:34
【问题描述】:

我目前正在学习 C,我的任务是创建一个保存在记录中的结构,我应该使用链表。我的功能之一是通过输入姓氏来删除记录。使用 fgets 后代码停止工作(没有崩溃只是停止)。

struct students
{
char firstname[21];
char lastname[21];
double score;
int zip;
struct students* next;
};
struct students* head;
void add()
{
    struct students* new_node=(struct students*)malloc(sizeof(struct students));
    struct students *past=head;
    fflush(stdin);
    new_node->next=NULL;
    printf("Enter data: \n");
    printf("First name: ");
    fgets(new_node->firstname, 21, stdin);
    printf("Last name: ");
    fgets(new_node->lastname, 21, stdin);
    printf("Score: ");
    scanf("%lf", &new_node->score);
    printf("ZIP code: ");
    scanf("%d", &new_node->zip);
    if(head==NULL)
    {
        head=new_node;
        return;
    }
    while(past->next!=NULL)
    {
        past=past->next;
    }
    past->next=new_node;
    return;
}
void delrec()
{
    char last[21];
    printf("Enter last name: ");
    fflush(stdin);
    fgets(last, 21, stdin);
    struct students* temp=head;
    last[strcspn(last, "\n")]=0;
    if(strcmp(temp->lastname, last)==0)
    {
        struct students *next=temp->next;
        free(temp);
        temp=next;
    }
    while(temp!=NULL)
    {
        if(temp->next==NULL)
        {
            return;
        }
        if(strcmp(temp->next->lastname, last)==0)
        {
            struct students *next=temp->next->next;
            free(temp->next);
            temp->next=next;
        }
        temp=temp->next;
    }
}
int main()
{
    head=NULL;
    int i, x, y;
    printf("Enter 5 records:\n");
    for(i=0; i<5; i++)
    {
        add();
    }
    print();
    printf("What would you like to do?\n");
    y=1;
    while(y)
    {
        printf("Print records (press 1)\n");
        printf("Add new record (press 2)\n");
        printf("Delete record (press 3)\n");
        printf("Exit the program (press 0)\n");
        scanf("%d", &x);
        switch(x)
        {
        case 0:
            y=0;
            break;
        case 1:
            print();
            break;
        case 2:
            add();
            break;
        case 3:
            delrec();
            break;
        }
    }
    return 0;
}

我不认为它与链表有关,但可能是我的输入或其他东西。

EDIT1:我发现错误是我忘记在 delrec 的 while 循环中提供 temp=temp-&gt;next;。我现在当前的问题是,即使我输入了确切的姓氏,它也不会从列表中删除记录/取消链接结构。我已经编辑了代码以显示我的进度。

EDIT2:没有什么大的理由来编辑,但为了避免不想要的答案,我已经能够弄清楚如何从链接列表中删除结构。但是,如果我从头部删除结构,它会打印出非常奇怪的文本,再次编辑代码以显示进度。

【问题讨论】:

  • 在每个 printf() 中添加 can \n 看看是否仍然感觉卡住了

标签: c linked-list structure fgets


【解决方案1】:

fgets() 也会读入尾随的\n。所以与

fgets(last, 21, stdin);

如果您将"Doe" 作为输入,则存储的是"Doe\n"

您正在将此字符串与末尾的\n 与您的记录进行比较。

您需要删除结尾的\n。可以用

last[strlen(last)-1] = '\0';

编辑:正如joop 指出的那样,如果字符串为空,strlen() 可以返回0。如果strlen(last) 给出0,那么last[strlen(last)-1]。如前所述,您可以使用strcspn() 代替

last[strcspn(last, "\n")] = '\0';

strcspn(char *dest, char *src) 返回其第一个参数指向的字符串的最大初始段的长度,该长度仅由第二个参数指向的字符串中的字符组成。

还要注意fflush(stdin) 的效果是未定义的。标准说(根据this 回答),

如果流指向一个输出流或更新流,其中没有输入最近的操作,则 fflush 函数会导致该流的任何未写入数据被传递到主机环境以写入文件;否则,行为未定义。

看看the问题和this

【讨论】:

  • 在 'struct students* temp=head;' 之后添加了该部分,它确实有助于删除一个结构,但它删除了最后一个结构而不是我想要的。
  • 注意:strlen(last) 可以为零,导致last[strlen(last)-1)] = 0; 写入超出lasts 边界。 last[strcspn(last,"\r\n")] = 0; 是首选方式。
【解决方案2】:

在你的代码行中

printf("Enter data: \n");

在 add() 中产生了问题,因为 printf() 在输入缓冲区中留下空白, fgets() 将从那里读取它。

一种解决方案是在 printf() 之后放置 fflush(stdin),如下所示:

printf("Enter data: \n");
fflush(stdin);

或者您可以使用 scanf() 来获取带空格的字符,如下所示:

scanf("%[^\n]",new_node->firstname);

【讨论】:

  • 即使我更改了 add() 函数,问题仍然存在于 delrec() 函数中
  • Printf 在输入缓冲区中留下空白?一堆垃圾!
  • fflush(stdin) 是未定义的行为。你最好避免这种情况。
猜你喜欢
  • 2023-04-03
  • 2013-03-15
  • 1970-01-01
  • 2016-06-15
  • 2015-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-07
相关资源
最近更新 更多