詳解如何利用C++實(shí)現(xiàn)Mystring類
功能實(shí)現(xiàn)
<基本功能>
1> 實(shí)現(xiàn)頭文件的封裝:MyString.h
2> 缺省構(gòu)造函數(shù)對(duì)字符串的初始化( MyString() )
3> 使用構(gòu)造函數(shù)初始化字符串的另外兩種方式 * 2( 動(dòng)態(tài)指針+拷貝構(gòu)造函數(shù) )
4> 析構(gòu)函數(shù)( 釋放動(dòng)態(tài)申請(qǐng)的字符串空間 )
5> 重載輸出運(yùn)算符( << )
6> 重載賦值運(yùn)算符 * 2( = )
7> 重載下標(biāo)運(yùn)算符( [],索引輸出 )
<拓展功能>
1> 字符串長(zhǎng)度的比較
2> 字符串的排序功能
3> 字符串的倒置
4> 字符串中指定兩個(gè)字符的交換
5> 查找某字符串是否位于指定的字符串中(采用暴力查找)
<細(xì)節(jié)修改>
1> 使用自定義函數(shù)來替換strlen()和strcpy()
一: 基本功能 (實(shí)現(xiàn)源碼)
1) MyString.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h> //會(huì)借用strlen與strcpy函數(shù)實(shí)現(xiàn)相應(yīng)的功能
using namespace std;
class MyString {
public:
MyString();
MyString(const char *const);
MyString(const MyString &);
~MyString();
int length()const; //const函數(shù)不能修改其數(shù)據(jù)成員,僅僅起到輸出數(shù)據(jù)的作用
int size() const; //和length功能一致
const char * getString() const; //直接調(diào)用字符串首指針返回
friend ostream & operator << (ostream &, const MyString &); //重載輸出運(yùn)算符
MyString & operator = (const MyString &);
MyString & operator = (const char * );
char & operator [] (const int index);
private:
char * str; //指向數(shù)組首地址(此時(shí)為野指針)
int len;
};
2)MyString.cpp
#include "MyString.h"
using namespace std;
MyString::MyString() //構(gòu)造空字符串
{
str = new char[1];
str[0] = '\0';
len = 0;
}
MyString::MyString(const char * const P) //按照動(dòng)態(tài)指針來構(gòu)造相應(yīng)的字符串
{
if (P)
{
len = strlen(P); //取長(zhǎng)度
str = new char[len + 1]; //開空間
strcpy(str, P); //復(fù)制值
}
else
{
MyString(); //如果傳入的字符串為空,直接調(diào)用缺省值構(gòu)造函數(shù)
}
}
MyString::MyString(const MyString & AnotherMyString) //拷貝構(gòu)造函數(shù),這里的形參使用了const,該形參類中的所有函數(shù)都要使用const來修飾
{
len = AnotherMyString.length();
str = new char[len + 1];
strcpy(str, AnotherMyString.str);
}
int MyString::length() const //求長(zhǎng)度成員函數(shù)
{
return len;
}
int MyString::size() const
{
return len;
}
const char * MyString::getString()const
{
return str;
}
MyString & MyString::operator=(const MyString &AnotherMyString)
{
if (&AnotherMyString == this)
{
return *this;
}
delete[] str;
len = AnotherMyString.length();
str = new char[len + 1];
strcpy(str, AnotherMyString.str);
return *this;
// TODO: 在此處插入 return 語(yǔ)句
}
MyString & MyString::operator=(const char * P)
{
delete[] str;
len = strlen(P);
str = new char[len + 1];
strcpy(str, P);
return *this;
// TODO: 在此處插入 return 語(yǔ)句
}
char & MyString::operator[](const int index)
{
if (index > len) //如果索引越界,輸出最后一個(gè)字符
{
cout << "Warning!!!" << endl;
cout << "Out of boundary! The last char is: ";
return str[len - 1];
}
else
{
return str[index-1];
}
// TODO: 在此處插入 return 語(yǔ)句
}
MyString::~MyString() //釋放數(shù)組空間
{
delete[] str;
len = 0;
}
ostream & operator << (ostream & output, const MyString & str) //重載輸出運(yùn)算符
{
output << str.getString();
return output;
// TODO: 在此處插入 return 語(yǔ)句
}
這里需要提到的一點(diǎn)是析構(gòu)函數(shù)中的delete[] str;

<delete[]與delete的區(qū)別>
使用new得來的空間使用delete釋放;使用new[]得來的空間使用delete[]釋放;這是永遠(yuǎn)不會(huì)錯(cuò)的。
但是更加深入一點(diǎn)去理解:
使用new[]得到的空間如果 動(dòng)態(tài)申請(qǐng)的數(shù)據(jù)類型時(shí)基本數(shù)據(jù)類型也可以使用delete直接釋放,但是如果使用new[]申請(qǐng)的數(shù)據(jù)的類型時(shí)自定義類型(例如類名),這就必須使用delete[]來進(jìn)行釋放,只有這樣才能夠調(diào)用自定義類型的析構(gòu)函數(shù)進(jìn)行對(duì)自定義類型進(jìn)行釋放。
除此之外,再提一點(diǎn)關(guān)于delete[]的注意事項(xiàng):
當(dāng)使用new[]動(dòng)態(tài)生成內(nèi)存的時(shí)候,刪除的時(shí)候必須將刪除的指針指向new[]出來的內(nèi)存的首地址:
#include <iostream>
using namespace std;
int main()
{
int *p = new int[3];
*p = 1;
p++;
*p = 2;
delete[]p;
cout << "*" << endl;
return 0;
}
這一段小程序中:
因?yàn)閜指針不是指向了首地址,所以程序雖然沒報(bào)錯(cuò),但是無法正常運(yùn)行!我們可以將申請(qǐng)的首地址保存起來,供刪除的時(shí)候使用。
3)test_main.cpp
#include "MyString.h"
using namespace std;
int main()
{
MyString a;
cout << "【調(diào)用缺省構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string a = " << a << endl;
cout << "Length = " << a.length() << endl << endl;
MyString b("123456");
cout << "【調(diào)用普通構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string b = " << b << endl;
cout << "Length = " << b.length() << endl << endl;
MyString c(b);
cout << "【調(diào)用拷貝構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string c = " << c << endl;
cout << "Length = " << c.length() << endl << endl;
MyString d = b; //這里不會(huì)再次調(diào)用缺省構(gòu)造函數(shù)進(jìn)行初始化
cout << "【調(diào)用 =(對(duì)象) 實(shí)現(xiàn)賦值】" << endl;
cout << "string d = " << d << endl;
cout << "Length = " << d.length() << endl << endl;
MyString e = "00000000";
cout << "【調(diào)用 =(動(dòng)態(tài)指針) 實(shí)現(xiàn)賦值】" << endl;
cout << "string d = " << e << endl;
cout << "Length = " << e.length() << endl << endl;
MyString f = "abcdefghijklmn";
char str = f[5];
cout << "【調(diào)用 [] 實(shí)現(xiàn)索引定位輸出】" << endl;
cout << "f[5] = " << str << endl << endl;
return 0;
}
二:拓展功能
字符串長(zhǎng)度的比較
使用</>/>=/<=等符號(hào)進(jìn)行比較,返回bool值
- bool operator >(const MyString &str);
- bool operator >(const char * c_str);
- bool operator <(const MyString &str);
- bool operator <(const char * c_str);
- bool operator >=(const MyString &str);
- bool operator >=(const char * c_str);
- bool operator <=(const MyString &str);
- bool operator <=(const char * c_str);
字符串的排序功能
使用類中的成員函數(shù)對(duì)類中的私有字符串進(jìn)行從小到大的排序:
- A.Sort_String_LB();
- A.Sort_String_BL();
字符串的倒置
使用類中的成員函數(shù)對(duì)類中的私有字符串進(jìn)行倒置:
A.Reverse();
字符串中指定兩個(gè)字符的交換
A.ChangeTwoCharPosition(int firstposition,int second position);
查找某字符串是否位于指定的字符串中(采用暴力查找)
A.Find(char *search_string);
完整版源碼
MyString.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h> //會(huì)借用strlen與strcpy函數(shù)實(shí)現(xiàn)相應(yīng)的功能
using namespace std;
class MyString {
public:
//構(gòu)造函數(shù)+析構(gòu)函數(shù)
MyString();
MyString(const char *const);
MyString(const MyString &);
~MyString();
//直接調(diào)用字符串首指針返回,返回的指針可以直接使用cout<<輸出
const char * getString() const;
//求字符串的長(zhǎng)度(直接返回類中的私有成員len的值)
//const函數(shù)不能修改其數(shù)據(jù)成員,僅僅起到輸出數(shù)據(jù)的作用
int length()const;
int size() const;
//重載賦值運(yùn)算符,使得可以使用對(duì)象與"xxxxxx"來賦值
MyString & operator = (const MyString &);
MyString & operator = (const char * );
//重載下標(biāo)運(yùn)算符
char & operator [] (const int index);
//重載輸出運(yùn)算符
friend ostream & operator << (ostream &, const MyString &);
//字符串長(zhǎng)度比較
bool operator >(const MyString &str);
bool operator >(const char * c_str);
bool operator <(const MyString &str);
bool operator <(const char * c_str);
bool operator >=(const MyString &str);
bool operator >=(const char * c_str);
bool operator <=(const MyString &str);
bool operator <=(const char * c_str);
//字符串內(nèi)部?jī)?nèi)容的冒泡排序(ASCII碼),Little->Big
void Sort_String_LB();
void Sort_String_BL();
//對(duì)字符串進(jìn)行倒置
void Reverse();
//交換字符串中兩個(gè)字符的位置
void ChangeTwoCharPosition(int firstposition, int secondposition);
//查詢某字符串是否是指定字符串的子串(暴力模式)
bool Find(char *search_string);
private:
char * str; //指向數(shù)組首地址(此時(shí)為野指針)
int len; //字符串的長(zhǎng)度
};
MyString.cpp
#include "MyString.h"
using namespace std;
MyString::MyString() //構(gòu)造空字符串
{
str = new char[1];
str[0] = '\0';
len = 0;
}
MyString::MyString(const char * const P) //按照動(dòng)態(tài)指針來構(gòu)造相應(yīng)的字符串
{
if (P)
{
len = strlen(P); //取長(zhǎng)度
str = new char[len + 1]; //開空間
strcpy(str, P); //復(fù)制值
}
else
{
MyString(); //如果傳入的字符串為空,直接調(diào)用缺省值構(gòu)造函數(shù)
}
}
MyString::MyString(const MyString & AnotherMyString) //拷貝構(gòu)造函數(shù),這里的形參使用了const,該形參類中的所有函數(shù)都要使用const來修飾
{
len = AnotherMyString.length();
str = new char[len + 1];
strcpy(str, AnotherMyString.str);
}
int MyString::length() const //求長(zhǎng)度成員函數(shù)
{
return len;
}
int MyString::size() const
{
return len;
}
const char * MyString::getString()const
{
return str;
}
MyString & MyString::operator=(const MyString &AnotherMyString)
{
if (&AnotherMyString == this)
{
return *this;
}
//delete[] str;
len = AnotherMyString.length();
str = new char[len + 1];
strcpy(str, AnotherMyString.str);
return *this;
// TODO: 在此處插入 return 語(yǔ)句
}
MyString & MyString::operator=(const char * P)
{
//delete[] str;
len = strlen(P);
str = new char[len + 1];
strcpy(str, P);
return *this;
// TODO: 在此處插入 return 語(yǔ)句
}
char & MyString::operator[](const int index)
{
if (index > len) //如果索引越界,輸出最后一個(gè)字符
{
cout << "Warning!!!" << endl;
cout << "Out of boundary! The last char is: ";
return str[len - 1];
}
else
{
return str[index-1];
}
// TODO: 在此處插入 return 語(yǔ)句
}
bool MyString::operator>(const MyString & str)
{
if (this->len > str.len)
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator>(const char * c_str)
{
if (this->len > int (strlen(c_str)))
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator<(const MyString & str)
{
if (this->len < str.len)
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator<(const char * c_str)
{
if (this->len < int(strlen(c_str)))
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator>=(const MyString & str)
{
if (this->len > str.len)
{
return true;
}
else if (this->len = str.len)
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator>=(const char * c_str)
{
if (this->len > int(strlen(c_str)))
{
return true;
}
else if (this->len = strlen(c_str))
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator<=(const MyString & str)
{
if (this->len < str.len)
{
return true;
}
else if (this->len = str.len)
{
return true;
}
else
{
return false;
}
return false;
}
bool MyString::operator<=(const char * c_str)
{
if (this->len > int (strlen(c_str)))
{
return true;
}
else if (this->len = strlen(c_str))
{
return true;
}
else
{
return false;
}
return false;
}
void MyString::Sort_String_LB()
{
int length = this->len;
char temp_data;
char *c_str = this->str;
bool ischanged = false;
for (int i = length-1; i > 0; i--)
{
for (int j = 0; j < i; j++)
{
if (c_str[j] > c_str[j + 1])
{
temp_data = c_str[j];
c_str[j] = c_str[j + 1];
c_str[j + 1] = temp_data;
ischanged = true;
}
}
if (!ischanged)
{
return;
}
}
}
void MyString::Sort_String_BL()
{
int length = this->len;
char temp_data;
char *c_str = this->str;
bool ischanged = false;
for (int i = length - 1; i > 0; i--)
{
for (int j = 0; j < i; j++)
{
if (c_str[j] < c_str[j + 1])
{
temp_data = c_str[j];
c_str[j] = c_str[j + 1];
c_str[j + 1] = temp_data;
ischanged = true;
}
}
if (!ischanged)
{
return;
}
}
}
void MyString::Reverse()
{
int length = this->len;
char *c_str = this->str;
char temp_data;
for (int i = 0; i < length/2; i++)
{
temp_data = c_str[i];
c_str[i] = c_str[length-1-i];
c_str[length-1-i] = temp_data;
}
}
void MyString::ChangeTwoCharPosition(int firstposition, int secondposition)
{
int length = this->len;
char *c_str = this->str;
char temp_data;
if (firstposition > len || secondposition > len)
{
cout << "輸入下標(biāo)越界,數(shù)組實(shí)際長(zhǎng)度為: " << length << endl;
return;
}
else
{
temp_data = c_str[firstposition-1];
c_str[firstposition-1] = c_str[secondposition-1];
c_str[secondposition-1] = temp_data;
}
}
bool MyString::Find(char * search_string)
{
int length = this->len;
char *c_str = this->str;
bool judge = false;
//確保i每次可以往后移動(dòng)一位
int temp_data=0;
for (int i = 0,j=0; j < strlen(search_string)&&i<length; )
{
if (c_str[i] == search_string[j])
{
//cout << c_str[i] << "==" << search_string[j] << endl;
//cout << i << "::" << j << endl;
judge = true;
i++;
j++;
}
else
{
judge = false;
temp_data++;
i = temp_data;
j = 0;
}
}
return judge;
}
MyString::~MyString() //釋放數(shù)組空間
{
delete[] str;
len = 0;
}
ostream & operator << (ostream & output, const MyString & str) //重載輸出運(yùn)算符
{
output << str.getString();
return output;
// TODO: 在此處插入 return 語(yǔ)句
}
Test_Possess.cpp
#include "MyString.h"
using namespace std;
int main()
{
MyString a;
cout << "【調(diào)用缺省構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string a = " << a << endl;
cout << "Length = " << a.length() << endl << endl;
MyString b("123456");
cout << "【調(diào)用普通構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string b = " << b << endl;
cout << "Length = " << b.length() << endl << endl;
MyString c(b);
cout << "【調(diào)用拷貝構(gòu)造函數(shù)實(shí)現(xiàn)初始化】" << endl;
cout << "string c = " << c << endl;
cout << "Length = " << c.length() << endl << endl;
MyString d = b; //這里不會(huì)再次調(diào)用缺省構(gòu)造函數(shù)進(jìn)行初始化
cout << "【調(diào)用 =(對(duì)象) 實(shí)現(xiàn)賦值】" << endl;
cout << "string d = " << d << endl;
cout << "Length = " << d.length() << endl << endl;
MyString e = "00000000";
cout << "【調(diào)用 =(動(dòng)態(tài)指針) 實(shí)現(xiàn)賦值】" << endl;
cout << "string d = " << e << endl;
cout << "Length = " << e.length() << endl << endl;
MyString f = "abcdefghijklmn";
char str = f[5];
cout << "【調(diào)用 [] 實(shí)現(xiàn)索引定位輸出】" << endl;
cout << "f[5] = " << str << endl << endl;
//測(cè)試字符串的大小比較功能
MyString A1 = "123456789";
MyString B1 = "4321";
MyString C1 = "456";
MyString D1 = "456789";
if (A1 >= B1)
{
cout << "A1>=B1" << endl;
}
else
{
cout << "A1<B1" << endl;
}
//測(cè)試字符串的排序功能
B1.Sort_String_LB();
cout << B1 << endl;
//測(cè)試字符串的倒置功能
A1.Reverse();
cout << A1 << endl;
//測(cè)試指定兩個(gè)字符的交換
A1.ChangeTwoCharPosition(1, 9);
cout << A1 << endl;
//判斷某字符串是否為指定字符串的子串
if (D1.Find("678"))
{
cout << "Successful!" << endl;
}
else
{
cout << "Fail!" << endl;
}
return 0;
}
三:細(xì)節(jié)部分修改
本次更新了 "取消了strlen()與strcpy()的使用,在間接調(diào)用該接口的自定義函數(shù)中,使用自定義方法實(shí)現(xiàn)這兩個(gè)接口的功能"
這里僅僅給出了替換部分部分示例,其他部分也可按照相同原理替換:
1.使用指針實(shí)例化對(duì)象部分
MyString::MyString(char * P) //按照動(dòng)態(tài)指針來構(gòu)造相應(yīng)的字符串
{
char * temp_P = P; //使得指針指向的內(nèi)存重置
if (P)
{
int xx_length = 0;
while (*P != '\0')
{
xx_length++;
P = P + sizeof(char);
}
len = xx_length;
P = temp_P;
//len = strlen(P); //取長(zhǎng)度
str = new char[len + 1]; //開空間
strcpy(str, P); //復(fù)制值
}
else
{
MyString(); //如果傳入的字符串為空,直接調(diào)用缺省值構(gòu)造函數(shù)
}
}
2.重載 "=" 運(yùn)算符函數(shù)的過程
MyString & MyString::operator=(char * P)
{
//delete[] str;
char *temp_P = P;
int xx_length = 0;
char temp = '0';
while (*P != '\0')
{
xx_length++;
P = P + sizeof(char);
}
//len = strlen(P);
len = xx_length;
P = temp_P;
str = new char[len + 1];
for (int i = 0; i < len; i++)
{
*str = *P;
str += sizeof(char);
P += sizeof(char);
}
//strcpy(str, P);
return *this;
// TODO: 在此處插入 return 語(yǔ)句
}( 附加:對(duì)于自定義的類,需要盡量減少對(duì)其他頭文件的需求。)
到此這篇關(guān)于詳解如何利用C++實(shí)現(xiàn)Mystring類的文章就介紹到這了,更多相關(guān)C++ Mystring類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)簡(jiǎn)單學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
C語(yǔ)言中分支和循環(huán)的6種實(shí)現(xiàn)形式總結(jié)
C語(yǔ)言時(shí)一門結(jié)構(gòu)化的程序設(shè)計(jì)語(yǔ)言,這篇文章主要介紹了C語(yǔ)言中的分支和循環(huán)的6種實(shí)現(xiàn)形式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04
C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)中求解迷宮問題實(shí)現(xiàn)方法
這篇文章主要介紹了C語(yǔ)言 數(shù)據(jù)結(jié)構(gòu)中求解迷宮問題實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2017-03-03
純C語(yǔ)言實(shí)現(xiàn)火車售票系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了純C語(yǔ)言實(shí)現(xiàn)火車售票系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
c#中實(shí)現(xiàn)退出程序后自動(dòng)重新啟動(dòng)程序的方法
下面小編就為大家?guī)硪黄猚#中實(shí)現(xiàn)退出程序后自動(dòng)重新啟動(dòng)程序的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01

