- 浏览: 454401 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
前言
上一篇《C和指针》可能对关于C和指针的有些内容没有说透,下来写了一个链表的实现,当然,也是用C的函数指针来模拟OO的结构来做的。链表结构本身比较复杂(关于指针的使用方面),所以这个例子可能更清晰一些。之所以选List这个例子来说,是因为大家在学校里肯定接触过这个简单数据结构,从一个比较熟悉的例子入手可能比较容易理解一些。
接口定义
可以先看看接口的定义,与Java或者C#类似:
* File: IList.h
* Author: juntao.qiu
*
* Created on May 22, 2009, 2:51 PM
*/
#ifndef _ILIST_H
#define _ILIST_H
typedef struct node{
void *data;
struct node *next;
}Node; //定义List中的元素类型,void * 相当于C中的泛型,可以支持任何结构的节点
typedef struct list{
struct list *_this;
Node *head;
int size;
void (*insert)(void *node);
void (*drop)(void *node);
void (*clear)();
int (*getSize)();
void* (*get)(int index);
void (*print)();
}List; //用head (Node)来维护链表的链!
void insert(void *node);
void drop(void *node);
void clear();
int getSize();
void* get(int index);
void print();
#endif /* _ILIST_H */
接口中定义所有的公开的方法,正如所有的List结构一样,我们定义了
void drop(node);//删除一个指定的节点
void clear();//清空List
int getSize();//取到List的大小
void* get(int index);//取到指定位置的元素
void print();//打印整个List,用于调试
这样几个方法。
接口的实现
然后看看实现,同上篇一样,引入一个标记链表自身的_this指针,通过对这个指针的引用来修改真实对象中的状态。
#include <stdlib.h>
#include "IList.h"
Node *node = NULL;
List *list = NULL;
/* 函数声明块,作用已经在上边解释了*/
void insert(void *node);
void drop(void *node);
void clear();
int getSize();
void print();
void* get(int index);
/* 构造方法 */
List *ListConstruction(){
list = (List*)malloc(sizeof(List));
node = (Node*)malloc(sizeof(Node));
list->head = node;
list->insert = insert;
list->drop = drop;
list->clear = clear;
list->size = 0;
list->getSize = getSize;
list->get = get;
list->print = print;
list->_this = list;
return (List*)list;
}
void ListDeconstruction(){
}
//插入节点,size增加1
void insert(void *node){
Node *current = (Node*)malloc(sizeof(Node));
current->data = node;
current->next = list->_this->head->next;
list->_this->head->next = current;
(list->_this->size)++;
}
//删除一个节点,size减1
void drop(void *node){
Node *t = list->_this->head;
Node *d = NULL;
int i = 0;
for(i;i < list->_this->size;i++){
d = list->_this->head->next;
if(d->data == ((Node*)node)->data){
list->_this->head->next = d->next;
free(d);
(list->_this->size)--;
break;
}else{
list->_this->head = list->_this->head->next;
}
}
list->_this->head = t;
}
//取到指定index的节点
void* get(int index){
Node *node = list->_this->head;
int i = 0;
if(index > list->_this->size){
return NULL;
}else{
for(i;i < index;i++){
node = node->next;
}
if(node != (Node*)0){
return node->data;
}else{
return NULL;
}
}
}
void clear(){
Node *node = NULL;
int i = 0;
for(i;i< list->_this->size;i++){
node = list->_this->head;
list->_this->head = list->_this->head->next;
free(node);
}
list->_this->size = 0;
list = NULL;
}
int getSize(){
return list->_this->size;
}
//调试用,像这种getSize(), print()这种调用,需要注意的是在调用过程中不能对原始指针做任何修改,
//否则可能出现无法预测的错误。
void print(){
Node *node = list->_this->head;
int i = 0;
for(i;i <= list->_this->size;i++){
if(node != (Node*)0){
printf("[%p] = {%s}\n",&node->data, node->data);
node = node->next;
}
}
}
测试
/*
* File: Main.c
* Author: juntao.qiu
*
* Created on May 21, 2009, 4:05 PM
*/
#include <stdio.h>
#include <stdlib.h>
s#include "IList.h"
int main(int argc, char** argv) {
List *list = (List*)ListConstruction();//构造一个新的list
list->insert("Apple");
list->insert("Borland");
list->insert("Cisco");
list->insert("Dell");
list->insert("Electrolux");
list->insert("FireFox");
list->insert("Google");//插入一些节点
list->print();//查看是否插入正确
printf("list size = %d\n",list->getSize());
//删除两个节点,并打印结果查看。
Node node;
node.data = "Electrolux";
node.next = NULL;
list->drop(&node);
node.data = "Cisco";
node.next = NULL;
list->drop(&node);
list->print();
printf("list size = %d\n",list->getSize());
list->clear();
return 0;
}
运行结果
$./ooc
[00489760] = {Google}
[00489730] = {FireFox}
[00489700] = {Electrolux}
[004896D0] = {Dell}
[004896A0] = {Cisco}
[00489670] = {Borland}
[00489640] = {Apple}
list size = 7
[00489760] = {Google}
[00489730] = {FireFox}
[004896D0] = {Dell}
[00489670] = {Borland}
[00489640] = {Apple}
list size = 5
[00489760] = {Google}
[00489730] = {FireFox}
[00489700] = {Electrolux}
[004896D0] = {Dell}
[004896A0] = {Cisco}
[00489670] = {Borland}
[00489640] = {Apple}
list size = 7
[00489760] = {Google}
[00489730] = {FireFox}
[004896D0] = {Dell}
[00489670] = {Borland}
[00489640] = {Apple}
list size = 5
可以看出,程序正如预期的那样运行(前一项为节点在内存中的地址,后一项为节点的值),如果大家有兴趣,可以将上一篇《C和指针》s中的Executor装入一个List实现一个Executor的管理器,加入get方法,同时考虑多线程的状态,即可自己完成一个线程池的实现。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2385第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6494基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4312前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 2017前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1291前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1135前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
有限自动机与建模
2009-06-06 10:48 1830前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1456前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1371前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3817第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3681接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2930第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3930第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 4083第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4601第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2149前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 5113第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6181第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5744第二章 基本概念 ... -
JavaScript内核系列 第1章 前言及概述
2010-04-01 23:15 9980前言 从2006年第一次接触JavaScript至今,算来也 ...
相关推荐
`ftell`获取文件当前的读写位置,`fseek`可以将文件指针移动到指定位置,这在断点续传中非常重要。 5. **状态保存**:在开始传输前,需要检查本地是否已有部分文件,如果是,则读取该文件的大小作为续传的起点。这...
在断点续传中,需要使用`ftell()`获取文件当前位置,`fseek()`设置文件指针位置。 5. **错误处理**:在网络通信中,必须处理各种可能的错误,如网络中断、文件不存在、权限问题等。通过`errno`全局变量和`perror()`...
在这篇文章中,我们将讨论 FTP 断点续传的实现,包括 FTP 协议的基本原理、断点续传的实现方法和 FTP 命令的使用。 FTP 协议的基本原理 FTP 协议是一个基于 TCP 的客户服务器架构的协议。FTP 服务器进程可以同时为...
例如,我们在C语言编写的程序完成后,通常会将其保存为一个具有`.c`扩展名的文件。随后,通过编译器编译成机器可以执行的程序文件,通常具有`.exe`扩展名。 根据文件的内容和功能,我们可以将文件分为程序文件和...
而非缓冲文件系统则需要程序员手动管理缓冲区,这在现代C语言编程中很少使用,因为ANSI C标准已经推荐使用缓冲文件系统来处理所有类型的文件,包括文本文件和二进制文件。 在C语言中,文件操作以流的形式进行,这是...
C语言中国象棋程序设计...该程序展示了C语言编程的多个方面,包括数组、指针、宏、常量、游戏状态机、棋盘表示、棋子表示、游戏逻辑、界面设计、游戏状态保存和加载、键盘输入和事件处理、错误处理、代码组织和结构等。
描述与标签:“C编程语言”涵盖了计算机科学中的一种核心编程语言,以其高效、灵活和广泛的应用范围而闻名。C语言自1972年由Dennis Ritchie在贝尔实验室开发以来,成为了现代编程语言的基石,影响了如C++、Java等...
熟练掌握C语言的基本知识,具备基本的C程序设计能力,能熟练地阅读、理解和编制简短的C程序。 基本内容 ### 数据的定义 * 数据类型和存储类别 + 基本类型:整型、实型、字符型(主要是int, float, double, char...
C语言的运算符种类多样,包括算术、关系、逻辑、位和指针运算,这使得处理各种计算和逻辑判断变得简单。 C程序的基本结构是基于函数的。一个C程序可以包含一个或多个函数,每个函数由函数说明和函数体组成。函数...
C1-简介 C2-运算符、表达式 C3-运算符、表达式(续) C4-基本语句、顺序结构 C5-选择结构 C6-循环结构 C7-循环结构(续) C8-数组 C9-字符数组 C10-结构体 ...C12-函数(续1) C13-函数(续2) C14-指针 C15-指针(续)
此外,遵循一定的规范和最佳实践,如MISRA-C规范,可以有效避免潜在的安全隐患,提高系统的稳定性和可靠性。最后,合理的性能优化措施能够充分利用有限的硬件资源,达到更好的运行效果。总之,良好的编程习惯是每一...
6. 数组和指针的关系(续) 在问题(6)中,我们可以看到数组和指针的关系。在数组的指针加 1 时,系统会认为加一个数组的偏移,而不是简单地加 1。因此,指针的计算需要根据指针类型和数组的大小。 7. 内存分配...
源码中会包含C语言的基本结构,如变量声明、函数定义、控制流语句(if-else、for、while)、数据类型(int、char、float等)和指针操作。学习者可以通过源码理解C语言如何用于实现复杂的系统功能。 在飞鸽传书的...
选项B不准确,C语言允许定义空类型指针;选项C不准确,枚举类型是C语言中的基本类型之一;选项D不准确,数组属于构造类型。 #### 50104 题目解析:main()函数的位置 **题目**: main()函数的位置(B)。 - A.必须在...
本资源包含了一组C语言实现的数据结构练习题,旨在帮助学生巩固和提升对数据结构的理解,为学校的考试做好准备。 在数据结构的学习中,我们通常会接触到以下关键概念: 1. **数组**:是最基本的数据结构,用于存储...
该酒店管理系统利用C语言的基本控制结构和数据类型实现了酒店预订的主要业务功能。尽管没有使用指针、数组或文件读写等更高级的功能,但通过对基本数据结构的巧妙运用,仍能较好地满足需求。通过本系统的开发,不仅...
8. **内存管理**:C语言提供动态内存分配函数`malloc`、`calloc`、`realloc`和`free`,理解内存管理的原理和最佳实践,避免内存泄漏和悬挂指针。 9. **权限和文件系统**:了解Linux的用户和组概念,以及如何使用`...
本项目聚焦于如何使用纯C语言来实现对C8051F单片机的在线程序更新,这是一项重要的技术,它允许在不拆卸设备的情况下更新固件,提高了系统的可维护性和灵活性。 在线程序更新(OTA,Over-the-Air Update)的核心...
- `const`用于声明常量,可以修饰基本类型、指针、函数参数和返回值,以及类成员。修饰指针时,可以表示指针本身是常量(不能改变指针地址),或指针所指的对象是常量(不能通过指针修改对象的值)。 9. `const`的...