0

问题解决了。一个人在评论中给出了它。问题是我%d用来阅读short int. 我应该使用%hd或者我应该使用'int'。


我试图创建一个仅使用局部变量的单链表程序。我能够通过使用全局变量来制作一个工作程序。

带有局部变量的程序可以编译,但是当我尝试遍历链表时它会崩溃。

我完全不知道局部变量的实现有什么问题。局部变量的实现中存在什么问题?

关于程序的结构:

我知道程序很大,所以我会介绍一下程序的结构。

  • 该程序结构为菜单驱动程序。所以对函数的初始调用是在 main() 函数中
  • main() 菜单中有 3 个选项 - 退出、遍历和插入
  • Exit 返回 0 退出程序,而其他 2 执行函数调用

  • 插入功能本身被安排为菜单驱动程序。

  • 它有 3 个选项 - return 、 insert_begin 和 insert_end。最后两个是函数调用。

  • 我知道存在内存泄漏,因为我没有释放任何内存,但在我了解当前程序中的问题后,我会处理这个问题。

//使用全局变量的工作实现

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

#define MIN 0
#define MAX 2

#define INS_MIN 0
#define INS_MAX 2

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

sll_node *start = NULL;

void intro()
{
    system("cls");
    printf("\n\tThese are the various options:\n");
    printf("\n\t00 Exit");
    printf("\n\t01 Traverse the list");
    printf("\n\t02 Insertion into the list");
}

void insert_begin()
{
    sll_node *node = malloc(sizeof(sll_node));
    if(node == NULL)
    {
        printf("\n\tNot enough menory");
        exit(-1);
    }
    int data;
    printf("\n\tData to be entered: ");
    scanf("%d", &data);

    node->data = data;
    node-> next = start;
    start = node;
}

void insert_end()
{
    sll_node *node = malloc(sizeof(sll_node));
    if(node == NULL)
    {
        printf("\n\tNot enough menory");
        exit(-2);
    }

    if(start == NULL)
        insert_begin();
    else
    {
        printf("\n\tData to be entered: ");
        scanf("%d", &(node->data));
        node-> next = NULL;

        sll_node *node2;
        for(node2 = start; node2->next != NULL; node2 = node2->next)
            ;
        node2->next = node;
    }
}

void insert_intro()
{
    system("cls");
    printf("\n\tThese are the various options:\n");
    printf("\n\t00 Insertion Done");
    printf("\n\t01 Insert at beginning");
    printf("\n\t02 Insert at end");
}

void insertion()
{
    short choice;
    while(1)
    {
        choice = -1;
        while(choice < INS_MIN || choice > INS_MAX)
        {
            insert_intro();
            printf("\n\n\tEnter your chocie: ");
            scanf("%d", &choice);
        }

        switch(choice)
        {
        case 0:
            return;
        case 1:
            insert_begin();
            break;
        case 2:
            insert_end();
            break;
        }
    }
}

void traverse()
{
    if(start == NULL)
        printf("\n\n\tLinked list is empty");
    else
    {
        printf("\n\n\t");
        for(sll_node *node = start; node != NULL; node = node->next)
            printf("%d ", node->data);
    }
    getch();
}

int main()
{
    short choice;
    while(1)
    {
        choice = -1;
        while(choice < MIN || choice > MAX)
        {
            intro();
            printf("\n\n\tEnter your choice: ");
            scanf("%d", &choice);
        }

        switch(choice)
        {
        case 0:
            return 0;
        case 1:
            traverse();
            break;
        case 2:
            insertion();
            break;
        }
    }
    return 0;
}

//编译但崩溃 - 相同的程序,但具有局部变量启动和函数之间的变量传递

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

#define MIN 0
#define MAX 2

#define INS_MIN 0
#define INS_MAX 2

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

void intro()
{
    system("cls");
    printf("\n\tThese are the various options:\n");
    printf("\n\t00 Exit");
    printf("\n\t01 Traverse the list");
    printf("\n\t02 Insertion into the list");
}

sll_node* insert_begin(sll_node *start)
{
    sll_node *node = malloc(sizeof(sll_node));
    if(node == NULL)
    {
        printf("\n\tNot enough menory");
        exit(-1);
    }
    int data;
    printf("\n\tData to be entered: ");
    scanf("%d", &data);

    node->data = data;
    node-> next = start;
    return node;
}

sll_node* insert_end(sll_node *start)
{
    sll_node *node = malloc(sizeof(sll_node));
    if(node == NULL)
    {
        printf("\n\tNot enough menory");
        exit(-2);
    }

    if(start == NULL)
        start = insert_begin(start);
    else
    {
        printf("\n\tData to be entered: ");
        scanf("%d", &(node->data));
        node-> next = NULL;

        sll_node *node2;
        for(node2 = start; node2->next != NULL; node2 = node2->next)
            ;
        node2->next = node;
    }
    return start;
}

void insert_intro()
{
    system("cls");
    printf("\n\tThese are the various options:\n");
    printf("\n\t00 Insertion Done");
    printf("\n\t01 Insert at beginning");
    printf("\n\t02 Insert at end");
}

sll_node* insertion(sll_node *start)
{
    short choice;
    while(1)
    {
        choice = -1;
        while(choice < INS_MIN || choice > INS_MAX)
        {
            insert_intro();
            printf("\n\n\tEnter your chocie: ");
            scanf("%d", &choice);
        }

        switch(choice)
        {
        case 0:
            return start;
        case 1:
            start = insert_begin(start);
            break;
        case 2:
            start = insert_end(start);
            break;
        }
    }
}

void traverse(sll_node *start)
{
    if(start == NULL)
        printf("\n\n\tLinked list is empty");
    else
    {
        printf("\n\n\t");
        for(sll_node *node = start; node != NULL; node = node->next)
            printf("%d ", node->data);
    }
    getch();
}

int main()
{
    sll_node *start = NULL;
    short choice;
    while(1)
    {
        choice = -1;
        while(choice < MIN || choice > MAX)
        {
            intro();
            printf("\n\n\tEnter your choice: ");
            scanf("%d", &choice);
        }

        switch(choice)
        {
        case 0:
            return 0;
        case 1:
            traverse(start);
            break;
        case 2:
            start = insertion(start);
            break;
        }
    }
    return 0;
}
4

5 回答 5

3

insertion()将项目添加到列表时,您不会从函数返回任何内容。所以链表可能无法正确构建。

start可能,只有在开头添加它时才应该返回,否则startinmain()将不会指向列表的头部。

sll_node* insertion(sll_node *start)
{
        ...
        switch(choice)
        {
        case 0:
            return start;
        case 1:
            start = insert_begin(start);
            return start;  //<----- return node
            break;
        case 2:
            start = insert_end(start);
            break;
        }
    ...

}
于 2013-06-23T07:18:53.843 回答
2

更改short choiceint choice

为什么这会有所作为?

简短的回答是printf("%d")需要一个整数。

长答案是"%d"将您传递给的数据类型描述printf为整数(通常为 4 到 8 个字节),并且您给它的数据类型为short- 通常为 2 个字节长。当您的程序读取输入并将其存储在指针处时&choice,它会从该地址开始写入 4 个字节(但只保留了 2 个字节)。这会导致分段错误并使您的程序崩溃。

这是一些文档的列表。printf你会注意到将 a 传递shortprintf你会写%hd而不是%d

于 2013-06-23T08:04:38.807 回答
1

当我在计算机上编译您的代码时,它可以正常工作,但是我将“简短选择”更改为“ int Choice”,因为scanf(“%d”,&Choce因为 short 只有 2 个字节,因此会发生堆栈损坏,我在您的计算机上这种损坏会损坏“开始”指针。

于 2013-06-23T07:42:46.633 回答
0

关于坠机。将函数insert_begininsert_end中的参数start更改为sll_node ** start,并在分配新值时使用表达式*start = your-new-value。这是因为您必须将指针传递给也是指针的局部变量start。您不需要更改功能traverse

关于内存泄漏,让我指出,当您从 insert_end 内部调用insert_begin,从insert_end创建的节点未被使用。在exit()和 main() 中的return之前,您应该释放列表。

于 2013-06-23T07:47:22.873 回答
0

是的,对不起。还有一个很难看到的错误。它在您阅读的 2 行处(选择)。

    短期选择;
    ...
    // 将“%d”与(短选择)一起使用是错误的,因为堆栈将
    // 被意想不到的结果覆盖。格式说明符“%hd”
    // 告诉编译器 (&choice) 指向一个短的 16 位整数,
    // 不是 32 位的
    scanf("%hd", &choice);

这是稍微不同的版本,经过测试,没有内存泄漏。

//

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

    #定义最小值 0
    #define MAX 2
    #define INS_MIN 0
    #define INS_MAX 2

    typedef 结构节点
    {
        整数数据;
        结构节点*下一个;
    } sll_node;

    无效 clear_list(sll_node** 开始)
    {
        断言(开始!= NULL);
        sll_node* 节点 = *开始;
        而(节点!= NULL)
        {
            sll_node* 元素 = 节点;
            节点=元素->下一个;
            自由(元素);
        }
        *开始=空;
    }

    无效介绍()
    {
        系统(“cls”);
        printf("\n\t这些是各种选项:\n");
        printf("\n\t00 退出");
        printf("\n\t01 遍历列表");
        printf("\n\t02 插入列表");
    }

    无效插入开始(sll_node** pstart)
    {
        sll_node* 节点 = (sll_node*)malloc(sizeof(sll_node));
        如果(节点 == NULL)
        {
            printf("\n\t内存不够");
            清除列表(pstart);
            退出(-1);
        }
        整数数据;
        printf("\n\t要输入的数据:");
        scanf_s("%d", &data);//scanf
        节点->数据=数据;
        节点->下一个 = *pstart;
        // 更新从 main 传递的局部变量 start 指向刚刚插入的节点
        *pstart = 节点;
    }

    无效 insert_end(sll_node** 开始)
    {
        断言(开始!= NULL);
        if (*start == NULL)
        {
            插入开始(开始);
        }
        别的
        {
            sll_node* 节点 = (sll_node*)malloc(sizeof(sll_node));
            如果(节点 == NULL)
            {
                printf("\n\t内存不够");
                清除列表(开始);
                退出(-2);
            }
            printf("\n\t要输入的数据:");
            scanf("%d", &(node->data));
            节点->下一个 = NULL;
            sll_node* 节点2;
            for(node2 = *start; node2->next != NULL; node2 = node2->next)
                ;
            节点2->下一个=节点;
        }
    }

    无效插入介绍()
    {
        系统(“cls”);
        printf("\n\t这些是各种选项:\n");
        printf("\n\t00 插入完成");
        printf("\n\t01 在开头插入");
        printf("\n\t02 插入末尾");
    }

    无效插入(sll_node** 开始)
    {
        短期选择;
        而(1)
        {
            选择 = -1;
            而(选择 < INS_MIN || 选择 > INS_MAX)
            {
                插入介绍();
                printf("\n\n\t输入你的选择:");
                scanf("%hd", &choice);
            }
            开关(选择)
            {
            案例0:
                返回;
            情况1:
                插入开始(开始);
                休息;
            案例2:
                插入结束(开始);
                休息;
            }
        }
    }

    无效遍历(sll_node *开始)
    {
        如果(开始 == NULL)
            printf("\n\n\t链表为空");
        别的
        {
            printf("\n\n\t");
            for(sll_node *node = start; node != NULL; node = node->next)
                printf("%d", 节点->数据);
        }
        getch();
    }

    主函数()
    {
        sll_node *start = NULL;
        短期选择;
        而(1)
        {
            选择 = -1;
            而(选择 < MIN || 选择 > MAX)
            {
                介绍();
                printf("\n\n\t输入你的选择:");
                scanf("%hd", &choice);
            }
            开关(选择)
            {
            案例0:
                clear_list(&start);
                返回0;
            情况1:
                遍历(开始);
                休息;
            案例2:
                插入(&开始);
                休息;
            }
        }
        返回0;
    }

PS 很难编辑!我是新来的,没有足够的经验。浪费了很多时间编辑!

于 2013-06-23T10:04:35.197 回答