c - 在我用 C 实现的基本单链表中,Do-while 表现得很有趣。请指出错误

标签 c linked-list

实现得很好。没有编译错误,一切正常。只是看起来 do-while 结构在不应该重复的时候重复了两次。例如,如果“插入新节点”选择“i”,则大小写应切换为“i”,调用插入函数,然后遍历列表。它确实做到了这一点,但也再次打印 do-while 循环中的所有内容并打印默认情况。

我将在我的代码输出之后发布代码。

这是我的 C 代码,它实现了一个链表及其基本的遍历和插入功能:

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

struct node
{
    int data;
    struct node *next;
};

void traverse(struct node *);
void insert(struct node **);

int main()
{
    char choice;
    struct node *head,**tohead;
    head=(struct node *)malloc (sizeof(struct node));
    tohead=&head;
    //STACKOVERFLOW NOTE: this is where I think the relevant portion begins
    do
    {
        printf("\nChoose operation to perform:\n");
        printf("\tInsert a node(i)\n");
        printf("\tShow currenct linked list(s)\n");
        printf("\tQuit without saving changes(q):\t");
        scanf("%c",&choice);
        switch(choice)
        {
            case 'i':
                insert(tohead);
                break;
            case 's':
                traverse(head);
                break;
            case 'q':
                printf("QUITTING\n");
                break;
            default:
                printf("Invalid choice\n");
        }
    }while(choice!='q');
}//STACKOVERFLOW NOTE: This is where I think relevant portion ends. Possibly.

void traverse(struct node *p)
{
    printf("Linked list looks like: ");

    if(p->next==0)
    {
        printf("nothing. It's EMPTY");
        p->next==NULL;
    }
    else
    {   while(p->next!=NULL)
        {
            printf("%d\t",p->data);
            p=p->next;
        }
        printf("%d",p->data);
    }
    printf("\n");
}

void insert(struct node **pp)
{
    int value,position;
    struct node *q;
    q=*pp;
    struct node *newnode=(struct node *)malloc(sizeof(struct node));
    printf("Insert what number?:\t");
    scanf("%d",&value);
    printf("In what position? Push '0' for last,'1' for first");
    printf("\n\t\tOR\nenter position no.:\t");
    scanf("%d",&position);
    newnode->data=value;
    if(position==1)
    {   newnode->next=q;
        *pp=newnode;
    }
    else if(position==0)
    {
        while(q->next!=NULL)
            q=q->next;
        q->next=newnode;
        newnode->next=NULL;
    }
    else if(position>1)
    {
        int i;
        for(i=1;i<position-1;i++)
            q=q->next;
        newnode->next=q->next;
        q->next=newnode;
    }
    else
        printf("Invalid Position");
    traverse(*pp);
}

这是一个示例输出:请注意 do-while 如何重复自身并显示“无效选择”

用户@主机:~$ ./a.out

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): i
Insert what number?:    5
In what position? Push '0' for last,'1' for first
        OR
enter position no.: 0
Linked list looks like: 0   5

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): Invalid choice

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): i
Insert what number?:    3
In what position? Push '0' for last,'1' for first
        OR
enter position no.: 1
Linked list looks like: 3   0   5

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): Invalid choice

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): i
Insert what number?:    2
In what position? Push '0' for last,'1' for first
        OR
enter position no.: 3
Linked list looks like: 3   0   2   5

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): Invalid choice

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): s
Linked list looks like: 3   0   2   5

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): Invalid choice

Choose operation to perform:
    Insert a node(i)
    Show currenct linked list(s)
    Quit without saving changes(q): q
QUITTING
user@host:~$ 

最佳答案

当您使用 Scanf 输入任何内容时,将以换行符结束。问题是 scanf 函数仅提取请求的输入,并将换行符保留在输入缓冲区中,因此在下一次迭代中,程序读取并提取该换行符,并将其视为无效输入并循环一次再次。

这个问题很容易解决:在"%c"格式代码前添加一个额外的空格,这样就

scanf(" %c",&choice);
/*     ^           */
/*     |           */
/* Note space here */

这将告诉 scanf 读取并丢弃所有前导空格(换行符)。

我还建议您阅读例如 this scanf reference .

关于c - 在我用 C 实现的基本单链表中,Do-while 表现得很有趣。请指出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24721369/

相关文章:

C - 初始化结构数组

c - C 中的链表循环输出

c++ - 重载的 + 和 - 运算符,无法弄清楚如何检查传入的 "amount"是否为负数

java - 如何将链接列表中的下一个元素打印到 CSV 文件?

c++ - 增量运算符/迭代器实现

c - 在 c 中有效暂停执行的最佳方法

c - 如何从文件中读取/写入包含 4 个指针的 C 结构到相同类型的结构?

c - 有没有办法用只有 pem 公钥文件或 pem 私钥文件的 RSA 进行加密和解密?

c - 在 fread/fwrite 期间去除 AES 填充

java - 从另一个类java访问主类中的链表