之前那篇,函数也有些小问题,比如只判断了是否为空,如果传入的就是空字符串的情况呢?并且length成员变量也没怎么试用
并且这次的代码加入了C++语法中拷贝构造和拷贝赋值函数的代码实现
#include <stdio.h>
#include <stdlib.h>#include <iostream>
using namespace std;
#pragma warning(disable:4996)
#pragma warning(once:4996)
class String
{
public:
String(void);
~String(void);
String(char* str);
String(const String& str); //拷贝构造
const String& operator= (const String& str); //拷贝赋值
void output();
bool PushBack(char* str);
private:
char* data;
int length;
int count;
};
String::String(void)
{
count = 0;
length = 0;
data = NULL;
}
String::~String(void)
{
if (NULL != data)
{
delete data;
data = NULL;
}
}
String::String(char* str)
{
String();
int len = strlen(str); //避免了每次使用str长度都要调用strlen函数,用空间来换取时间
//在这里加入了一个如果就是一个空字符串情况的判断以及处理
if ((NULL == str) || (0 == len)){
return;
}
count = len + 1;
count = count * 2; //这里用现有容量的二倍作为申请空间大小,避免了每次都要申请空间
data = new char[count];
if (NULL == data)
{
count = 0;
return;
}
strncpy(data, str, len);
length = len;
data[length] = '\0'; //字符串数组的下标从0开始,所以len也就是length代表的就是字符串紧跟着的位置
}
//拷贝构造函数的实现
String::String(const String& str)
{
String();
if ((NULL == str.data) || (0 == str.length))
{
return;
}
count = str.length + 1;
count = count * 2;
data = new char[count]; //避免浅拷贝问题
if (NULL == data)
{
count = 0;
return;
}
strncpy(data, str.data, str.length);
length = str.length;
data[length] = '\0';
}
//拷贝赋值的实现
const String& String::operator= (const String& str)
{
//避免自拷贝
if (this == &str){
return *this;
}
//如果内容为空的情况
if ((NULL == str.data) || (0 == str.length))
{
return *this;
}
int size = count; //size保存旧容量
count = str.length + 1;
count = count * 2;
char* tmp = new char[count]; //申请新内存
if (NULL == tmp)
{
count = size; //申请失败情况下,容量大小复位
return *this;
}
strncpy(tmp, str.data, str.length);
length = str.length;
tmp[length] = '\0';
if (NULL != data)
{
delete data; //释放旧内存
}
data = tmp; //指向新内存
return *this;
}
void String::output()
{
if ((NULL == data) || (0 == strlen(data)))
{
return;
}
printf("%s\n", data);
}
bool String::PushBack(char* str)
{
int len = strlen(str);
if ((NULL == str) || (0 == len))
{
return false;
}
int left = count - length - 1; //count剩余大小,1代表'\0'
int size = count;
//剩余内存足够情况下,直接在这个内存中存入新字符串
if (left >= len)
{
strncpy(data+strlen(data), str, len);
length += len;
data[length] = '\0';
return true;
}
//此时是剩余内存不够的情况,就需要重新计算拼接后所需的大小,并重新申请空间
count += len;
count = count * 2;
char* tmp = new char[count];
if (NULL == tmp)
{
count = size; //申请失败,复位
return false;
}
strncpy(tmp, data, strlen(data));
strncpy(tmp + strlen(data), str, len);
length = strlen(tmp);
tmp[length] = '\0';
if (NULL != data)
{
delete data; //释放旧内存
}
data = tmp; //指向新内存
return true;
}
int main()
{
String str("hello");
str.output(); // hello
str.PushBack("world");
str.output(); // helloworld
str.PushBack("");
str.output(); //helloworld
String str1(str); //调用拷贝构造函数
str1.output(); //helloworld
str1.PushBack("o");
str1.output(); //helloworldo
String str2;
str2 = str1; //拷贝赋值
str2.output(); //helloworldo
str2.PushBack("1");
str2.output(); //helloworldo1
return 0;
}