文档章节

Head First C学习日志 第六章用堆进行动态存储

AlexTuan
 AlexTuan
发布于 2016/02/21 22:27
字数 1059
阅读 68
收藏 3

书中的例子是,在多座岛屿间规划航线,并记录,将岛屿作为节点,数据结构如下

typedef struct island {
    char *name;
    char *opens;
    char *closes;
    struct island *next;
} island;

注意,递归结构(含有指向相同类型的指针)不能为匿名结构,结构中相同类型的指针,在c语法中不允许通过别名来声明它。

创建create,display,release函数

create:

island *create(char *name) {
    island *i = malloc(sizeof(island));
    i->name = strdup(name);
    i->opens = "09:00";
    i->closes = "17:00";
    i->next = NULL;
    return i;
}

分配sizeof(island)大小的堆内存,并将地址给i,malloc的返回值是void*类型,可以充当任何类型指针赋值操作的右值,但是有的编译器可能会警告。

给成员赋值:i->name=strdup(name);strdup的含义是在内存中拷贝name,并返回地址,返回值类型为char* ,之所以这么做,是因为name只是用做接收输入的字符串,在内存中的位置固定,且内容会不断更新,如果直接使用name,那么就会有多个节点(i->name)指向同一个地址,结果就是,多个岛屿的名字都是最后一次输入的那个。

i->next=NULL;由于创建岛屿时不知道航线的下一个目的地是哪,所以逻辑上要置空,还有一个原因就是,如果不把指针置为NULL,那么指向的内存位置是不确定的,容易导致意想不到的问题。

display:

void display(island *start) {
    island *i = start;
    for (; i != NULL; i = i->next)
        printf("Name:%s\n open:%s-%s\n", i->name, i->opens, i->closes);
}

将链表(航线)的起始指针传入,使用一个island类型的指针进行遍历,这个指针充当的是游标/迭代器。

release:释放内存

void release(island *start) {
    island *i = start;
    island *next = NULL;
    for (; i != NULL; i = next) {
        next = i->next;
        free(i->name);
        free(i);
    }
    printf("finish releasing.\n");
}

使用两个island类型指针从起始位置开始进行顺序释放。逻辑步骤:将i指向起始位置,如果i指向的位置的next不为空,next指向起始节点的下一个节点,释放i,将i指向next指向的位置,然后循环。

free()接收一个void*指针,返回值类型为void,注意一点:free(i)之前,要先把i->name释放掉,还记得吗,我们用strdup拷贝的name,如果直接free(i),那么拷贝的这个name的那部分内存,就再也访问不到了,没有人知道他的地址,造成内存泄漏,free函数并没有那么智能,所以我们要手动的将这部分内存释放掉,然后再free(i)。

main函数:

int main() {
    printf("Game on\n");
    island *start = NULL;
    //i as a iterator
    island *i = NULL;
    island *node = NULL;
    char name[80];
    for (; fgets(name, 80, stdin); i = node) {
        if (name[strlen(name) - 1] == '\n')
            name[strlen(name) - 1] = 0;
        //node leads to a piece of storage which contains the new island,the 'node' pointer changes every time you create a new island.
        node = create(name);
        if (start == NULL) {
            start = node;
        }
        if (i != NULL) {
            i->next = node;
        }
    }
    display(start);
    release(start);
    return 0;
}

创建3个island指针,start代表该链表(航线)的起始位置,i作为迭代器将多个节点串联起来,node是新创建的island,每次创建都会更新node的地址,链表中每个节点只是一段内存(连续或不连续),并没有实际的名称。

逻辑步骤:接收一个island名,创建island,用node指针标记这一新建节点,如果当前start为空,将start赋值为node,如果i不为空,将i->next指向node,最后i=node,将i指向新创建的节点(为连接下一个节点做准备),循环这一步骤。完成这一系列操作后,node,i,i->next似乎都指向同一块内存。

单链表的创建在逻辑上绝对不会有太大出入,一个递归结构作为节点,循环创建节点,用一个临时指针串联所有节点,只start起始指针标记这一链表

代码已上传到github:https://github.com/AlexTuan1024/egsonhfc.git

© 著作权归作者所有

AlexTuan
粉丝 4
博文 27
码字总数 17966
作品 0
程序员
私信 提问
从零开始UNIX环境高级编程(7):进程环境

0. 引言 在学习进程控制前,先了解进程运行的环境,如:main函数是如何被调用的;命令行参数是如何传递给新程序的;程序在内存空间中是什么样的结构;进程的终止方式等。 1. main函数 1.1 程...

伤口不该结疤
2017/04/24
0
0
《深入理解 Java 虚拟机 》学习笔记

原文出处:c-rainstorm 第二章 Java 内存区域与内存溢出异常 内存区域 – from 姜志明 对象创建 加载类 若已经在内存中则跳过。 类加载完以后就可以确定对象所需的空间大小 // TODO why? 分配...

c-rainstorm
2018/12/08
0
0
Head First C学习日志 第六章 最高机密 二叉树和valgrind工具

程序会从根节点开始提问,其左右子树为疑犯名字或另外一个问题。先看数据结构: typedef struct node {char *question;struct node *no;struct node *yes;} node; 一个递归结构,内容很简单,...

AlexTuan
2016/02/23
59
0
转行程序员?你可能忽略了一件事。

     程序 = 数据结构 + 算法   ——图灵奖得主,计算机科学家N.Wirth(沃斯)      作为程序员,我们做机器学习也好,做python开发也好,java开发也好。   有一种对所有程序员无一...

java进阶架构师
2018/10/25
0
0
《java数据结构和算法》读书笔记

《Java多线程编程核心技术》读书笔记 常用数据结构 第2章 数组 最简单的数据结构,在查找上比链表有优势,但是在插入与删除上比不上链表。 Java中的数组有长度限制,为int值。在内存模型中,...

刀狂剑痴
2016/05/27
248
0

没有更多内容

加载失败,请刷新页面

加载更多

c++ 虚基类

c++ 虚基类 p556

天王盖地虎626
13分钟前
10
0
Java中的面向对象

一、面向对象 面向对象和面向过程的区别 过程就是函数,就是写方法,就是方法的一种实现。 对象就是将函数,属性的一种封装。用人们思考习惯的方式思考问题。 如何自定义类 修饰符 类名{ //成...

zhiruochujian
21分钟前
3
0
k8s删除Terminating状态的命名空间

背景: 我们都知道在k8s中namespace有两种常见的状态,即Active和Terminating状态,其中后者一般会比较少见,只有当对应的命名空间下还存在运行的资源,但是该命名空间被删除时才会出现所谓的...

Andy-xu
24分钟前
15
0
seata源码阅读笔记

seata源码阅读笔记 本文没有seata的使用方法,怎么使用seata可以参考官方示例,详细的很。 本文基于v0.8.0版本,本文没贴代码。 seata中的三个重要部分: TC:事务协调器,维护全局事务和分支...

东都大狼狗
37分钟前
5
0
Rust:最小化窗口后 CPU占用率高 (winit,glutin,imgui-rust)

最近试着用 imgui-rust 绘制界面,发现窗口最小化后CPU占用会增大。 查询的资料如下: https://github.com/rust-windowing/winit/issues/783 https://github.com/ocornut/imgui/issues/1151 ...

reter
41分钟前
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部