您的位置: 首页 N搜咨询 文章阅读 C数值计算程序移植到VC开发环境
打印本页 放大字体 关闭本页
C数值计算程序移植到VC开发环境

作者:N搜网友 编辑:N搜网 录入:N搜网 来源:N搜网络
录入时间:2006-8-17 更新时间:2006-8-17 点击次数:700
主标题:C数值计算程序移植到VC开发环境
副标题:C数值计算程序移植到VC开发环境
短标题:C数值计算程序移植到VC开发环境
 
   摘 要:针对C程序的特点,给出将之移植到VC集成环境下的技术,对一个常用程序集实施了改写,并提供了C++数组和矩阵模板类,对C程序进行面向对象的封装。
    关键词: 移植;数值计算;封装;模板类
    The Migration of Old C Code to Visual C++ IDE
    Abstract: According to the character of C programs, this paper presents some techniques to migrate them to Visual C++ IDE, as a implemention, it reprograms a set of numerical arithmetic programs for further engineering use.
    Key words: Migration; Numerical Arithmetic, Encapsulation, Template Class
    代码下载
    一. 引言
    由于C语言长期广泛应用,现存有大量经过严格检验的实用C程序,它们可以用来很好地解决工程应用中的实际问题。但是旧的C程序往往有很多与现代编译器不兼容的地方,因此我们要根据具体的代码情况进行相应的移植处理。
    本文以改写清华大学出版社出版的C常用算法程序集(以下简称“程序集”)为例,说明如何将旧的C程序移植到目前普遍使用的C/C++开发环境Visual C++下。除了列举一些移植程序的方法和技巧,本文还给出两个C++类:数组类和矩阵模板类,以例示如何对C程序进行面向对象的包装处理。
    二。.基于C语言分析和改换
    我们知道,Visual C++支持ANSI C,下面列举源代码影响编译、不兼容的情况和相应解决方案,并给出基于ANSI C标准的函数的基本调用例子。
    1. 函数定义参数声明没有采用现代风格,例如全选主元高斯消去法:
    int agaus(a,b,n)
    int n;
    double a[],b[];
    {……;}
    参数声明应改为数组形式:
    int agaus(double a[],double b[],int n)
    或者改为指针形式:
    int agaus(double* a,double* b,int n);
    调用方法:
    agaus(&a[0][0],&b[0],n);
    /* a二维双精度型数组、b一维双精度型数组,n整型变量 */
    C/C++中用下标法和指针法都可以访问一个数组,设有数组a,则a[i]和*(a+i)无条件等价。如果指针变量p指向数组中的一个元素,则p+1指向同一数组的下一个元素。若p的初值为&a[0],则p+i和a+I都是a[i]的地址;*(p+i)和*(a+i)就是p+i或a+i所指向的数组元素,即a[i];指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。所以,在实际使用该函数,如果遇到数组作形参,可以将数组第一个元素地址作为实参传值调用函数。
    2. 动态存储分配函数返回void*型指针变量,它指向一个抽象类型的数据,ANSI C标准规定在将它赋值给另一个指针变量时需要进行强制类型转换,所以下面代码Line1要用Line2替换:
    double* v;
    v=malloc(n*m*sizeof(double));/* Line1 */
    v=(double*)malloc(n*m*sizeof(double));
    /* Line2 */
    3. 某些算法函数可能要调用一些用户自定义函数,如最佳一致逼近的里米兹方法:
    void hremz(a,b,p,n,eps)
    int n;
    double a,b,eps,p[];
    { extern double hremzf();
    …
    }
    原方法使程序集与应用程序的耦合程度增加,缺乏灵活性,可以改为:
    void hremz(double a,double b,
    double p[],int n,double eps,
    double (*hremzf)(double x))
    {…
    }
    用函数指针作参数,调用时直接将函数名作实参即可:
    hremz(a,b,p,4,eps,hremzf);
    /* 假设各参数在主程序文件已定义 */
    4. 有的时候需要将一些函数的控制台输出作为字符串值返回,比如:
    printf("%c",xy[i][j]);
    我们可以用形似
    sprintf( buffer,"%c",xy[i][j]),
    strcat( str, buffer );
    的合并语句(其中str是一个足够大的字符串数组参数)代替
    printf("%c",xy[i][j]);
    例如:
    char* buffer;
    buffer =(char*)malloc(n*sizeof(char)); /*n作为参数传递,例如100 */
    sprintf( buffer,"%c",xy[i][j]),
    strcat( str, buffer );    
    /*把终端输出字符添加到str 串尾*/
    …
    free(buffer)
    如果用到了它们,调用方法以随机样本分析为例:
    char str[1024];
    str[0]='\0';/*初始化为空串*/
    irhis(x,100,x0,h,10,1,&dt[0],&g[0],&q[0],str);
    现在str数组保存了终端输出文本,可以随意使用它,比如在控制台程序里输出:
    puts(str);
    在使用MFC类库时,str可以直接赋值给一个CString对象的实例。
    经过以上的工作,我们得到基于ANSI C标准的程序版本,可以在C和C++开发环境下使用。
    三. 基于C++语言分析和改换
    由于C语言本身的弱点,程序集还存在的缺陷主要有
    1.异常处理机制支持较弱;
    2.程序没有对数组下标是否越界的检测。
    如果编程人员对C/C++语言很生疏,并且不熟悉该程序集,那么有可能由于编码的失误在调试过程中得到不可预知的荒谬结果。我们的解决方案是为程序集增加C++的异常处理机制,以及用类封装技术,对数组进行面向对象的封装和使用,用Array模板类对象替换一维数组,用Matrix模板类对象替换二维数组。下面给出两个类的声明部分,它们分别实现最基本的数组和矩阵数据结构和算法。
    template <class T=double>
    class TArray
    {
    protected:
    T* pdata;
    unsigned int length;
    public:
    TArray();
    TArray(unsigned int);
    TArray(TArray const&);
    virtual ~TArray();
    void operator = (TArray&);
    TArray<T>& operator + (TArray&);
    TArray<T>& operator - (TArray&);
    T const& operator [] (unsigned int)const;
    T& operator [](unsigned int);
    T const* GetData() const;
    unsigned int GetLenght();
    void SetLength(unsigned int,bool=true);
    };
    template <class T=double>
    class TMatrix
    {
    protected:
    unsigned int numberOfRows;
    unsigned int numberOfColumns;
    TArray<T> array;
    public:
    class Row
    {
    TMatrix<T>& matrix;
    unsigned int const row;
    public:
    Row (TMatrix<T>& _matrix,unsigned int _row):matrix(_matrix),row(_row){}
    T& operator [](unsigned int column)const
    {return matrix.Select(row,column);}
    };
    TMatrix();
    TMatrix(unsigned int, unsigned int);
    TMatrix(TMatrix<T>& mat);
    virtual ~TMatrix();
    T& Select(unsigned int, unsigned int);
    Row & operator[](unsigned int);
    TMatrix<T>& operator + (TMatrix<T>& mat);
    TMatrix<T>& operator - (TMatrix<T>& mat);
    TMatrix<T>& operator * (TMatrix<T>& mat);
    bool operator == (TMatrix<T>& mat);
    TArray<T>& GetData();
    unsigned int GetNumberOfRows();
    unsigned int GetNumberOfColumns();
    bool LoadFromArray(T [],unsigned int,unsigned int);
    bool LoadFromString(char*,char,char);
    bool ResetMatrix(unsigned int, unsigned int);
    bool ReverseMatrix();
    void ZeroMatrix();
    void RandomMatrix(int max);
    };
    举例说明我们关于异常机制和数组越界的检测方法的思路。TMatrix类的operator[]返回一个嵌套类Row的引用,它用来描述某一给定二维数组的一个特定行。Row类的operator[]则返回该行一个特定位置的T类型值。最终实现还是通过Matrix<T>::Select()函数,该函数体代码如下:
    template <class T>
    T& TMatrix<T>::Select(unsigned int i, unsigned int j)
    {           
    char ch[50];
    if(i>=numberOfRows)
    sprintf(ch," Error -- Invalid row: %d",i), throw (ch);
    if(j>=numberOfColumns)
    sprintf(ch," Error -- Invalid colum: %d",
    j), throw (ch);
    return array[i*numberOfColumns+j];
    }
    应用程序实例:
    unsigned int i,j;
    unsigned int m=2,n=3;
    TMatrix< > mat(m,n);//双精度型矩阵
    try
    {
    for(i=0; i<m; i++)
    {
    for(j=0; j<n+1; j++)// Line3
    cout<<mat[i][j]<<"\t";
    cout<<endl;
    }
    }
    catch(char* str)     //捕获异常
    {cout<<str<<endl;}
    终端输出如下(注:类实例mat没有初始化):
    -6.27744e+066   -6.27744e+066   -6.27744e+066   Error -- Invalid colum: 3
    只输出一行,根据出错提示,把Line3改为:“for(j=0; j<n; j++)”,重新编译运行,输出2行3列的正确结果:
    -6.27744e+066   -6.27744e+066   -6.27744e+066
    -6.27744e+066   -6.27744e+066   -6.27744e+066
    由于我们对operator[]进行了重载,所以数组模板类(矩阵模板类)完全兼容C/C++一维数组(二维数组)的存取操作,因此旧程序中数组变量直接可以用类实例变量替代。
    上边给出的数组和矩阵模板类简洁高效,易于使用,并且也有较好的灵活性。但是,标准C++中提供了为数值计算优化过的valarray模板类取代数组操作,请参阅文献[3],在Numerics这一章中,探讨了valarray,slice等技术,并给出一个在此基础上Matrix类的实现。建议熟练的C++程序员掌握这些更为权威、高级的技术。笔者已经在所附的程序集里包含了一个实现,可能有Bug哦,呵呵!
    图1是我们用Visual C++ 6开发的演示程序界面,左边是所有算法的目录树,右边是文本计算结果输出,下部悬浮窗口是算法程序源代码,可以拷贝粘贴,稍作修改即可重用。
    图1
    四. 结论
    新的程序与原程序相比较的优点
    1. 遵从ISO C/C++标准,因此具有良好的可移植性。可以在大多数流行的C++开发环境下使用;
    2. 利用一些技巧,改进了原程序不利于扩展和缺少灵活性的缺点;
    3. 去除了原程序中几个影响效率的Bug;
    4. 增加异常处理机制和数组越界检测,增强可调试性和健壮性;
    5. 数组和矩阵操作得到了强有力的支持。
    经过我们实际应用测试,新的程序集可以满足一般工程应用的数值计算需要,并且能够在原来的基础上,方便地进行必要的改进和扩充。

 

N搜网-中国网上商店商品服务搜索门户]:[本文章由N搜网于2006-8-17录入系统,网址:www.nsall.com

打印本页 放大字体 关闭本页
 
 
相关主题文章
C++中的const限定修饰符 C++中的虚函数(virtual function)
C++中确定基类有虚析构函数 C++中用vectors改进内存的再分配
C++中用函数模板实现和优化抽象操作 CBuilder中帮助文件的连接及显示讨论
CRC循环校验的具体算法 C标准中一些预定义的宏
C程式中关于整数储存的说明 C数值计算程序移植到VC开发环境
C语言初学者入门讲座 第八讲 转移语句 C语言初学者入门讲座 第二讲 数据类型(1)
C语言初学者入门讲座 第二讲 数据类型(2) C语言初学者入门讲座 第二讲 数据类型(3)
C语言初学者入门讲座 第九讲 数组(1) C语言初学者入门讲座 第九讲 数组(2)
C语言初学者入门讲座 第六讲 分支结构(1) C语言初学者入门讲座 第六讲 分支结构(2)
C语言初学者入门讲座 第七讲 循环结构 C语言初学者入门讲座 第三讲 基础语句
C语言初学者入门讲座 第十二讲 结构(1) C语言初学者入门讲座 第十二讲 结构(2)
C语言初学者入门讲座 第十二讲 结构(3) C语言初学者入门讲座 第十讲 函数(1)
C语言初学者入门讲座 第十讲 函数(2) C语言初学者入门讲座 第十讲 函数(3)
C语言初学者入门讲座 第十讲 函数(4) C语言初学者入门讲座 第十六讲 文件(1)
C语言初学者入门讲座 第十六讲 文件(2) C语言初学者入门讲座 第十三讲 联合
C语言初学者入门讲座 第十四讲 枚举与位运算(1) SNMP用VC++6.0实现的方法
XML在系统日志设计中的运用 利用VC++编写Windows95的CPL组件
利用VC++开发所见即所得的打印程序 利用VB自制OCX控件
利用Visual Basic 实现无线通讯 利用VC实现AVI文件的图像截取
利用VB实现宽行打印的一个技巧 调试Release版本应用程序
利用VC++编程实现程序自动启动 利用VB制作MP3播放列表
利用VC++开发ASP图像处理组件 利用VC++获取异构型数据库库结构信息
如何在ASP.Net 中把图片存入数据库 用TAPI为掌上电脑开发通讯应用程序
让窗口一直在上面 通过DELPHI小程序在WINDOWS下更好地使用DOS批处理…
用ASP实现的2000年倒记时程序 在vb组件内调用excel2000实现GIF饼图
用VB编写接近实际的抽奖程序 微软风格的Explore
在 C# 中使用画笔 用VB6分离出文本框的单词
如何拦截键盘输入 在VB5.0下有效控制鼠标的输入焦点
用VB5创建B/S程序 在ASP中用“正则表达式对象”来校验数据的合法性…
用VB实现局域网屏幕监视 用ASP实现网上考试系统
在ASP中利用“正则表达式” 对象实现UBB风格… [组图] 用Excel的宏编制个人证券账户管理器
用Powerbuilder进行分布式应用开发三级体系结构 在Asp.Net中从sqlserver检索(retrieve)图片
论游戏中的搜索问题(初级篇) 用VB调试串口通讯
使用API创建窗体(类似VC的创建过程) 用Delphi做一个OpenGL控件
如何在程序中使用自己的库单元 消息队列在VB.NET数据库开发中的应用
在VFP5.0中实现中英文自动切换 在BCB下使用GExperts的Debug功能
用FoxWeb在网上快速发布你的FOXPRO数据库 用VB6.0设计一个打字练习软件
在VFP中实现跟变式组合框及椭圆图形菜单 用Delphi合并Word表格中单元格
用BCB实现超星格式转换为BMP格式 拼图游戏的算法
在拷贝、删除文件时显示飞行的文件夹动画 在PB中如何使用Microsoft Outlook发送邮件
在PowerBuilder中调用ChooseColor函数 一个简单的MP3播放器
如何用pb实现MSACCESS数据库的图片字段存取 在C++Builder中使用Compress Html Help
压缩HTMl文件 在powerbuilder中向Excel传递数据
人民币大小写转换算法 在PB中应用灵活多样的排序
如何在程序启动默认浏览器与电子邮件系统 用C#编写获取远程IP,MAC的方法
用API实现在MSN的信息提示 真正意义上的前台窗口切换
如何在ASP程序中打印Access报表 如何在Windows应用程序中实现电子注册功能
上楼梯算法的java实现 实时曲线的绘制和保存
用Vb.net实现自定义界面 刘徽《九章算术》中的勾股数
ASCII码表 水仙花数
 
 
 
本站关键字:网上商店商品服务大全 网上购物导航 在线购物搜索引擎 网店比较购物 网络商城 特色网上超市商店 网上网络开店购物