| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1051 人关注过本帖
标题:一个链表程序,不知道为什么不行
只看楼主 加入收藏
davidguhao
Rank: 1
来 自:广东
等 级:新手上路
帖 子:126
专家分:7
注 册:2016-7-18
结帖率:89.47%
收藏
已结贴  问题点数:20 回复次数:5 
一个链表程序,不知道为什么不行
程序代码:
#include <stdlib.h>
#include <stdio.h>

#ifndef NULL
#define NULL 0
#endif

struct list
{
    char *ch;
    struct list *next_rec;
};

typedef struct list LIST;
typedef LIST *LISTPTR;

LISTPTR add_to_list(char *, LISTPTR);
void show_list(LISTPTR);
void free_memory_list(LISTPTR);

LISTPTR first = NULL;

int main(void)
{

    int i = 0;
    char *ch;
    
    ch = (char *)malloc(40);

    while(i++ < 5)
    {
        printf("\nEnter name %d,", i);

        do
        {
            printf("\nPlease enter a name(<=40):  ");
            gets(ch);
        }while( (*ch < 'a' || *ch > 'z') && ( *ch < 'A' || *ch > 'Z') );

        add_to_list(ch, first);
    }
    show_list(first);
    free_memory_list(first);
    return 0;
}

LISTPTR add_to_list( char *ch, LISTPTR first)
{
    LISTPTR new_rec = NULL;
    LISTPTR tmp_rec = NULL;
    LISTPTR prev_rec = NULL;

    if((new_rec = (LISTPTR)malloc(sizeof(LIST)) ) == NULL)
    {
        fprintf(stderr, "\nUnable to allocate memory!\n");
        exit(1);
    }

    new_rec->ch = ch;
    new_rec->next_rec = NULL;

    if(first == NULL)
    {
        first = new_rec;
        new_rec->next_rec = NULL;
    }
    else
    {
        if(strcmp(new_rec -> ch, first -> ch) < 0)
        {
            new_rec -> next_rec = first;
            first = new_rec;
        }
        else
        {
            while ( tmp_rec -> next_rec != NULL)
            {
                if( strcmp(new_rec->ch, tmp_rec->ch) < 0)
                {
                    new_rec->next_rec = tmp_rec;
                    if(new_rec->next_rec != prev_rec->next_rec)
                    {
                        fprintf(stderr, "ERROR");
                        getc(stdin);
                        exit(1);
                    }
                    prev_rec->next_rec = new_rec;
                    break;
                }
                else
                {
                    tmp_rec = first -> next_rec;
                    prev_rec = prev_rec->next_rec;
                }
            }

            if(tmp_rec->next_rec == NULL)
            {
                if(strcmp(new_rec->ch, tmp_rec->ch) < 0)
                {
                    new_rec->next_rec = tmp_rec;
                    prev_rec->next_rec = new_rec;
                }
                else
                {
                    tmp_rec = tmp_rec -> next_rec;
                    prev_rec = prev_rec -> next_rec;
                }
            }
        }
    }
    return(first);
}

void show_list(LISTPTR first)
{
    LISTPTR cur_ptr;
    int counter = 1;

    printf("\n\nRec addr    Position    Data    Next Rec addr\n");
    printf("========================================\n");

    cur_ptr = first;
    while(cur_ptr != NULL)
    {
        printf("    %p    ", cur_ptr);
        printf("    %2i    %s", counter++, cur_ptr->ch);
        printf("    %p    \n", cur_ptr->next_rec);
        cur_ptr = cur_ptr->next_rec;
    }
}

void free_memory_list(LISTPTR first)
{
    LISTPTR cur_ptr, next_rec;
    cur_ptr = first;

    while(cur_ptr != NULL)
    {
        next_rec = cur_ptr->next_rec;
        free(cur_ptr);
        cur_ptr = next_rec;
    }
}


以上是我写的程序, 不知道为什么出错
搜索更多相关主题的帖子: 链表程序 
2016-08-28 10:49
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1744
专家分:3216
注 册:2015-12-2
收藏
得分:0 
改了一点,能输出,但只能输出最后一个
你的添加程序有很大问题,只能返回最后一项的指针
LISTPTR ft;
         ft=add_to_list(ch, first);
     }
     show_list(ft);
     free_memory_list(ft);
2016-08-28 12:23
linlulu001
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:20
帖 子:944
专家分:4047
注 册:2016-4-13
收藏
得分:7 
while( (*ch < 'a' || *ch > 'z') && ( *ch < 'A' || *ch > 'Z') );//只要求第一个字符字母那到没什么,如果不是也要改改。
add_to_list(ch, first);//这个子函数是带返回值的。虽然说first是全局变量,但是它的值就没变过,不知道你有没有注意到这一点
   
LISTPTR add_to_list( char *ch, LISTPTR first)
{
    LISTPTR new_rec = NULL;        
    LISTPTR tmp_rec = NULL;
    LISTPTR prev_rec = NULL;        //以上三个变量都是每调用一次函数都初始化NULL,而后面的代码没有考虑到这点。所以就会出错

排序那部分肯定是有错,具体怎么改你在试吧,改不出来再说。
2016-08-28 13:35
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1744
专家分:3216
注 册:2015-12-2
收藏
得分:0 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct list
 {
     char ch[40];
     struct list *next_rec;
 };

typedef struct list LIST;
typedef LIST *LISTPTR;

 LISTPTR add_to_list(char *, LISTPTR);
void show_list(LISTPTR);
void free_memory_list(LISTPTR);

 LISTPTR first = NULL;

int main(void)
 {

     int i = 0;
     char ch[40];
     

     while(i++ < 5)
     {
         printf("\nEnter name %d,", i);


             printf("\nPlease enter a name(<=40):  ");
             gets(ch);
         first=add_to_list(ch, first);
         
        ch[0]='\0';
     }
     show_list(first);
     free_memory_list(first);
     return 0;
 }

 LISTPTR add_to_list( char *ch, LISTPTR first)
 {
     LISTPTR new_rec = NULL;
     LISTPTR tmp_rec = NULL;
     LISTPTR prev_rec = NULL;

     if((new_rec = (LISTPTR)malloc(sizeof(LIST)) ) == NULL)
     {
         fprintf(stderr, "\nUnable to allocate memory!\n");
         exit(1);
     }
     
     strcpy(new_rec->ch,ch);
     new_rec->next_rec = NULL;

     if(first == NULL)
     {
         first = new_rec;
         new_rec->next_rec = NULL;
         
     }
     else
     {
         
         if(strcmp(new_rec -> ch, first -> ch) <= 0)
         {
             new_rec -> next_rec = first;
             first = new_rec;
            
         }
         else
         {   
              
             for(tmp_rec=first;tmp_rec!=NULL;tmp_rec=tmp_rec->next_rec)
             if(strcmp(tmp_rec->ch,new_rec->ch)>0)
             break;
            
             if(tmp_rec!=NULL&&first->next_rec!=NULL)
             {
            
             for(prev_rec=first;prev_rec->next_rec!=tmp_rec;prev_rec=prev_rec->next_rec);
                  
                  prev_rec->next_rec=new_rec;
                 
                 new_rec->next_rec=tmp_rec;
                 
             }
             else if(tmp_rec==NULL)
             {  
                  for(tmp_rec=first;tmp_rec->next_rec!=NULL;tmp_rec=tmp_rec->next_rec);
                 tmp_rec->next_rec=new_rec;
             }

         }
     }
     return(first);
 }

void show_list(LISTPTR first)
 {
     LISTPTR cur_ptr;
     int counter = 1;

     printf("\n\nRec addr    Position    Data    Next Rec addr\n");
     printf("========================================\n");

     cur_ptr = first;
     while(cur_ptr != NULL)
     {
         printf("    %p    ", cur_ptr);
         printf("    %2i    %s", counter++, cur_ptr->ch);
         printf("    %p    \n", cur_ptr->next_rec);
         cur_ptr = cur_ptr->next_rec;
     }
 }

void free_memory_list(LISTPTR first)
 {
     LISTPTR cur_ptr, next_rec;
     cur_ptr = first;

     while(cur_ptr != NULL)
     {
         next_rec = cur_ptr->next_rec;
         free(cur_ptr);
         cur_ptr = next_rec;
     }
 }
2016-08-28 15:52
书生牛犊
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:星夜征程
等 级:贵宾
威 望:10
帖 子:1101
专家分:5265
注 册:2015-10-27
收藏
得分:7 
关于全局变量的使用,应当谨慎!我们的目标是尽量少用。就算要用,通常也会搞得特别长,做个明显的复杂的标记,避免在各个模块函数中重名,起冲突。

目前看来,你声明的全局变量first并不会有助于任何的代码,反而容易不小心制造bug。。。我也找不到你这里面有什么语法上的错误了,如果你的某租测试过不了,到时可以一起贴上来看看
程序代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct list {
    char ch[40];
    struct list *next_rec;
};

typedef struct list LIST;
typedef LIST *LISTPTR;

LISTPTR add_to_list(char *, LISTPTR);
LISTPTR add_to_list2(char *, LISTPTR);
void show_list(LISTPTR);
void free_memory_list(LISTPTR);

LISTPTR first = NULL;//原则上还是尽量减少这种全局变量的使用。尤其是不应该出现局部变量和全局变量重名,我推荐你把它放到main()里面去


int main(void) {

    int i = 0;
    char ch[40];
    while(i++ < 5) {
        printf("\nEnter name %d,", i);
        printf("\nPlease enter a name(<=40):  ");
        gets(ch);
        first=add_to_list(ch, first);

        ch[0]='\0';
    }
    show_list(first);
    free_memory_list(first);
    return 0;
}

LISTPTR add_to_list( char *ch, LISTPTR first) {//这是个不好的习惯,first原来是一个全局变量,你在这里又声明了同名变量,在这个函数内,全局变量first不起作用了。
    LISTPTR new_rec = NULL;
    LISTPTR tmp_rec = NULL;
    LISTPTR prev_rec = NULL;

    if((new_rec = (LISTPTR)malloc(sizeof(LIST)) ) == NULL) {
        fprintf(stderr, "\nUnable to allocate memory!\n");
        exit(1);
    }

    strcpy(new_rec->ch,ch);
    new_rec->next_rec = NULL;

    if(first == NULL) {
        first = new_rec;//这里我猜你是要给外面的全局变量first 赋值吧。sorry,你赋值的是函数内部的这个临时变量
        new_rec->next_rec = NULL;//这句貌似没什么作用,new_rec->next_rec本来就是NULL啊

    } else {//z这一块代码其实完全可以递归实现

        if(strcmp(new_rec -> ch, first -> ch) <= 0) {
            new_rec -> next_rec = first;
            first = new_rec;

        } else {
            /*  */
            for(tmp_rec=first; tmp_rec!=NULL; tmp_rec=tmp_rec->next_rec)
                if(strcmp(tmp_rec->ch,new_rec->ch)>0)
                    break;

            if(tmp_rec!=NULL&&first->next_rec!=NULL) {

                for(prev_rec=first; prev_rec->next_rec!=tmp_rec; prev_rec=prev_rec->next_rec);

                prev_rec->next_rec=new_rec;

                new_rec->next_rec=tmp_rec;

            } else if(tmp_rec==NULL) {
                for(tmp_rec=first; tmp_rec->next_rec!=NULL; tmp_rec=tmp_rec->next_rec);
                tmp_rec->next_rec=new_rec;
            }

        }
    }
    return(first);//不过你又把这里面造的first传递到外面去了,所以你又成功令外面的first接收到了正确的信息。

}
LISTPTR add_to_list2(char*ch,LISTPTR h) {//学习使用递归函数可以让代码量减少,思路更直观

    if(h==NULL||strcmp(ch,h->ch)) {
        LISTPTR temp=(LISTPTR)malloc(sizeof(LIST));
        if(!temp) {
            fprintf(stderr, "\nUnable to allocate memory!\n");
            exit(1);
        }
        strcpy(temp->ch,ch);
        temp->next_rec = h;
        return temp;
    } else {
        h->next_rec=add_to_list2(ch,h->next_rec);//递归调用下一层函数 ,可以理解为当前位置不适合插入ch,继续向后查找。
        return h;
    }
}
void show_list(LISTPTR first) {//类似的这里的first变量也和全局变量冲突到了,不过因为这里的局部变量挡住了外面的全局变量,所以目前还没有导致什么错误

    LISTPTR cur_ptr;
    int counter = 1;

    printf("\n\nRec addr    Position    Data    Next Rec addr\n");
    printf("========================================\n");

    cur_ptr = first;
    while(cur_ptr != NULL) {
        printf("    %p    ", cur_ptr);
        printf("    %2i    %s", counter++, cur_ptr->ch);
        printf("    %p    \n", cur_ptr->next_rec);
        cur_ptr = cur_ptr->next_rec;
    }
}

void free_memory_list(LISTPTR first) {//形同show_list(),有风险,但恰巧没错。

    LISTPTR cur_ptr, next_rec;
    cur_ptr = first;

    while(cur_ptr != NULL) {
        next_rec = cur_ptr->next_rec;
        free(cur_ptr);
        cur_ptr = next_rec;
    }
}






φ(゜▽゜*)♪
2016-08-28 19:05
davidguhao
Rank: 1
来 自:广东
等 级:新手上路
帖 子:126
专家分:7
注 册:2016-7-18
收藏
得分:0 
回复 5楼 书生牛犊
我记得……它是可以编译通过的……只是在运行过程中输入第二个值时会出现程序崩溃……就类似用scanf没有用取址运算符一样退出来……

暨南大学市场营销……
但是我有一颗计算机专业的心……
2016-09-02 11:05
快速回复:一个链表程序,不知道为什么不行
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017195 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved