C语言链表插入不生效

问题遇到的现象和发生背景

插入第一次成功,但是插入第二次就报失败,不知道为什么

问题相关代码,请勿粘贴截图
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>

void menu (void);
void clear_input_queue();

typedef struct Link{
    char  *elem;
    struct Link *next;
}link;

link * initLink();
link * insertElem(link * p,char *elem,int add);
void display(link *p);

int main()
{
    menu();
    return 0;
}


void menu()
{
    // 初始化列表
    link *p=initLink();

    display(p);

    while(1){
        printf("select: a:展示全部链表, b:插入链表.\n");
        char ch;
        ch = getchar();
        
        switch(ch)
        {
            case 'a':
                printf("Then you choose show all.\n");
                display(p);  
                break;      
            case 'b':
                printf("Please enter which position you will add .\n");
                int n;
                while(scanf("%d",&n)!=1);
                {
                    while((ch=getchar())!='\n')
                        putchar(ch);
                }

                char name[50];
                gets(name);
                
                p = insertElem(p, name, n);
                display(p);
                break;
            case 'c':
                goto loop;
                break;

        }
    }
    loop:
        printf("Exit");
}

link * initLink(){
    link * p=(link*)malloc(sizeof(link)); //创建一个头结点
    link * temp=p; //声明一个指针指向头结点,用于遍历链表
    
    char *subways[] = {"第一个元素", "中间元素", "最后元素"};
    for (int i=0; i<3; i++) {
        link *a=(link*)malloc(sizeof(link));
        a->elem=subways[i];
        a->next=NULL;
        temp->next=a;
        temp=temp->next;
    }
    return p;
}

link * insertElem(link * p,char *elem,int add){
    link * temp = p;//创建临时结点temp
    link * c = NULL;
    int i = 0;
    //首先找到要插入位置的上一个结点
    for (i = 1; i < add; i++) {
        if (temp == NULL) {
            printf("插入位置无效\n");
            return p;
        }
        temp = temp->next;
    }
    c=(link*)malloc(sizeof(link));
    strcpy(c->elem,elem);
    // c->elem = tmp;
    c->next = temp->next;
    temp->next = c;
    return  p;
}


void display(link *p){
    link* temp=p; //将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp->next) {
        temp=temp->next;
        char *data = temp->elem;
        for (int i=0; i < strlen(data); i++){
            printf("%c",data[i]);
        }
        if (temp->next)
            printf(" --- ");
    }
    printf("\n");
}

运行结果及报错内容
第一个元素 --- 中间元素 --- 最后元素
select: a:展示全部链表, b:插入链表.
a
Then you choose show all.
第一个元素 --- 中间元素 --- 最后元素
select: a:展示全部链表, b:插入链表.    // 这里为啥显示两遍??
select: a:展示全部链表, b:插入链表.
b
Please enter which position you will add .
2       // 插入位置
元素1    // 插入元素
第一个元素 --- 元素1 --- 中间元素 --- 最后元素
select: a:展示全部链表, b:插入链表.
b
Please enter which position you will add .
2
元素2     //  后面就没了,退出程序了
我的解答思路和尝试过的方法
我想要达到的结果

正常插入

修改如下,修改处见注释,供参考:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
void menu(void);
void clear_input_queue();
typedef struct Link {
    char* elem;
    struct Link* next;
}link;
link* initLink();
link* insertElem(link* p, char* elem, int add);
void  display(link* p);
int main()
{
    menu();
    return 0;
}

void menu()
{
    // 初始化列表
    link* p = initLink();
    display(p);
    while (1) {
        printf("select: a:展示全部链表, b:插入链表.\n");
        char ch;
        ch = getchar(); 
        switch (ch)
        {
        case 'a':
            printf("Then you choose show all.\n");
            getchar();     //修改
            display(p);
            break;
        case 'b':
            printf("Please enter which position you will add .\n");
            int n;
            while (scanf("%d", &n) != 1)    //;  修改 多了';' 分号
            {
                while ((ch = getchar()) != '\n')
                    putchar(ch);
            }
            getchar();      //修改
            char name[50];
            gets(name);
            p = insertElem(p, name, n);
            display(p);
            break;
        case 'c':
            goto loop;
            break;
        }
    }
loop:
    printf("Exit");
}
link* initLink() {
    link* p = (link*)malloc(sizeof(link)); //创建一个头结点
    link* temp = p; //声明一个指针指向头结点,用于遍历链表
    char* subways[] = { "第一个元素", "中间元素", "最后元素" };
    for (int i = 0; i < 3; i++) {
        link* a = (link*)malloc(sizeof(link));
        a->elem = subways[i];
        a->next = NULL;
        temp->next = a;
        temp = temp->next;
    }
    return p;
}
link* insertElem(link* p, char* elem, int add) {
    link* temp = p;//创建临时结点temp
    link* c = NULL;
    int   i = 0;
    //首先找到要插入位置的上一个结点
    for (i = 1; i < add; i++) {
        if (temp->next == NULL) {     // if (temp == NULL) 修改
            printf("插入位置无效\n");
            return p;
        }
        temp = temp->next;
    }
    c = (link*)malloc(sizeof(link));
    c->elem = (char*)malloc(sizeof(char) * 50);  // 修改
    strcpy(c->elem, elem);
                                  // c->elem = tmp;
    c->next = temp->next;
    temp->next = c;
    return  p;
}
void display(link* p) {
    link* temp = p; //将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp->next) {
        temp = temp->next;
        char* data = temp->elem;
        for (int i = 0; i < strlen(data); i++) {
            printf("%c", data[i]);
        }
        if (temp->next)
            printf(" --- ");
    }
    printf("\n");
}

  1. select: a:展示全部链表, b:插入链表. // 这里为啥显示两遍??
    因为输入a之后还有一个回车,在getchar()后在调用一次

  2. 退出程序是因为程序第96行, strcpy(c->elem,elem); 这里c->elem指针没有申请内存


#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
void menu(void);
void clear_input_queue();
typedef struct Link {
    char* elem;
    struct Link* next;
}link;
link* initLink();
link* insertElem(link* p, char* elem, int add);
void display(link* p);
int main()
{
    menu();
    return 0;
}

void menu()
{
    // 初始化列表
    link* p = initLink();
    display(p);
    while (1) {
        printf("select: a:展示全部链表, b:插入链表.\n");
        char ch;
        scanf("%c",&ch);
        switch (ch)
        {
        case 'a':
            printf("Then you choose show all.\n");
            display(p);
            break;
        case 'b':
            printf("Please enter which position you will add .\n");
            int n;
            while (scanf_s("%d", &n) != 1);
            {
                while ((ch = getchar()) != '\n')
                    putchar(ch);
            }
            char name[50];
            scanf_s("%s", &name);
            p = insertElem(p, name, n);
            display(p);
            break;
        case 'c':
            goto loop;
            break;
        default:
            break;
        }
    }
loop:
    printf("Exit");
}
link* initLink() {
    link* p = (link*)malloc(sizeof(link)); //创建一个头结点
    link* temp = p; //声明一个指针指向头结点,用于遍历链表
    char subways[][11] = { "第一个元素", "中间元素", "最后元素" };
    for (int i = 0; i < 3; i++) {
        link* a = (link*)malloc(sizeof(link));
        a->elem = subways[i];
        a->next = NULL;
        temp->next = a;
        temp = temp->next;
    }
    return p;
}
link* insertElem(link* p, char* elem, int add) {
    link* temp = p;//创建临时结点temp
    link* c = NULL;
    int i = 0;
    //首先找到要插入位置的上一个结点
    for (i = 1; i < add; i++) {
        if (temp == NULL) {
            printf("插入位置无效\n");
            return p;
        }
        temp = temp->next;
    }
    c = (link*)malloc(sizeof(link));
    c->elem = (char*)malloc(sizeof(char));
    c->next = NULL;
    strcpy(c->elem, elem);
    // c->elem = tmp;
    c->next = temp->next;
    temp->next = c;
    return  p;
}

void display(link* p) {
    link* temp = p; //将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp->next) {
        temp = temp->next;
        char* data = temp->elem;
        for (int i = 0; i < strlen(data); i++) {
            printf("%c", data[i]);
        }
        if (temp->next)
            printf(" --- ");
    }
    printf("\n");
}