`
abruzzi
  • 浏览: 454401 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

C和指针(续)

阅读更多

前言

上一篇《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 insert(node);//插入一个新的节点到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 
*= list->_this->
head;
    Node 
*=
 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

 

可以看出,程序正如预期的那样运行(前一项为节点在内存中的地址,后一项为节点的值),如果大家有兴趣,可以将上一篇《C和指针》s中的Executor装入一个List实现一个Executor的管理器,加入get方法,同时考虑多线程的状态,即可自己完成一个线程池的实现。

 

分享到:
评论

相关推荐

    C语言实现ftp断点续传.rar.rar

    `ftell`获取文件当前的读写位置,`fseek`可以将文件指针移动到指定位置,这在断点续传中非常重要。 5. **状态保存**:在开始传输前,需要检查本地是否已有部分文件,如果是,则读取该文件的大小作为续传的起点。这...

    文件传输系统-C语言支持断点续传功能

    在断点续传中,需要使用`ftell()`获取文件当前位置,`fseek()`设置文件指针位置。 5. **错误处理**:在网络通信中,必须处理各种可能的错误,如网络中断、文件不存在、权限问题等。通过`errno`全局变量和`perror()`...

    ftp 断点续传实现

    在这篇文章中,我们将讨论 FTP 断点续传的实现,包括 FTP 协议的基本原理、断点续传的实现方法和 FTP 命令的使用。 FTP 协议的基本原理 FTP 协议是一个基于 TCP 的客户服务器架构的协议。FTP 服务器进程可以同时为...

    电脑基础知识c语言续PPT学习教案.pptx

    例如,我们在C语言编写的程序完成后,通常会将其保存为一个具有`.c`扩展名的文件。随后,通过编译器编译成机器可以执行的程序文件,通常具有`.exe`扩展名。 根据文件的内容和功能,我们可以将文件分为程序文件和...

    电脑基础知识c语言续PPT课件.pptx

    而非缓冲文件系统则需要程序员手动管理缓冲区,这在现代C语言编程中很少使用,因为ANSI C标准已经推荐使用缓冲文件系统来处理所有类型的文件,包括文本文件和二进制文件。 在C语言中,文件操作以流的形式进行,这是...

    C语言中国象棋C语言中国象棋

    C语言中国象棋程序设计...该程序展示了C语言编程的多个方面,包括数组、指针、宏、常量、游戏状态机、棋盘表示、棋子表示、游戏逻辑、界面设计、游戏状态保存和加载、键盘输入和事件处理、错误处理、代码组织和结构等。

    C programming language

    描述与标签:“C编程语言”涵盖了计算机科学中的一种核心编程语言,以其高效、灵活和广泛的应用范围而闻名。C语言自1972年由Dennis Ritchie在贝尔实验室开发以来,成为了现代编程语言的基石,影响了如C++、Java等...

    C语言程序设计复习大纲PPT课件.pptx

    熟练掌握C语言的基本知识,具备基本的C程序设计能力,能熟练地阅读、理解和编制简短的C程序。 基本内容 ### 数据的定义 * 数据类型和存储类别 + 基本类型:整型、实型、字符型(主要是int, float, double, char...

    C语言复习

    C语言的运算符种类多样,包括算术、关系、逻辑、位和指针运算,这使得处理各种计算和逻辑判断变得简单。 C程序的基本结构是基于函数的。一个C程序可以包含一个或多个函数,每个函数由函数说明和函数体组成。函数...

    C语言学习课件

    C1-简介 C2-运算符、表达式 C3-运算符、表达式(续) C4-基本语句、顺序结构 C5-选择结构 C6-循环结构 C7-循环结构(续) C8-数组 C9-字符数组 C10-结构体 ...C12-函数(续1) C13-函数(续2) C14-指针 C15-指针(续)

    嵌入式C语言进阶之道(C语言编程风格)

    此外,遵循一定的规范和最佳实践,如MISRA-C规范,可以有效避免潜在的安全隐患,提高系统的稳定性和可靠性。最后,合理的性能优化措施能够充分利用有限的硬件资源,达到更好的运行效果。总之,良好的编程习惯是每一...

    华为笔试题及答案.doc

    6. 数组和指针的关系(续) 在问题(6)中,我们可以看到数组和指针的关系。在数组的指针加 1 时,系统会认为加一个数组的偏移,而不是简单地加 1。因此,指针的计算需要根据指针类型和数组的大小。 7. 内存分配...

    飞鸽传书c语言源码

    源码中会包含C语言的基本结构,如变量声明、函数定义、控制流语句(if-else、for、while)、数据类型(int、char、float等)和指针操作。学习者可以通过源码理解C语言如何用于实现复杂的系统功能。 在飞鸽传书的...

    12月C语言选择题

    选项B不准确,C语言允许定义空类型指针;选项C不准确,枚举类型是C语言中的基本类型之一;选项D不准确,数组属于构造类型。 #### 50104 题目解析:main()函数的位置 **题目**: main()函数的位置(B)。 - A.必须在...

    C语言数据结构练习题,学校考试用

    本资源包含了一组C语言实现的数据结构练习题,旨在帮助学生巩固和提升对数据结构的理解,为学校的考试做好准备。 在数据结构的学习中,我们通常会接触到以下关键概念: 1. **数组**:是最基本的数据结构,用于存储...

    C语言 酒店管理系统VC6.0编辑

    该酒店管理系统利用C语言的基本控制结构和数据类型实现了酒店预订的主要业务功能。尽管没有使用指针、数组或文件读写等更高级的功能,但通过对基本数据结构的巧妙运用,仍能较好地满足需求。通过本系统的开发,不仅...

    linux c编程源码

    8. **内存管理**:C语言提供动态内存分配函数`malloc`、`calloc`、`realloc`和`free`,理解内存管理的原理和最佳实践,避免内存泄漏和悬挂指针。 9. **权限和文件系统**:了解Linux的用户和组概念,以及如何使用`...

    用纯C语言实现C8051F单片机的在线程序更新.zip_C8051f 在线_c8051_在线升级

    本项目聚焦于如何使用纯C语言来实现对C8051F单片机的在线程序更新,这是一项重要的技术,它允许在不拆卸设备的情况下更新固件,提高了系统的可维护性和灵活性。 在线程序更新(OTA,Over-the-Air Update)的核心...

    C语言题库(含答案).pdf

    - `const`用于声明常量,可以修饰基本类型、指针、函数参数和返回值,以及类成员。修饰指针时,可以表示指针本身是常量(不能改变指针地址),或指针所指的对象是常量(不能通过指针修改对象的值)。 9. `const`的...

Global site tag (gtag.js) - Google Analytics