C++ | 湖北工业大学期末试卷

 一、

以下String类的友员函数完成C串与String串的“+”运算,将程序补充完整。

String operator+ (const char* c, const String& s){

        String w;

        int len =       ;

        delete []w.str;

        w.str =       ;

        if(w.str == NULL) s.error("overflow");

              ;

      ;

        w.size = len;

             ;}

①strlen(c) + s.size;

②new char[len +1];

③strcpy(w.str, c);

④strcat(w.str, s.str);

⑤return w; 

对于为什么String s不能使用strlen()来计算大小:

String s是一个String类的对象,它拥有一个私有成员变量size来表示字符串的长度。在构造String对象时,已经将字符串的长度保存在size变量中,不需要再使用strlen()来计算长度。

在以上的代码中,已经通过s.size获取了String对象s的长度,因此不需要再使用strlen()去计算c字符串的长度。直接使用s.size即可得到两个字符串连接后的总长度。这样可以避免重复计算,提高代码的效率。

 

char *c可以使用strlen()来计算长度

是因为c是一个字符串字面量(即由双引号包围的字符序列)。在C/C++中,字符串字面量被视为以空字符(\0)结尾的字符数组,因此可以使用strlen()来计算其长度,即不包括空字符在内的字符数。

在以上代码中,通过strlen(c)可以得到字符串字面量c的长度,然后与String对象s的size相加,得到连接后的字符串的总长度。这样可以动态地分配足够的内存空间来存储连接后的字符串。

 需要注意的是

在连接字符串的过程中,需要先删除之前分配的内存空间(delete []w.str),然后再动态分配新的内存空间(new char[len+1]),以确保可以存储连接后的字符串。同时还需要检查内存是否分配成功,如果内存分配失败,则使用error()函数进行相应的处理。最后,使用strcpy()函数将c字符串复制到w.str中,然后使用strcat()函数将s.str拼接到w.str的末尾,最后更新w的size,包装成String对象并返回。 

字符串函数

字符串函数:strlen函数,strcpy函数,strcat函数,strcmp函数_双鱼211的博客-CSDN博客 

二、实现Vector的成员函数

#ifndef VECTOR_H
#define VECTOR_H
#include <stdlib.h>

template<class T>
class Vector
{
private:
	T *data;						//指向动态数组指针
	int size;						//数组的数据元素个数
	int max;						//数组容量
	void Error(const char* cs)const { cout << cs << endl; exit(1); }//错误信息报告
public:
	enum { SPARE_MAX = 16 };				//枚举常量表示数组最小长度
	explicit Vector(int n = 0) :size(0), max(n + SPARE_MAX)
	{
		if (max > 0) data = new T[max];
	}
	Vector(const Vector& v) :data(NULL), max(0) { operator=(v); }//复制构造函数
	~Vector() { delete[]data; }
	Vector& operator=(const Vector<T>& v);		//复制赋值函数
	T& operator[](int id) { return data[id]; }		//下标运算符函数
	const T& operator[](int id)const { return data[id]; }//常量型下标运算符函数
	bool Empty()const { return size == 0; }			//判空
	bool isFull() const { return size == max; } //判满
	int Size()const { return size; }				//求数据个数
	int Max()const { return max; }					//求数组容量
	void Clear() { size = 0; }						//清空。删除所有数据元素
    //迭代器类型
	typedef T* iterator;						//迭代器
	typedef const T* const_iterator;			//指向const常量的迭代器

	iterator Begin() { return data; }				//使迭代器指向容器起始位置
	const_iterator Begin()const { return data; }
	iterator End() { return data + size; }			//使迭代器指向容器最后一个数据元素的后继
	const_iterator End()const { return data + size; }

	const T& Front()const { return data[0]; }		//返回首元素的引用(可以返回*begin())
	T& Front() { return data[0]; }
	const T& Back()const { return data[size - 1]; }	//返回尾元素的引用(不能返回*--end())
	T& Back() { return data[size - 1]; }
	void Push_back(const T& item);              //尾插
	void Pop_back() { size--; }					//尾删
	void Reserve(int newMax);					//扩大数组容量为newmax,保留原来数据
	void Resize(int newSize, const T& item = T());	//把数据个数增加为newsize,保留原来的数据,其余的值为item
	iterator Insert(iterator itr, const T& item);
	iterator Erase(iterator itr);

	iterator Erase(iterator first, iterator last); //删除[first,last)区间的数据,返回当前数据的位置。
	void Insert(iterator pos, iterator first, iterator last);//在pos处插入另一个Vector容器指定区间[first, last)的数据
	void Swap(Vector<T>& v); //交换两个Vector中的数据。
};

template<class T>

Vector<T>& Vector<T>::operator=(const Vector<T>& v)//复制赋值函数

{

       if (max != v.Max())

       {

              delete[]data;

              max = v.max;

              data = new T[max];

       }

       size = v.Size();

       for (int i = 0; i < size; i++)

              data[i] = v.data[i];

       return *this;

}

template<class T>                           //模板参数表

typename Vector<T>::iterator                      //返回值类型

Vector<T>::Erase(iterator itr)  //删除指示器指向的元素

{

       for (iterator p = itr, q = itr + 1; q != data + size; ++p, ++q)

              *p = *q;

       size--;

       return itr;

}

 


 

template<class T>      //

把元素item插入到迭代器itr的位置

typename Vector<T>::iterator Vector<T>::Insert(iterator itr, const T& item)

{

/*******************请在此处写出成员函数的定义***********************/

    
    if(size==max)
{
      int n = itr-Begin();
  Reserve(2*max+1);
      itr = Begin() + n;
}
for(iterator p = data +size,q = data+size-1;p!=itr;--p,--q)
{
  *p=*q;
}
*itr = item;
size++;
return itr;

  /***********************************************************************/

}

 

 这三行代码什么意思:int n = itr - Begin(); Reserve(2 * max + 1); itr = Begin() + n;

  1. int n = itr - Begin();:计算迭代器itr相对于Begin()的偏移量,并将结果赋值给整型变量n。这里假设Begin()是一个返回容器起始位置迭代器的函数。

  2. Reserve(2 * max + 1);:调用Reserve函数,将容量扩展为当前容量的两倍加1。这个函数用来确保容器有足够的空间来存储新增的元素。

  3. itr = Begin() + n;:根据之前计算得到的偏移量n,通过Begin()函数获取容器起始位置迭代器,然后将其与偏移量相加,更新迭代器itr的值。这样做的目的是保证插入位置不会受到扩容操作的影响,始终指向插入前的位置。

 

上述代码返回值类型为什么是int:int n = itr - Begin(); 

对于 int n = itr - Begin(); 这行代码,返回值类型是 int

itr - Begin() 返回的是两个迭代器之间的距离,而且针对指针迭代器,其结果类型是一个整数。

在这种情况下,itr 是一个指向容器中的元素的迭代器,Begin()是指向容器起始位置的迭代器,所以 itr - Begin() 的结果会返回两个迭代器之间的元素个数或距离,对于指针迭代器来说,结果是一个整数。

因此,int n = itr - Begin(); 将会把 itr 和 Begin() 之间的距离赋值给 n,所以返回值类型是 int

代码原来data+size位置的元素是不是被覆盖了 

是的,代码中将插入位置之后的元素向后移动一位来腾出空间,并将要插入的元素赋值给插入位置。这样做会覆盖原来data+size位置的元素。具体来说:

  1. 首先,使用两个迭代器pq分别指向数据的末尾和末尾前一个位置(即data+sizedata+size-1)。

  2. 接着,使用循环从后向前遍历,将q位置上的元素赋值给p位置上的元素,即将元素向后移动一位。

  3. 在循环结束后,让itr位置上的元素等于要插入的元素item,完成插入操作。

  4. 最后,增加size的值,表示容器中元素的数量增加了一个。

因此,原来data+size位置上的元素确实会被覆盖。

图示: 


 

template<class T>

void Vector<T>::Push_back(const T& item)

{

       if (size < max) {

              data[size] = item;

       }

       else {

              T* old = data;

              int len = 2 * max + 1;

              data = new T[len];

              int i = 0;

              for (; i < size; i++) {

                     data[i] = old[i];

              }

              data[i] = item;

              max = len;

              delete[] old;

       }

       size++;                                     //数据个数增1

}

 

template<class T>

void Vector<T>::Reserve(int newmax)                                          

{

       if(newmax<max)              //如果数组容量已满,则返回

              return;

       T* old=data;              //保留原数组

       data=new T[newmax];             //重新分配新数组            

       for(int i=0;i<size;i++)       //把原数组中的数据复制到新数组

              data[i]=old[i];

       max=newmax;                         //修改数组容量

       delete[]old;                 //释放原数组空间                  

}

 

template<class T>//数据个数增为newsize,原数据保留,增加的数据元素初始化为item

void Vector<T>::Resize(int newsize,const T& item)                           

{

       if(newsize>max)                             //如果数据元素个数大于数组容量

              Reserve(newsize*2+1);           //扩大数组容量

       for(int i=size;i<newsize;i++)   //把增加的数据元素初始化为item

              data[i]=item;

       size=newsize;

}


        iterator Erase(iterator first, iterator last); //删除[first,last)区间的数据,返回当前数据的位置。

template<class T>

typename Vector<T>::iterator Vector<T>::Erase(iterator first, iterator last)

{

/*******************请在此处写出成员函数的定义*********************/

 While(first!=last)

{

Erase(first);

last--

}

return last;

    /******************************************************************/

}

 

 

template<class T>

void Vector<T>::Insert(iterator pos, iterator first, iterator last)

{

/*******************请在此处写出成员函数的定义*********************/

   

for(iterator it=first;it!=last;++it)

{

  pos=Insert(pos,*it);

 pos++;

}

    /******************************************************************/

}

 

template<class T>

void Vector<T>::Swap(Vector<T>& v)

{

       Vector<T> temp = v;

       v = *this;

       *this = temp;

}

 

 测试代码

#include<iostream>

#include"Vector.h"

using namespace std;

template<class Iterator>   //在指定范围内输出元素

void display_vector(Iterator first, Iterator last)

{

       for (; first != last; ++first)

              cout << *first << '\t';

       cout << endl;

}

int main() 

{

      

       Vector<int> V1;

      

       for(int i=0;i<10;i++)

       {

              V1.Push_back(i);

       }

       cout << "original V1:\t";

       display_vector(V1.Begin(), V1.End());

      

       Vector<int> V2;                                           

       for (int i = 0; i < 10; i++)

       {

              V2.Push_back(i * 2 + 1);

       }

       cout << " original V2:\t ";

       display_vector(V2.Begin(), V2.End());

//  不是 V1.XX ,直接函数用

       V1.Swap(V2);

       cout << "After swap, V1:";

       display_vector(V1.Begin(), V1.End());

       cout << "V2: ";

       display_vector(V2.Begin(), V2.End());

       Vector<int>::iterator itr = V1.Begin()+ 3;

       V1.Insert(itr, V2.Begin(), V2.End());

       cout << "After insert v2 into v1:\n";

       display_vector(V1.Begin(), V1.End());

       V1.Erase(V1.Begin(), V1.Begin() + 5);

// 删除[V1.Begin(),V1.Begin+5)

       cout << "After erase 5 elements, v1:\n";

       display_vector(V1.Begin(), V1.End());

       return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值