x072816 发表于 2015-6-15 22:10:43

单链表插入问题

我照着网上程序编了一个单链表的学生健康统计的c语言程序,但进行插入操作,出现问题。

#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <math.h>
#include <process.h>

//函数结果状态
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef int Status;//STATUS 是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean;//Boolean是布尔类型,其值是TRUE或FALSE

#define NAMELEN 8//姓名最大长度
#define CLASSLEN 4//班级名最大长度
#define N 4//student记录的个数

typedef struct stud//记录的结构
{
        char name;
        long num;
        char sex;
        int age;
        char Class;
        int health;
}stud;
typedefstud ElemType;//链表结点元素类型为结构体

char sta ={"健康","一般","神经衰弱"};//健康状况
FILE *fp;

typedef struct LNode
{
    ElemType data;            //单链表中的数据域   
    struct LNode *next;          //单链表的指针域   
}LNode,*LinkList;
/********************************************************************************/
//单链表的初始化
//函数要求采用地址调用,才能改变主函数中的值,动态分配内存
Status InitList(LinkList *L)
{
        //构造一个空的单链表
    *L = (LinkList )malloc(sizeof(LinkList));   //申请结点空间   
    if(*L == NULL)                     //判断是否有足够的内存空间   
      printf("申请内存空间失败/n");
    (*L)->next = NULL;                  //将next设置为NULL,初始长度为0的单链表
        return OK;
}

/********************************************************************************/
//初始条件单链表已经讯在
//操作结果依次对L的每一个数据元素调用函数vi(),一但调用失败
//则是操作失败,vi()形参为指针,表示可通过调用函数改变元素的值
Status ListTraverse(LinkList L,void(*vi)(ElemType ))
{
        LinkList p = L->next;
        while(p)
        {
                vi(p->data);
                p = p->next;
        }
   printf("\n");
       return OK;
}
/********************************************************************************/
void Print(ElemType e)
{
        //显示记录e的内容
        printf("%-8s %6ld", e.name,e.num);
        if(e.sex == 'm')
          printf(" 男");
        else
          printf(" 女");
        printf("%5d %-4s",e.age,e.Class);
        printf("%9s\n",sta);       
}
/********************************************************************************/
//初始条件:按非降序排列的顺序线性表L已存在
// 操作结果:在L中按非降序插入新的数据元素e,L的长度加1
void InsertAscend(LinkList L,ElemType e)
{
        LinkList q = L, p = L->next;
        LinkList s = (LinkList )malloc(sizeof(LNode));
        if(!s)
        {
          printf("分配内存不成功!");
          exit(0);
    }
        s->data = e;
        while(p && (e.num > p->data.num))
        {
                q = p;
                p = p->next;
        }
        q->next = s;
        s->next = p;       
}

/********************************************************************************/
void ReadIn( stud *e)
{
        //由键盘输入结点信息
        printf("请输入姓名(<=%d个字符):",NAMELEN);
        scanf("%s",e->name);
        printf("请输入学号:");
        scanf("%ld",&e->num);
        printf("请输入性别(m:男f:女)");
        scanf("%*c%c",&e->sex);
        printf("请输入年龄:");
        scanf("%d",&e->age);
        printf("请输入班级(<=%d个字符)",CLASSLEN);
        scanf("%s",e->Class);
        printf("请输入健康状况(0:%s 1:%s 2:%s):",sta,sta,sta);
        scanf("%d",&e->health);
}
/********************************************************************************/
void WriteToFile( stud e)
{
        //将结点信息写入fp指定的文件中
        fwrite(&e,sizeof(stud),1,fp);
}
/********************************************************************************/
Status ReadFromFile(stud e)
{
        //由fp指定的文件读取结点信息到e
        int i ;
        i = fread(&e,sizeof(stud),1,fp);
        if(i == 1) //读取文件成功
          return OK;
        else
          return FALSE;
}
/********************************************************************************/
Status FindFromNum(LinkList L,long num,LinkList p,LinkList q)
{
        //查找表中学号为num的结点,如果找到,q指向此结点,p指向q的前驱
        //并返回TRUE,如果无此元素,则返回FALSE
        p = L;
        while(p)
        {
                q = p->next;
                if(q && q->data.num > num)//因为是按学号非降序排列
                  break;
                if(q && q->data.num == num)
                  return TRUE;
                p =q;
        }
        return FALSE;
}
/********************************************************************************/
Status FindFromName(LinkList L,char name[],LinkList p,LinkList q)
{
        //查找表中姓名为name的结点,如果找到,q指向此结点,p指向q的前驱
        //并返回TRUE,如果无此元素,则返回FALSE
        p = L;
        while(p)
        {
                q = p->next;
                if(q && !strcmp(q->data.name , name))//因为是按学号非降序排列
                  return TRUE;
                p = q;
        }
        return FALSE;
}
/********************************************************************************/
Status DeleteElemNum(LinkList L,long num)
{
        //删除表中学号为num的元素,并返回TRUE,如果无此元素,则返回FALSE
        LinkList p,q;
        if(FindFromNum(L,num,p,q))//找到此结点,且q指向该结点,p指向其前驱
    {
            p->next = q->next;
                free(q);
                return TRUE;
    }
        return FALSE;       
}
/********************************************************************************/
Status DeleteElemName(LinkList L,char name[])
{
        //删除表中姓名为name的元素,并返回TRUE,如果无此元素,则返回FALSE
        LinkList p,q;
        if(FindFromName(L,name,p,q))//找到此结点,且q指向该结点,p指向其前驱
    {
            p->next = q->next;
                free(q);
                return TRUE;
    }
        return FALSE;       
}
/********************************************************************************/
void Modify(ElemType e)
{
        //修改结点内容
        char s;
        Print(e); //显示原内容
        printf("请输入待修改项的内容,不修改的项按回车键保持原值:\n");
       
        printf("请输入姓名(<=%d个字符):",NAMELEN);
        gets(s);
        if(strlen(s))
           strcpy(e.name,s);
        printf("请输入学号:");
        gets(s);
        if(strlen(s))
           e.num = atol(s);
        printf("请输入性别(m:男f:女)");
        gets(s);
        if(strlen(s))
          e.sex = s;
        printf("请输入年龄:");
        gets(s);
        if(strlen(s))
           e.age = atol(s);
        printf("请输入班级(<=%d个字符)",CLASSLEN);
        gets(s);
        if(strlen(s))
           strcpy(e.Class,s);
        printf("请输入健康状况(0:%s 1:%s 2:%s):",sta,sta,sta);
        gets(s);
        if(strlen(s))
           e.health = atol(s);//修改完毕
}
/********************************************************************************/
/********************************************************************************/
int main(void)
{   //表的初始记录
        ElemType student = {{"王小林",790631,'m',18,"计91",0},
                               {"刘建平",790633,'m',21,"计91",0},
                               {"陈红",790632,'f',20,"计91",1},
                               {"张立立",790634,'m',17,"计91",2}};
       
        int i=0,j=0,flag =1;
        long num;
        char filename,name;
        ElemType e;
        LinkList T,q,p;
        InitList(&T);

          
       
        while(flag)
        {
                printf("1:将结构体数组student中的记录按学号非降序插入链表\n");
                printf("2:将文件中的记录按学号非降序插入链表\n");
                printf("3:键盘输入新纪录,并将其按学号非降序插入链表\n");
                printf("4:删除链表中第一个有给定学号的记录\n");
                printf("5:删除链表中第一个有给定姓名的记录\n");
                printf("6:修改链表中第一个有给定学号的记录\n");
                printf("7:修改链表中第一个有给定姓名的记录\n");
                printf("8:查找链表中第一个有给定学号的记录\n");
                printf("9:查找链表中第一个有给定姓名的记录\n");
                printf("10:显示所有记录\n11:将链表中所有记录存入文件\n12:结束\n");
                printf("请选择操作命令:");
                scanf("%d",&i);
                switch(i)
                {
                        case 1:
                        for(j = 0; j < N; j++)
                   InsertAscend(T,student);
                   ListTraverse(T,Print);
                                break;

                        case 2:
                                printf("请输入文件名:");
                                scanf("%s",filename);
                                if((fp = fopen(filename,"rb")) == NULL)
                                   printf("打开文件失败!\n");
                                else
                                {
                                  while(ReadFromFile(e))
                                  InsertAscend(T,e);
                                fclose(fp);
                          }
                          break;
                  case 3:
                          ReadIn(&e);
                          InsertAscend(T,e);
                          break;
                  case 4:
                          printf("请输入待删除记录的学号:");
                                scanf("%ld",&num);
                                if(!DeleteElemNum(T,num))
                                   printf("没有学号为%ld的记录\n",num);
                        break;
                  case 5:
                          printf("请输入待删除记录的姓名:");
                                scanf("%s",name);
                                if(!DeleteElemName(T,name))
                                   printf("没有姓名为%s的记录\n",name);
                          break;
                  case 6:
                          printf("请输入待修改记录的学号:");
                                scanf("%ld%*c",&num);//%*c吃掉回车符
                                if(!FindFromNum(T,num,p,q))
                                   printf("没有学号为%ld的记录\n",num);
                                else
                                {
                                        Modify(q->data);
                                        if(q->data.num != num)//学号被修改
                                        {
                                                p->next = q->next;//把q所指的结点从L中删除
                                                InsertAscend(T,q->data);//吧元素插入L
                                                free(q);//删除q
                                        }
                                }
                          break;
                  case 7:
                          printf("请输入待修改记录的姓名:");
                                scanf("%ld%*c",name);//%*c吃掉回车符
                                if(!FindFromName(T,name,p,q))
                                   printf("没有姓名为%s的记录\n",num);
                                else
                                {
                                        num = q->data.num; //把学号存入num
                                        Modify(q->data);
                                        if(q->data.num != num)//学号被修改
                                        {
                                                p->next = q->next;//把q所指的结点从L中删除
                                                InsertAscend(T,q->data);//吧元素插入L
                                                free(q);//删除q
                                        }
                                }
                          break;
                  case 8:
                          printf("请输入待查找记录的学号:");
                                scanf("%ld",&num);
                                if(!FindFromNum(T,num,p,q))
                                   printf("没有学号为%ld的记录\n",num);
                                else
                                  Print(q->data);
                          break;
                  case 9:
                          printf("请输入待查找记录的姓名:");
                                scanf("%s",name);
                                if(!FindFromName(T,name,p,q))
                                   printf("没有姓名为%s的记录\n",name);
                                else
                                  Print(q->data);
                          break;
                  case 10:
                          printf("   姓名       学号 性别 年龄 班级 健康状况\n");
                          ListTraverse(T,Print);
                          break;
                  case 11:
                          printf("请输入文件名:");
                                scanf("%s",filename);
                                if((fp = fopen(filename,"rb")) == NULL)
                                   printf("打开文件失败!\n");
                                else
                                   ListTraverse(T,WriteToFile);
                                fclose(fp);
                          break;

                  case 12:
                          flag = 0;
                          break;           
                }
        }
}

x072816 发表于 2015-6-15 22:13:57

上面程序我是用devc++调试过,调试的时候没有问题,但是直接运行就出现了刚才的问题

小学期 发表于 2015-6-17 18:01:46

怎么我用cfree运行了一下,好像没问题的样子。
页: [1]
查看完整版本: 单链表插入问题