一个动态分配内存及指向它的指针(C++)
收到版言主的来信,要求我进一步改进,我细化了一些文字与细节,给程序加了必要的注解,还附上个人的见解,我现改进如下: skipable-story: 常时间的埋头钻研,有苦有乐,有失落的情绪也有激昂的斗志。但一昧do it all by myself,我发现有很多时候,问题会变得相当的frustrating,跟本就没有rewarding感。 想必我也这样苦战了四年多,从无线电到计机算机,最后又从计算机学回到电子信息工程,这使得我对电类专业有了很深的了解。一路的课程可真的可谓大开眼界;从电路基 础到电路分析,从低频到高频,从数电到模电,从电视机到单片机,又从单片机过度到微机(8086);后来专功了一阵汇编语言,发现有汇编语言编太累(编一个实现 45*4/7+8-2)的计算器就把我累坏了,更不说什么工程了;但唯一让我有成就感的是我明白计算机的工作原理,进而又学了pascal这门最早的算法语言,但发现已很少有人用这开发什么了;又过度到了C语言,就在我用C语言编写比较大的程序的时候我又发现了自已的问题了,年青人对外表最感兴趣,自然一个好的用界面对于一个成功的程序是至关重要;还有我们总不可能编一个程每运行一次就得重新输入一次数据(很多人都这样,悲衰!),这样对于一个简单的数据管理程序来说,操作员实在是太累了,这就要求要学会利用文件来管理。当我试图实现这些时,我发现我得先学会驱到程的原理,显式的显示模式,初始化,这里又涉及了硬件及操作系统的功能调用问题;要学好文件管理系统又要先懂流操作,内存如何实现buffer与硬作的协调工作,文件的具体数据结构(包括逻辑结构与物理结构)及实现的方法。这样续学了《操作系统概论》,《微机原理》.后来深入学习了win2000,但我发现跟本就啃不动,因为有太多的高级技术我弄不明白,有很多也不公开,最后以失告终。进入Dos这习阶段,在Dos的学习过程中我发现我所看到的地方我都能接受,虽然不能自己做出来(例如加一个中断向量,直接用功能调用来编写几个不是很完美的Dos命令,驱动程序组成结构及接口规范等)。走到这一步我已觉得身心疲备不堪,后来就开始着手编写有点水平的程序,虽然我知道我还缺泛《数据结构》,《图论》,《编译原理》,《软件工程》等方面的知识,我都没有花时间去学习,只是实行缺那补那的原则。因为我学的专业是电子信息工程,加者学习上任务也不轻,有要考六级。这样我已有很长时间没写程序了,隅尔打印几分C/C++的函数头文件graphics.h,Stdio.h,String.h,ctype.h,math.h,mem.h 来看看。这样在编程时就不用自己编写没有质量保证的函数,用得越多错得越多,也省得累坏了自己。好了先把自己的故事说到这。这是我第一次到论谈来有很多地方不懂望能得到各位的指教。我真心的希望能与大家成为道上的良师益友。
point section:
经过长时间的学习与自身的编程体练我发现编一个含金量较高的程序真的不容易,而且还发现如果还发现一旦编写成功,受益非浅.
我现在举一个最生动最有代表性的例子来与大家分享.在我的发表中如果有错误与足的地方,我恳请各位编程高手能给指点与指正,本人将 感激不尽。我发现编程是一门艺术,不仅是一门科学,加上本人的语言表达能力有限,所以在很多地方我都会用列子来说明问题,再与一些 必要的文字来说明。这个程序起源于《线性代数》这门课程:克拉默法则。
我给程序的名称叫《元素全排列的实现》 illustration: 输入:3 (阿拉伯数字) abc(或任意字符) 输出:abc cab bca bac cba acb(或相应字符的全排列)
本程序所出现的问题是当我输入的数据元素个数超过6个时,就出错了,系统的错误信息是“not enough memory", 但按理说这是决对不可能内存不足。(看完程序后,希望各位能发现它隐含错误的地方)
我刚开始编写此程序时,范了一个目前许多编程学习者和程序员都爱范的毛病------一个程序=一个含有main()主函数的文件.声明与定义不独立成文件. 这虽然没有错误,但最起码没有人愿意看他的程序,与大众接不了斩.这样的成功又能展现在谁的面前,谁又能说它的程序是成功的呢?所以我把我的程序大众 化了,分为三个文件: ele.h(类声明), ele.cpp(类定义), arrange.cpp(程序的实现)
代码清单如下: //文件说明------------------------很多人都没有写这一部分,如果要发表,最好写上这一部分,因为没有人愿意接受没有产品说明的东西. /* * Copyright (c) 2005, 沈阳理工大学信息工程系电子信息工程专业 * All rights shared. * * Filename: ele.h * File speciment: offered in agneda * Abstract: arrange object * * Current edition: 1.1 * Author: Victory Chueng * Completed date: Jun, 20th, 2005 * * Replaced edition: 1.0 * Author: Victory Chueng * Completed date: Jun, 25th, 2005 */ //文件说明结束----------------------*
//避免同一文件的多次包含的实现 #ifndef ELE_h #define ELE_h
#include <stdio.h> #include <iostream.h> #include <string.h> #include <conio.h> #include <assert.h> #include <ctype.h> #include <stdlib.h>
typedef struct Elements //把元素定义成结构体 { char m_ch; //用于存放从键盘输入的相应单个字符 int m_order; //用于存放从键盘输入的相应单个字符的序号,但本程序没用到此变量,以后的相应程序要用到. } Elements;
class Arrange //排序定义成类 { protected: unsigned long Factor(int n=0); // evaluate factorial 用于实现求N的阶乘 void Shift(Elements *desEl=NULL,int n=0); // rotate one object by right 用于把Elements数组右循环移动一个元素如:abc->cab public: void Show(); // show the result on screen 用于显结构 void Act(void); // implement permutation 排列的具体实现过程 Arrange(int initn=0,const char *str=NULL); Arrange(const Arrange &other);//拷贝构造函数 Arrange &operator=(const Arrange &other);// 对象赋值函数 ~Arrange(void); public: Elements *m_pEl; //用于指向动态生成Elements的指针 int m_n; //用于存放元素的个数 };
#endif //-------------------ele.h文件结束-----------------------------------------
//-------------------------------ele.h的实现文件ele.cpp------------ /* * Copyright (c) 2005, 沈阳理工大学信息工程系电子信息工程专业 * All rights shared. * * Filename: ele.h * File speciment: offered in agneda * Abstract: arrange object * * Current edition: 1.1 * Author: Victory Chueng * Completed date: Jun, 20th, 2005 * * Replaced edition: 1.0 * Author: Victory Chueng * Completed date: Jun, 25th, 2005 */
#include "ele.h"
//用递归实现n的阶乖 unsigned long Arrange::Factor(int n) { unsigned long result=0; if(n==1||n<=0) return 1; result=n*Factor(n-1); return result; }
void Arrange::Shift(Elements *desEl, int n) { assert(desEl!=NULL); //用于检查是否申请成功
Elements temp=*(desEl+n-1); //用于暂存最后一个元素
for (int i=n-1; i>=0;i--) //依次后移元素 *(desEl+i)=*(desEl+i-1);
*desEl=temp; //把最后一个元素放到原第一个元素的位置 }
void Arrange::Act() { assert(m_pEl!=NULL);//用于检查是否申请成功
Elements temp; //暂存 Elements *buffer=new Elements[m_n]; //申请n个Elements的空间用于暂存 assert(buffer!=NULL);
for (int k=2; k<m_n+1; k++) { unsigned long l=Factor(m_n)/Factor(k); //用于计算步长l的值
unsigned long c=Factor(k-1); //用于计算需要处理的数组个数
for (unsigned long i=0; i<c; i++) for(unsigned long j=0; j<k-1; j++) { memcpy(buffer,(m_pEl+(i*k*l+j*l)*m_n), //把原数组拷到buffer中 sizeof(Elements)*m_n ); //处理buffer temp=*(buffer+k-1); //以下几行本可以用Shift(。。。)来代替,但考虑到郊率,直接用Shift()的原代码来实现 for (long t=k-1; t>=0; t--) *(buffer+t)=*(buffer+t-1); *buffer=temp; //以下的memcpy()把处理完的结果放到指定的位置 memcpy(m_pEl+(i*k*l+(j+1)*l)*m_n, buffer, sizeof(Elements)*m_n );
} } // end for(k)
delete [] buffer; //养成好习惯用后,以后不再用就删除,避免资源的浪费和可能造成的后痪 buffer=NULL; //避免野指针的出现 }
void Arrange::Show() { FILE *fp=fopen("result.txt","w"); assert(fp!=NULL);
int k=1; if(m_n!=0) { unsigned long n=Factor(m_n);
assert(m_pEl!=NULL);
const Elements *buffer=m_pEl;
for (unsigned long i=0; i<n; i++) { for (unsigned long j=0; j<m_n; j++) { cout<<(buffer+i*m_n+j)->m_ch; fprintf(fp,"%c",(buffer+i*m_n+j)->m_ch); } cout<<" "; fprintf(fp," ");
if (m_n!=0) { if (k%m_n==0) { cout<<endl; fprintf(fp,"\n"); k=1; } else { k++; } } } }//if(1) fclose(fp); }
Arrange::Arrange(int initn, const char *str) { const char *buf=str;
m_n=initn; if(initn==0) { NULL; }
else
{ unsigned long length=Factor(initn);
m_pEl=new Elements[length*m_n];// 可能问题在这 assert(m_pEl!=NULL);
for(unsigned long j=0; j<length; j++)//以下是初始化单元,别指望系统帮你初始化成0 for(unsigned long k=0; k<initn; k++) { (m_pEl+j*m_n+k)->m_ch='*'; (m_pEl+j*m_n+k)->m_order=0; }
Elements *e_buffer=m_pEl;// 以下是把从键盘的数据放到指定的地方
int i=initn; while (*buf!='\0' && i>0) { if(*buf==' ') { buf++; continue; }
e_buffer->m_ch=*buf; buf++; e_buffer++; i--; }
buf=NULL; e_buffer=NULL;
}//if(else)
} //下面这些是常用的常识,不用怎么细分了 // 本程序的数法大家不防这样考虑一下 // 假如我要处理的元素有4个,则计算机的要按这样处理 // i c L 计算机先处再这一步 // 2 1 12 其次 // 3 2 4 再次 // 4 6 1 最后 既结果以出现 // // 其中L为步长; 注意i*c*L=n!=24 // 大家跟据这个思路很快就能想明白 //
Arrange::Arrange(const Arrange &other) { unsigned long length=Factor(other.m_n); m_pEl=new Elements[length*other.m_n]; assert(m_pEl!=NULL);
memcpy(m_pEl,other.m_pEl,length*other.m_n*sizeof(Elements)); m_n=other.m_n; }
Arrange &Arrange::operator=(const Arrange &other) { if(this==&other) return *this;
delete [] m_pEl;
unsigned long length=Factor(other.m_n);
m_pEl=new Elements[length*other.m_n]; assert(m_pEl!=NULL);
memcpy(m_pEl,other.m_pEl,length*other.m_n*sizeof(Elements)); m_n=other.m_n;
return *this; }
Arrange::~Arrange() { delete [] m_pEl; }
//---------------以下为arrange.exe的实现-------------------------------------------------------------------------
#include "ele.h" #include <dos.h> main() { int n; char *str; system("cls"); cout<<"please input n="; cin>>n; cout<<endl; cout<<"please input char="; cin>>str; Arrange *a=new Arrange(n,str); a->Act(); cout<<"=============================================================="<<endl; a->Show(); cout<<"=============================================================="<<endl; delete a; return 0; }