`
liujunsong
  • 浏览: 75554 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中如何模拟指针操作,以迁移C++代码

阅读更多
1.前言
前段时间做了一项重要的工作,就是将原来开源的ICTCLAS的C++代码,全部迁移到了Java语言重新实现,在迁移完成以后,初步测试没有啥大问题,在此过程中得到了一点小小的经验,特记录下来,以供大家参考。

2.问题的分析
虽然说Java语言是从C++演化过来,语法关键词基本类似,但C++语言和Java语言相比,有一个最为关键的不同,就是Java不支持指针,无法直接进行地址的计算,这样的话,就给代码迁移带来了很大的困难。
例如下面这段代码,是C++的原始代码。
bool CContextStat::GetItem(int nKey,PMYCONTEXT *pItemRet)
{//Get the item according the nKey
	PMYCONTEXT pCur=m_pContext,pPrev=NULL;
	if(nKey==0&&m_pContext)
	{
		*pItemRet=m_pContext;
		return true;
	}
	while(pCur!=NULL&&pCur->nKey<nKey)
	{//delete the context array
		pPrev=pCur;
		pCur=pCur->next;
	}
    if(pCur!=NULL&&pCur->nKey==nKey)
	{//find it and return the current item
		*pItemRet=pCur;
		return true;
	}
	*pItemRet=pPrev;
	return false;
}


在这段代码中,要将这段代码使用Java来实现,最为头疼的地方就是*这个操作符号了,因为Java里面不能直接操作内存地址,因此必须采用转换的方式来进行模拟实现。

3.解决思路
在C语言里面,*操作符号和&操作符号是相对的,一个用来将指针所在地址赋值,一个用来获取一个内存地址。而在Java里面,内存地址是无法直接访问,也无法直接获取的。
因此在上面的例子中,我们首先定义一个PMYCONTEXT类。这个类代表一个一级指针。
/**
 * PMYCONTEXT的定义是一个指向结构体MYCONTEXT的指针, 是一个一级指针
 * @author liujunsong
 * 
 */
public class PMYCONTEXT {
	public MYCONTEXT p=null;// The chain pointer to next Context
	/**
	 * 带参数的构造函数
	 * @param tag
	 */
	public PMYCONTEXT(MYCONTEXT tag){
		p=tag;
	}
	
	/**
	 * 得到下一个节点,通过封装p来实现。
	 * @return
	 */
	public PMYCONTEXT next(){
		if(p!=null){
			return p.next;
		}else{
			return null;
		}
	}
	
	/**
	 * 从当前节点开始,递归到各个下级节点,然后释放所有链表的内存
	 * 这个方法用来释放内存。
	 */
	public void DestroyAll(){
		PMYCONTEXT pCur=next(),pTemp;
		//递归清理所有下级的节点
		while(pCur!=null){
			pTemp=pCur.next(); //得到下一节点			
			pCur.p.Destroy(); //当前节点内存释放
			pCur=pTemp; //指向下一节点
		}
		//清理本级指针对应节点
		if(p!=null){
			p.Destroy();
			p=null;
		}
	}
	
}

但在原来的C语言代码中,输入参数采用PMYCONTEXT *pItemRet的方式,实际上定义了一个二级指针出来,而Java不支持这样的直接定义,所以我们需要另外一个专门的二级指针对象,来模拟这个C语言里面的二级指针对象。
/**
 * 一个指向MYCONTEXT的二级指针
 * @author liujunsong
 *
 */
public class PPMYCONTEXT {
	public PMYCONTEXT p=null;
	
	/**
	 * 唯一可用的构造函数,可以传入一个null
	 * @param point
	 */
	public PPMYCONTEXT(PMYCONTEXT point){
		p=point;
	}
	
	/**
	 * 重新设置指针的值,这一方法不会生成新的PPMYCONTEXT对象
	 * 也不会重新分配内存。
	 * @param point
	 */
	public void setValue(PMYCONTEXT point){
		p=point;
	}	
}

有了这样一个对应的二级指针定义以后,就可以直接上面提到的C++语言代码,直接迁移改造成同等算法的Java代码,结果如下:
	/**
	 * 利用给定的key值,来检索一个MYCONTEXT对象,返回一个ppItemRet,二级指针
	 * <P>
	 * 在二级指针中设置指针的数据,不新增加内存。
	 * 
	 * @param nKey
	 * @param pItemRet
	 * @return
	 */
	private boolean GetItem(int nKey, PPMYCONTEXT pItemRet) {
		// Get the item according the nKey

		PMYCONTEXT pCur = _copy(m_pContext), pPrev = null;

		if (nKey == 0 && !_isNullPoint(m_pContext)) {
			pItemRet.setValue(m_pContext); // 如果nkey==0,返回头元素
			return true;
		}

		// pCur有效的情况下,循环查找,来按照nKey来查找
		// 此处代码有一个bug,假设是按照nkey来排序的
		// 但在Add的时候并没有进行排序处理
		// 所以要修改一个判断条件为不相等
		while (_isNotNullPoint(pCur) && pCur.p.nKey != nKey) {
			pPrev = _copy(pCur);
			pCur = _copy(pCur.next());
		}

		// 循环结束,判断循环结束点
		if (_isNotNullPoint(pCur) && pCur.p.nKey == nKey) {
			// find it and return the current item
			pItemRet.setValue(pCur);
			return true;
		}

		pItemRet.setValue(pPrev); // 设置最后一个有效节点
		return false;
	}

修改完成以后经过测试,程序运行正常。

4.小结
ictclas本身代码量有将近1M,原来的数据结构设计的非常严格,算法设计的也很巧妙,对于指针的使用非常频繁,几乎没有一段代码不涉及到指针的使用,采用上面这种方式进行数据结构的模拟,指针的模拟以后,在很短的时间内就将全部代码迁移到了Java语言重新实现。经过初步测试,系统功能完全正常。
同时由于存在一个作为样板目标的C++代码存在,当系统发生异常的时候,可以很方便的进行代码比较跟踪,查看那里修改算法出现了错误,这样就提高了程序开发的效率和质量。
欢迎大家下载本blog发布的ictclas,Java改写版本,其中附带有C++源代码,可以对比查看,确定效果如何。
如果大家还有其他C++代码迁移的案例,欢迎一起来讨论学习。
分享到:
评论

相关推荐

    C++ 指针 实现迷宫 程序代码 C++ 指针 实现迷宫 程序代码

    C++ 指针 实现迷宫 程序代码 C++ 指针 实现迷宫 程序代码 C++ 指针 实现迷宫 程序代码 C++ 指针 实现迷宫 程序代码

    27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)

    27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?(Visual C++编程 源代码)27.如何使用代码获取状态栏指针?...

    15.如何使用代码获取工具栏的指针?(Visual C++编程 源代码)

    15.如何使用代码获取工具栏的指针?(Visual C++编程 源代码)15.如何使用代码获取工具栏的指针?(Visual C++编程 源代码)15.如何使用代码获取工具栏的指针?(Visual C++编程 源代码)15.如何使用代码获取工具栏...

    约瑟夫环的C++代码

    约瑟夫环的C++代码,采用链表的数据结构,对写出了链表的模板类

    C++智能指针测试代码

    C++ 7种智能指针测试代码

    C++中this指针的用法

    C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法C++中this指针的用法

    C++指针介绍.ppt

    C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针介绍.ppt C++指针...

    C#,C++,VB,JAVA,C指针学习源代码大全

    指针的艺术配套光盘 讲述了五种计算机语言的指针使用方法 C,C++,C#,VB,JAVA 学好指针下这个资源就够了

    C和C++代码精粹 C和C++代码精粹

    《C和C++代码精粹》基于作者备受好评的C/C++ User Journal...《C和C++代码精粹》可以帮助有一定经验的C和C++程序员深入学习这两种密切相关的语言,对书中代码的参悟和应用,可以帮助他们从根本上提高使用程序的效率。

    c++模拟指针程序设计

    c++以模板形式编写,有很强的通用性 操作有,添加元素,删除元素,搜索元素,输出所有元素。

    关于C++中栈指针和堆指针的使用说明

    在这个类中有一个成员方法叫getArray(),在该方法中使用以上方式声明一个数组,然后返回数组的指针,然后在另一个成员方法showPointerOfArray(int*)接收传过来的int指针,在这个方法操作数组。 但是在运行时没有出现...

    C++ 与C#之间的指针参数传递传参参考

    C++ 与C#之间的指针参数传递,实现无限量数据的传递,轻松无压力,方便在C++里面获取或者从C#传递数据到C++的动态库调用内。

    C++指针学习C++指针学习

    C++指针C++指针C++指针C++指针C++指针C++指针C++指针C++指针C++指针C++指针C++指针

    C++指针 数组 内存释放.docx

    C++指针 数组 内存释放 相关说明

    C和C++代码精粹

    《C和C++代码精粹》基于作者备受好评的C/C++ User Journal..., 《C和C++代码精粹》可以帮助有一定经验的C和C++程序员深入学习这两种密切相关的语言,对书中代码的参悟和应用,可以帮助他们从根本上提高使用程序的效率。

    C++ 指针讲解 C++ 指针讲解

    C++ 指针讲解 C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解C++ 指针讲解

    C#中使用指针源程序,我想许多C程序员不愿意学习Java的原因之一就是Java不支持指针

    C#中使用指针源程序,我想许多C程序员不愿意学习Java的原因就是Java不支持指针,但是现在类似于Java的C#却已经支持了指针,你可以使用unsafe关键字来告诉编译器下面的函数或者代码是不安全的。一旦你使用了unsafe,...

    C++中指针的使用艺术

    C++中指针的使用艺术 C++中指针的使用艺术

    C# 调用C++DLL(函数参数包含指针)

    C#调用C++DLL,C++DLL中的函数参数包含指针。 绝对可用。

    指针函数和函数指针 C++代码

    指针函数和函数指针是C语言里两个比较绕的概念。但是不仅面试题爱考,实际应用中也比较广泛。很多人因为搞不清这两个概念,干脆就避而远之,我刚接触C语言的时候对这两个概念也比较模糊,特别是当指针函数、函数指针...

Global site tag (gtag.js) - Google Analytics