标签 C/C++ 下的文章

单链表操作

  1. Status 是函数的类型,其值是函数结果状态代码

    typedef int Status

  2. //函数结果状态代码

    #define True 1

    #define False 0

    #define OK 1;

    #define ERROR 0

    #define INFEASIBLE -1

    #define OVERFLOW -2




     

1.单链表的定义和表示

typedef struct {
    char name[10];
    char num[20];
    double score;
}Stu;

typedef struct LNode {
    Stu data;
    struct LNode *next;
}LNode,*LinkList;

 

2.初始化链表(带头结点的单链表)

思路:

  1. 生成新结点作头结点,用头指针L指向头结点
  2. 头结点的指针域置空
Status InitList_L(LinkList L)
{
    L = (LinkList)mallloc(sizeof(LNode));
    L->next = NULL;
    return OK;
}

 

3.判断链表是否为空

  1. 空表:链表中无元素(头指针和头结点仍然存在)

    思路:判断头结点指针域是否为空

    Status ListEmpty(LinkList L)
    {
       if(L->netx)
           return 0;
        else
            return 1;
    }
    

 

4.销毁单链表

思路:从头指针开始,依次释放所有结点

Status DestroyList_L(LinkList L)
{
    LNode *p; //或者 LinkList p;
    while(L)
    {
        p=L;
        L=L->next;
        free p;
    }
}

 

5.清空单链表

思路:依次释放所有结点,并为头结点指针域设置为空

Status ClearList(LinkList L)
{
    LNode *p,*q;
    p=L->next;
    while(p)
    {
        q = p->next;
        free p;
        p = q;
    }
    L->next = NULL; //头结点指针域为空
    return OK;
}

 

6.求单链表长度

思路:从首元结点开始,依次计数所有结点

Status ListLength_L(LinkList L)
{
    LNode *p;
    p = L->next; //p指向第一个结点
    int i = 0;
    while(p)  //遍历单链表,统计结点数
    {
        i++;
        p = p->next;
    }
    return i;
}

 

7.取值

Status GetElem_L(LinkList L, int i, ElemType e)
{
    LinkList p = L->next; 
    int j = 1;  //p指向第一个结点,j做计数器,累计当前扫描过的结点数
    while(p && j<i)  //向后扫描,p指向第i个元素或者p为空
    {
        p = p->next;
        j++;
    }
    if (!p || j>i)   //第i个元素不存在
        return ERROR;
    e = p->data;    //取第i个元素
    return Ok;
}

 

8.按值查找

Status LocatElem_L(LinkList L,Elemtype e)
{
    LinkList p = L->next;
    int j = 1;
    while(p && p->data != e)
    {
        p = p->next;  //遍历
        j++;          //位置序号
    }
    if(p)
        return i;
    else 
        return 0;
}

 

9.插入值

思路:

  1. 想要在链表第 i 个元素前面插入新结点,则需要将指针指向第 i-1 个元素,从而将其 next 域中保存的第 i 个元素地址赋值给新结点,实现链接
LinkList p = L;
int j = 0;
while(p && j<i-1)
  1. 代码中创建了指向头结点的指针变量,初始化起点并非首元结点,所以要想在第 i 个位置插入,while 循环次数需为 i-1

    若初始化为首元结点,即

    LinkList p = L->next;
    

    则 while 循环次数为 i-2,从而根据循环次数要求去初始化 j 或改变循环结束的条件

     

Status ListInsert_L(LinkList L, int i, Elemtype e)
{
    LinkList p = L;
    int j = 0;
    while(p && j<i-1)
    {
        p = p->next;
        ++j;
    }
    if(!p || j>i-1)
        return ERROR;
    s = (LinkList)malloc(sizeof(LNode));
    s->data = e;
    s->next = p->next;
    p->next = s;
    return Ok;
}

 

10. 删除第 i 个结点

Status ListDelete_L(LinkList_L, int i, Elemtype e)
{
    LinkList p = L;
    LinkList q;
    int j = 0;
    while(p->next && j<i-1)   //寻找第i个结点,并令p指向其前驱
    {
        p = p->next;
        ++j;
    }
    if(!(p->next) || j>i-1) //删除位置不合理
        return ERROR;
    q = p->next;        //临时保存被删除结点的地址以备释放
    p->next = q->next;  //改变删除结点的前驱结点的指针域
    e = q->data;        //保存删除结点的数据域
    free q;             //释放删除结点的空间
    return OK;
}


 

单链表的创建

1. 头插法(前插法)

思路:

  1. 从一个空表L开始,重复读入数据;
  2. 生成新结点,将读入数据存放到新结点的数据域中
  3. 从最后一个结点开始,依次将各结点插入到链表的前端
void CreatList_H(LinkList L, int n)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;  //建立一个带头结点的单链表
    for(i=n; i>0; --i)
    {
       p = (LinkList)malloc(sizeof(LNode));  //生成新结点p
        scanf(&p->data);                    //获取输入值
        p->next = L->next;                //插入到表头
        L->next = p;
    }
}

 

2. 尾插法(后插法)

思路:

  1. 从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针 r 指向链表的尾结点
  2. 初始时,r 同 L 均指向头结点。每读入一个数据元素则申请一个新结点,将新结点插入到尾结点后,r 指向新结点
void CreatList(LinkList L, int n)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    LNode *r;
    r = L;   //尾指针 r 指向头结点
    for(i=0; i<n; i++)
    {
        p = (LinkList)malloc(sizeof(LNode));   //生成新结点,输入元素值
        scanf(&p->data);
        p->next = NULL;
        r->next = p;    //插入到表尾
        r = p;          //r 指向新的尾结点
    }
}

 

循环链表

1.创建

//先创建初始化结点函数
LinkList initlist()
{
    LNode *head = (LinkList)malloc(sizeof(LNode));
    if(head == NULL)
    {
        printf("创建失败,退出程序");
    }
    else
    {
        head->next = NULL;
        return head;
    }
}

//创建循环链表
Status Insert_List(LNode *head)
{
    int data;
    printf("输入插入的元素:");
    scanf("%d",&data);
    
    LinkList node = initlist();
    node->data = data;   //初始化新结点
    
    if(head != NULL)
    {
        LNode *p = head;
        while(p->next != head)  //找到最后一个元素
        {
            p = p->next;
        }
        p->next = node;
        node->next = head;
        return 1;
    }
    else
    {
        printf("头结点已无元素\n");
        return 0;
    }
}

 

2. 带尾指针循环链表合并

LinkList Connect(LinkList Ta, LinkList Tb)
{  //假设Ta,Tb都是非空的单循环链表 
    p = Ta->netx;       //p 存表头结点
    Ta->next = Tb->next->next;  //Tb 表头连接 Ta 表尾
    free Tb->next;         //释放 Tb 表头结点
    Tb->next = p;          //修改指针
    return Yb;
}//时间复杂度O(1)

 

双向链表

1. 创建

//结点创建
typedef struct DuLNode
{
    Elemtype data;           //data
    struct DuLNode *pre;   //前驱 node
    struct DuLNode *next;  //后继 node
}DuLNode,*DuLinkList;

//插入数据
Status ListInsert_DuL(DuLinkList L, int i, ElemType e)
{
    //在带头结点的双链循环线性表L中第i个位置之前插入元素e
    //i的合法值为 1<=i<=表长+1
    if(!(p = GetElemP_DuL(L,i)))  //在L中确定插入的位置
        return ERROR;         //p=NULL,即插入位置不合法
    if(!(s=(DuLinkList)malloc(sizeof(DuLNode))))
        return ERROR;
    s->data = e;
    s->prior = p->prior;    p->prior->next = s;
    s->next = p;            p->prior = s;
    return OK;
}//LinkInsert_DuL

2.删除

Status ListDelete_DuL(DuLinkList L, int i, ElemType e)
{
    //删除带头结点的双链循环线性表L的第i个元素,i的合法值为1<=i<=表长
    if(!(p = GetElemP_DuL(L,i)))   //在L中确定第i个元素的位置指针p
        return ERROR;
    e = p->data;
    p->prior->next = p->next;
    p->next->prior = p->prior;
    free(p);
    return OK;
}ListDelete_DuL

 

--> 单链表操作Status 是函数的类型,其值是函数结果状态代码typedef int Status//函数结果状态代码#define True 1#define False 0#define OK 1;#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2 1.单链表的定义和表示typedef struct { c...

实现功能

1.录入(添加)学生信息:学号、姓名、平时成绩和考试成绩,总评成绩。
2.查询学生成绩:输入要查询的学生的学号,查询该学生的信息并显示。
3.显示学生成绩单:按学号顺序显示学生成绩单。
4.删除学生信息:输入要删除的学生的学号,,删除该学生的信息。
5.修改学生信息:输入要修改的学生的学号,显示该学生的原有信息,用户输入修改后的信息。

 

知识点

1.C语言的量声明和定义,以及变量初始化和生命周期与可见性
2.C语言指针的定义,初始化
3.C语言内存的申请和释放
4.C语言循环结构、选择结构、分支结构
5.C语言结构体
6.C语言数据结构之链表
7.C语言函数声明、实现、调用
8.C语言函数的参数、返回值
9.C语言文件打开、操作(读写)、关闭

代码

//宏定义区
#define _CRT_SECURE_NO_DEPRECATE  //防止VS警告

//头文件区
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

//全局变量区
//学生结构体
typedef struct tagStudent
{
    char Num[10];//学号
    char Name[20];//姓名
    double Regular_Score;//平时成绩
    double Final_Score;//期末成绩
    double Total_Score;//总评成绩
}Student;

//学生链表结点
typedef struct tagNode
{
    Student Stu;//数据域:学生信息
    struct tagNode *pNext;//指针域:指向下一个学生结点
}Node;

//定义链表的第一个学生,即学生单链表的头结点
Node *g_pHead = NULL;

//全局函数定义区
// 打印功能菜单
void Print_Menu();
//1录入学生信息
void Enter_Students();
//2查询学生信息
Node* Inquire_Students();
//3显示学生信息
void Display_Students();
//4删除学生信息
void Deleting_Students();
//5修改学生信息
void Amend_Students();

//程序的主函数——程序入口
int main(int argc, char *argv[])
{
    while (1)//死循环
    {
        //清屏
        system("CLS");

        //打印功能菜单
        Print_Menu();

        char  ch;
        //控制台无回显获取信息
        ch = _getch();

        //switch分支选择结构
        switch (ch)
        {
        case'1': //1录入学生信息
            Enter_Students();
        break;

        case'2': //2查询学生信息
        {
            Node *pNode = Inquire_Students();
            if (pNode != NULL)
            {
                printf("%s\t %s\t %0.2lf \t%0.2lf \t%0.2lf\t\n",
                    pNode->Stu.Num,   //学号
                    pNode->Stu.Name, //姓名
                    pNode->Stu.Regular_Score,//平时成绩
                    pNode->Stu.Final_Score,  //期末成绩
                    pNode->Stu.Total_Score); //总评成绩
            }
            else
            {
                printf("未找到学生信息,请确认学生信息!\n");
            }
        break;
        }

        case'3': //3显示学生信息
            Display_Students();
        break;

        case'4': //4删除学生信息
            Deleting_Students();
        break;

        case'5': //5修改学生信息
            Amend_Students();
        break;

        case'0': //退出程序系统
            printf("欢迎再次使用!\n");
            return 0;
        break;

        default: //程序的健壮性,友好提示
            printf("您输入的选择有错误,请重新选择功能!\n");
        break;
        }
    system("PAUSE");
    }
    return 0;
}

//全局函数实现区
// 打印功能菜单
void Print_Menu()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================请选择对应功能================\n");
    printf("=================================================\n");
    printf("=\t\t1、录入学生信息\t\t\t=\n");
    printf("=\t\t2、查询学生信息\t\t\t=\n");
    printf("=\t\t3、显示学生信息\t\t\t=\n");
    printf("=\t\t4、删除学生信息\t\t\t=\n");
    printf("=\t\t5、修改学生信息\t\t\t=\n");
    printf("=\t\t0、退出程序系统\t\t\t=\n");
    printf("=================================================\n");

    return;
}

//1录入学生信息
void Enter_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================录入学生信息功能================\n");
    printf("=================================================\n");
    printf("\n请依次输入学生信息:\n\n|学号 \t|姓名   |平时成绩|  |期末成绩|  |总评成绩|\n");

    //定义单链表的一个结点:当前结点
    Node *p;

    //将头结点给当前结点
    p = g_pHead;

    //在插入新结点前找到尾结点,
    while (g_pHead != NULL && p->pNext != NULL)
    {
        p = p->pNext;
    }

    //为新的学生元素分配一个空间
    //mallac  void*  泛类型   强制类型转换
    Node* pNewNode = (Node*)malloc(sizeof(Node));
    pNewNode->pNext = NULL;

    //将新节点插入尾结点或者作为头结点
    if (g_pHead == NULL)
    {
        g_pHead = pNewNode;
        p = g_pHead;
    }
    else
    {
        //p的下一个节点为pNewNode
        p->pNext = pNewNode;
    }

    //输入新的学生数据信息
    scanf("%s %s %lf %lf %lf", pNewNode->Stu.Num,        //学号  数组名就是数组首地址
        pNewNode->Stu.Name,                  //姓名
        &pNewNode->Stu.Regular_Score,    //平时成绩
        &pNewNode->Stu.Final_Score,      //期末成绩
        &pNewNode->Stu.Total_Score); //总评成绩

    printf("\n学生信息录入系统成功!\n");

    return;
}

//2查询学生信息
Node *Inquire_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================查询学生信息功能================\n");
    printf("=================================================\n");
    char Num[10]; //学号

    printf("\n请输入需要查询学生的学号:\n");

    scanf("%s",Num);

    Node  *p = g_pHead;
    printf("\n学号\t姓名\t平时成绩\t期末成绩\t总评成绩\t\n");

    //遍历链表
    while (p != NULL)
    {
        /*if (p->Stu.Num == Num) 字符数组不能比较
        需要字符比较      调用函数stricmp 以大小写不敏感方式比较两个串
        用法:int  stricmp( char  *str1,  char  *str2);
        返回值大于0,则str1>str2
        返回值小于0,则str1<str2
        返回值等于0,则str1=str2*/
        int  ptr = _stricmp(p->Stu.Num , Num);
        //如果找到学生信息
        if (ptr  ==  0)
        {
            return  p;
        }
        //否则继续找,直到遍历完链表退出while
        p = p->pNext;
    }

    //遍历完没有找到学生信息
    if (p == NULL)
    {
        return  NULL;
    }

    return  NULL;
}

//3显示学生信息
void Display_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================显示学生信息功能================\n");
    printf("=================================================\n");

    Node  *p = g_pHead;
    printf("学号\t| 姓名\t| 平时成绩\t| 期末成绩\t| 总评成绩\t|\n");

    //如果链表里没有学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请先录入学生信息!\n\n");
        return;
    }

    //如果链表里有学生信息,则遍历链表
    while (p != NULL)
    {
        printf("%s\t|  %s\t|  %0.2lf \t| %0.2lf \t| %0.2lf\t|\n",
                    p->Stu.Num,                  //学号
                    p->Stu.Name,                 //姓名
                    p->Stu.Regular_Score,    //平时成绩
                    p->Stu.Final_Score,      //期末成绩
                    p->Stu.Total_Score); //总评成绩);

        p = p->pNext;
    }
    printf("=================================================\n");
    return;
}

//4删除学生信息
void Deleting_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================删除学生信息功能================\n");
    printf("=================================================\n");
    char Num[10];  //学号

    printf("\n请输入需要删除学生的学号:\n");

    scanf("%s", Num);

    Node  *p = g_pHead;

    //定义一个临时变量结点
    Node  *p2 = NULL;

    //如果要删除的学生信息是链表的头结点
    int  ptr = _stricmp(g_pHead->Stu.Num , Num);
    if (ptr  ==  0)
    {
        p2 = g_pHead;
        g_pHead = g_pHead->pNext;
        //释放内存,删除信息
        free(p2);
        printf("删除学生信息成功!");
        return;
    }

    //删除的学生信息不是头结点
    while (p->pNext  !=  NULL)
    {
        int  ptr = _stricmp(p->pNext->Stu.Num, Num);
        if (ptr  ==  0)
        {
            p2 = p->pNext;
            p->pNext = p->pNext->pNext;
            //释放内存,删除信息
            free(p2);
            printf("删除学生信息成功!");
            return;
        }
        if (ptr != 0)
        {
            printf("学生信息不正确,请确认学生信息!");
        }
        //遍历链表
        p = p->pNext;
    }
    //遍历完没有找到学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请确认学生信息!\n\n");
    }
    return;
}

//5修改学生信息
void Amend_Students()
{
    //清屏
    system("CLS");
    printf("=================================================\n");
    printf("===============欢迎使用高校学生管理系统==========\n");
    printf("=================================================\n");
    printf("===================修改学生信息功能================\n");
    printf("=================================================\n");

    char Num[10];  //学号

    printf("\n请输入需要修改学生的学号:");

    scanf("%s", Num);

    Node  *p = g_pHead;

    //遍历链表
    while (p != NULL)
    {
        int  ptr = _stricmp(p->Stu.Num, Num);
        if (ptr  ==  0)
        {
            //显示要修改学生信息
            printf("=================================================\n");
            printf("%s\t|  %s\t|  %0.2lf \t| %0.2lf \t| %0.2lf\t|\n",
                p->Stu.Num,                  //学号
                p->Stu.Name,                 //姓名
                p->Stu.Regular_Score,    //平时成绩
                p->Stu.Final_Score,      //期末成绩
                p->Stu.Total_Score); //总评成绩);
            printf("=================================================\n");
            printf("请修改学生信息\n\n");
            printf("学号\t姓名\t平时成绩\t期末成绩\t总评成绩\t\n");
            scanf("%s %s %lf %lf %lf",
                p->Stu.Num,                  //学号
                p->Stu.Name,                 //姓名
                &p->Stu.Regular_Score,   //平时成绩
                &p->Stu.Final_Score,     //期末成绩
                &p->Stu.Total_Score);    //总评成绩
            printf("修改学生信息成功!\n");
            break;
        }
        //遍历链表
        p = p->pNext;
    }
    //遍历完没有找到学生信息
    if (p == NULL)
    {
        printf("未找到学生信息,请确认学生信息!\n\n");
    }
    return;
}

--> 实现功能1.录入(添加)学生信息:学号、姓名、平时成绩和考试成绩,总评成绩。2.查询学生成绩:输入要查询的学生的学号,查询该学生的信息并显示。3.显示学生成绩单:按学号顺序显示学生成绩单。4.删除学生信息:输入要删除的学生的学号,,删除该学生的信息。5.修改学生信息:输入要修改的学生的学号,显示该学生的原有信息,用户输入修改后的信息。 知识点1.C语言的量声明和定义,以及变量初始化和生命周期...

typedef struct Link{
    char elem; //代表数据域
    struct Link * next; //代表指针域,指向直接后继元素
}link; //link为节点名,每个节点都是一个 link 
//提示,由于指针域中的指针要指向的也是一个节点,因此要声明为 Link 类型
(这里要写成 struct Link* 的形式)。

  1. 头指针:一个普通的指针,它的特点是永远指向链表第一个节点的位置。很明显,头指针用于指明链表的位置,便于后期找到链表并使用表中的数据;
  2. 节点:链表中的节点又细分为头节点、首元节点和其他节点:
    • 头节点:其实就是一个不存任何数据的空节点,通常作为链表的第一个节点。对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题;
    • 首元节点:由于头节点(也就是空节点)的缘故,链表中称第一个存有数据的节点为首元节点。首元节点只是对链表中第一个存有数据节点的一个称谓,没有实际意义;
    • 其他节点:链表中其他的节点;

创建一个存储 {1,2,3,4} 的链表,C 语言完整代码如下:

#include <stdio.h>
#include <stdlib.h>
//链表中节点的结构
typedef struct Link {
    int  elem;
    struct Link *next;
}link;
//初始化链表的函数
link * initLink();
//用于输出链表的函数
void display(link *p);

int main() {
    link*p = NULL;
    //初始化链表(1,2,3,4)
    printf("初始化链表为:\n");
    p = initLink();
    display(p);
    return 0;
}

link * initLink() {
    int i;
    link * p = NULL;//创建头指针
    link * temp = (link*)malloc(sizeof(link));//创建首元节点
    //首元节点先初始化
    temp->elem = 1;
    temp->next = NULL;
    p = temp;//头指针指向首元节点
    for (i = 2; i < 5; i++) {
        link *a = (link*)malloc(sizeof(link));
        a->elem = i;
        a->next = NULL;
        temp->next = a;
        temp = temp->next;
    }
    return p;
}
void display(link *p) {
    link* temp = p;//将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp) {
        printf("%d ", temp->elem);
        temp = temp->next;
    }
    printf("\n");
}

注意,如果使用带有头节点创建链表的方式,则输出链表的 display 函数需要做适当地修改:

void display(link *p){
    link* temp=p;//将temp指针重新指向头结点
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while (temp->next) {
        temp=temp->next;
        printf("%d",temp->elem);
    }
    printf("\n");
}

--> 链表中每个数据的存储都由以下两部分组成:数据元素本身,其所在的区域称为数据域;指向直接后继元素的指针,所在的区域称为指针域;因此,链表中每个节点的具体实现,需要使用 C 语言中的结构体,具体实现代码为typedef struct Link{ char elem; //代表数据域 struct Link * next; //代表指针域,指向直接后继元素}link; //link为节...

#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL   40
#define MAXAUTL   40
#define MAXBKS   100              //最大书籍数

struct book {                     //建立book结构声明
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

int main(void)
{
    struct book library[MAXBKS]; //book 类型结构的数组
    int count = 0;
    int index;
    
    printf("Please enter the book title.\n");
    printf("Press [enter] at the start of a line to stop.\n");
    while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
           && library[count].title[0] != '\0')

//library[count].title[0] != '\0'判断字符串中的首字符是否为空字符
//按下 Enter 键相当于输入了一个字符串
    {
        printf("Now enter the author.\n");
        s_gets(library[count].author, MAXAUTL);
        printf("Now enter the value.\n");
        scanf("%f", &library[count++].value);
        while (getchar() != '\n')
            continue;          //清理输入行
        if (count < MAXBKS)
            printf("Enter the next title.\n");
    }
    
    if (count > 0)
    {
        printf("Here is the list of your books:\n");
        for (index = 0; index < count; index++)
            printf("%s by %s: $%.2f\n", library[index].title,
                   library[index].author, library[index].value);
    }
    else
    	printf("No books? Too bad.\n");
    
    return 0;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // 查找换行符
        if (find)                  //如果地址不是NULL
            *find = '\0';          // 在此处放置一个空字符
        else
            while (getchar() != '\n')
                continue;          // 处理输入行中剩余的字符
    }
    return ret_val;
}

--> #include <stdio.h> #include <string.h> char * s_gets(char * st, int n); #define MAXTITL 40 #define MAXAUTL 40 #define MAXBKS 100 //最大书籍数 struct book { ...

/*char *s_gets(char *st, int n)是为了获取字符st中的n个元素,
并将其结果返回为s_gets的字符指针。功能类似于fgets函数,
但它解决了fgets函数会读取'\n'的问题。*/

#include <stdio.h>
#include <string.h>

char * s_gets(char *st, int n);
int main()
{
    
    char name[20];
    printf("输入姓名\n");
    s_gets(name,20);
    printf("姓名为:%s\n",name);

    return 0;
}

char * s_gets(char *st, int n)
{
    char * ret_val;
    char * find;
                                     //表示从标准输入流中读取n-1个元素到字符st中,再将
    ret_val = fgets(st,n,stdin);     //再将指针ret_val指向指针st               
    if (ret_val)                      //if语句为了避免fgets函数返回值为NULL的情况
    {
        find  = strchr(st, '\n');      //查找换行符
        if (find)
            *find =  '\0';             //替换为空字符
        else
            while (getchar() != '\n')  //清除IO缓冲区 
                  continue;
    }
    return ret_val;
}

--> /*char *s_gets(char *st, int n)是为了获取字符st中的n个元素,并将其结果返回为s_gets的字符指针。功能类似于fgets函数,但它解决了fgets函数会读取'\n'的问题。*/#include <stdio.h>#include <string.h>char * s_gets(char *st, int n);int main(){ ...