九、实现函数和类
9.1 char *strcpy(char *dst, const char *src);
http://blog.csdn.net/yangquanhui1991/article/details/51804600
char *strcpy(char *dst, const char *src);
返回dst的原始值使函数能够支持链式表达式:strlen(strcpy(strA,strB)); 假如考虑dst和src内存重叠的情况,strcpy该怎么实现 char s[10]="hello"; strcpy(s, s+1); //应返回ello, strcpy(s+1, s);
//应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了
//
//C语言标准库函数strcpy的一种典型的工业级的最简实现。
//返回值:目标串的地址。
//对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。
//参数:des为目标字符串,source为原字符串。
char* strcpy(char* des,const char* source)
{
char* r=des;
assert((des != NULL) && (source != NULL));
while((*r++ = *source++)!='\0');
return des;
}
//while((*des++=*source++));的解释:赋值表达式返回左操作数,所以在赋值'\0'后,循环停止
9.2 string类
主要的数据成员是 char* data和 int size;
#include <iostream>
#include <cstring>
using namespace std;
class String {
public:
// 默认构造函数
String(const char* str = NULL);
// 复制构造函数
String(const String &str);
// 析构函数
~String();
// 字符串连接
String operator+(const String & str);
// 字符串赋值
String & operator=(const String &str);
// 字符串赋值
String & operator=(const char* str);
// 判断是否字符串相等
bool operator==(const String &str);
// 获取字符串长度
int length();
// 求子字符串[start,start+n-1]
String substr(int start, int n);
// 重载输出
friend ostream & operator<<(ostream &o, const String &str);
private:
char* data;
int size;
};
// 构造函数
String::String(const char *str) {
if (str == NULL) {
data = new char[1];
data[0] = '\0';
size = 0;
}//if
else {
size = strlen(str);
data = new char[size + 1];
strcpy(data, str);
}//else
}
// 复制构造函数
String::String(const String &str) {
size = str.size;
data = new char[size + 1];
strcpy(data, str.data);
}
// 析构函数
String::~String() {
delete[] data;
}
// 字符串连接
String String::operator+(const String &str) {
String newStr;
//释放原有空间
delete[] newStr.data;
newStr.size = size + str.size;
newStr.data = new char[newStr.size + 1];
strcpy(newStr.data, data);
strcpy(newStr.data + size, str.data);
return newStr;
}
// 字符串赋值
String & String::operator=(const String &str) {
if (data == str.data) { // 注意要先判断是否是自己给自己赋值
return *this;
}//if
delete[] data;
size = str.size;
data = new char[size + 1];
strcpy(data, str.data);
return *this;
}
// 字符串赋值
String& String::operator=(const char* str) {
if (data == str) {
return *this;
}//if
delete[] data;
size = strlen(str);
data = new char[size + 1];
strcpy(data, str);
return *this;
}
// 判断是否字符串相等
bool String::operator==(const String &str) {
return strcmp(data, str.data) == 0;
}
// 获取字符串长度
int String::length() {
return size;
}
// 求子字符串[start,start+n-1]
String String::substr(int start, int n) {
String newStr;
// 释放原有内存
delete[] newStr.data;
// 重新申请内存
newStr.data = new char[n + 1];
for (int i = 0; i < n; ++i) {
newStr.data[i] = data[start + i];
}//for
newStr.data[n] = '\0';
newStr.size = n;
return newStr;
}
// 重载输出
ostream & operator<<(ostream &o, const String &str) {
o << str.data;
return o;
}
int main() {
String str1("hello ");
String str2 = "world";
String str3 = str1 + str2;
cout << "str1->" << str1 << " size->" << str1.length() << endl;
cout << "str2->" << str2 << " size->" << str2.length() << endl;
cout << "str3->" << str3 << " size->" << str3.length() << endl;
String str4("helloworld");
if (str3 == str4) {
cout << str3 << " 和 " << str4 << " 是一样的" << endl;
}//if
else {
cout << str3 << " 和 " << str4 << " 是不一样的" << endl;
}
cout << str3.substr(6, 5) << " size->" << str3.substr(6, 5).length() << endl;
return 0;
}
9.3 void* memcpy(void* dst, const void* src, size_t n)
memcpy将源移动n个字节到目标,但是源和目的的内存区域不能重叠,不保证内存覆盖时移动正确
void* my_memcpy(void* dst, const void* src, size_t n)
{
char *tmp = (char*)dst;
char *s_src = (char*)src;
while(n--) {
*tmp++ = *s_src++;
}
return dst;
}
9.4 void* memmove(void* dst, const void* src, size_t n)
memmove保证内存覆盖时移动正确
void* my_memmove(void* dst, const void* src, size_t n)
{
char* s_dst;
char* s_src;
s_dst = (char*)dst;
s_src = (char*)src;
if(s_dst>s_src && (s_src+n>s_dst)) { //-------------------------第二种内存覆盖的情形。
s_dst = s_dst+n-1;
s_src = s_src+n-1;
while(n--) {
*s_dst-- = *s_src--;
}
}else {
while(n--) {
*s_dst++ = *s_src++;
}
}
return dst;
}