首页 > 代码库 > 算法之美--2.2 Array

算法之美--2.2 Array

2016-12-02    00:24:12

      利用抽象数据类型实现Array;主要用C++模板实现数组类;体会一个完整的C++类的写法,能顺利写出来的人不多了,特别是对复制构造函数和重载= []运算,都需要扎实的基本攻。然后在测试程序中巧妙的实现了质数序列的输出,和一般的求质数方法有些不一样!

//#include "Array.h"
#include <stdio.h>

const int DefaultSize = 100;

template <class Type>
class Array
{
private:
    Type *elements;   //数组存放的空间
    int ArraySize;    //当前长度
public:
    Array(int Size = DefaultSize);
    Array(const Array<Type>& x);   //复制构造函数
    ~Array(){ delete[] elements; }

    Array<Type>& operator =(const Array<Type>& rhs);  //数组复制
    Type& operator [] (int i);                        //取元素值
    int Length()const { return ArraySize; };
    void ReSize(int sz);
};

template <class Type>
Array<Type>& Array<Type>::operator =(const Array<Type>& rhs)
{
    int n = rhs.ArraySize; //取rhs的数组大小
    if(ArraySize!=n)
    {
        delete[] elements;
        elements = new Type[n];  //重新分配n个元素的内存
        if (elements==NULL)
        {
            ArraySize = 0;
            cerr << "存储分配错误!" << endl;
            exit(1);
        }
        ArraySize = n;
    }
    //从rhs向本对象复制元素
    Type *destptr = elements;
    Type *srcptr = rhs.elements;
    while (n--)
    {
        *destptr++ = *srcptr++;
    }
    return *this;
}

template <class Type>
Array<Type>::Array(int sz)
{
    if (sz <= 0)
    {
        ArraySize = 0;
        cerr << "非法数组大小" << endl;
        return;
    }
    elements = new Type[sz];
    if (elements==NULL)
    {
        ArraySize = 0;
        cerr << "存储分配错误!" << endl;
        exit(1);
    }
    ArraySize = sz;
}

template <class Type>
Array<Type>::Array(const Array<Type>& x)
{
    int n = x.ArraySize;
    ArraySize = n;
    elements = new Type[n];
    if (elements==    NULL)
    {
        ArraySize = 0;
        cerr << "存储分配错!"<<endl;
        exit(1);
    }
    Type* srcptr = x.elements;
    Type* destptr = elements;
    while (n--)
    {
        *destptr++ = *srcptr++;
    }
}

template<class Type>
Type& Array<Type>::operator [] (int i)
{
    if (i<0||i>ArraySize-1)
    {
        cerr << "数组下标超界" << endl;
        exit(1);
    }
    return elements[i];
}

template <class Type>
void Array<Type>::ReSize(int sz)
{
    if (sz>=0&&sz!=ArraySize)
    {
        Type *newArray = new Type[sz];
        if (newArray==NULL)
        {
            cerr << "内存分配失败!" << endl;
            return;
        }
        int n = (sz <= ArraySize) ? sz : ArraySize;// 按照新的大小确定传送数据的个数
        
        Type *srcptr = elements;
        Type *destptr = newArray;
        while (n--)
        {
            *destptr++ = *srcptr++;
        }
        delete[] elements;
        elements = newArray;
        ArraySize = sz;
    }
}


#include <iostream>
#include <iomanip>

using namespace std;
int main(int argc, char ** argv)   
{
    Array<int> A(10);       //数组输出质数序列
    int n;
    int primecount = 0, i, j;

    cout << "Enter a value>=2 as upper limit for prime numbers:";
    cin >> n;
    A[primecount++] = 2;   //2是质数
    for (int i = 3; i < n;i++)
    {
        if (primecount==A.Length())
        {
            A.ReSize(primecount + 10);
        }
        if (i%2==0)  //偶数跳过
        {
            continue;
        }
        j = 3;
        while (j<=i/2&&i%j!=0)
        {
            j += 2;
        }
        if (j>i/2)
        {
            A[primecount++] = i;
        }
    }

    for (int i = 0; i < primecount;i++)
    {
        cout << setw(5) << A[i];
        if ((i+1)%10==0)
        {
            cout << endl;
        }
    }
    cout << endl;

    return 0;
}

 

exit(0):正常运行程序并退出程序;

exit(1):非正常运行导致退出程序;

return():返回函数,若在主函数中,则会退出函数并返回一值。

详细说:

1. return返回函数值,是关键字; exit 是一个函数。

2. return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。
3. return是函数的退出(返回);exit是进程的退出。

4. return是C语言提供的,exit是操作系统提供的(或者函数库中给出的)。exit是一个库函数,exit(1)表示发生错误后退出程序,exit(0)表示正常退出。在stdlib.h中exit函数是这样子定义的:void exit(int status)。这个系统调用是用来终止一个进程的,无论在程序中的什么位置,只要执行exit,进程就会从终止进程的运行。讲到exit这个系统调用,就要提及另外一个系统调用,_exit,_exit()函数位于unistd.h中,相比于exit(),_exit()函数的功能最为简单,直接终止进程的运行,释放其所使用的内存空间,并销毁在内存中的数据结构,而exit()在于在进程退出之前要检查文件的状态,将文件缓冲区中的内容写回文件。

5. return用于结束一个函数的执行,将函数的执行信息传出给其他调用函数使用;exit函数是退出应用程序,删除进程使用的内存空间,并将应用程序的一个状态返回给OS或其父进程,这个状态标识了应用程序的一些运行信息,这个信息和机器和操作系统有关,一般是 0 为正常退出, 非0 为非正常退出。

6. 非主函数中调用return和exit效果很明显,但是在main函数中调用return和exit的现象就很模糊,多数情况下现象都是一致的。

算法之美--2.2 Array