您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么利用C++實現Mystring類”,在日常操作中,相信很多人在怎么利用C++實現Mystring類問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么利用C++實現Mystring類”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
<基本功能>
1> 實現頭文件的封裝:MyString.h
2> 缺省構造函數對字符串的初始化( MyString() )
3> 使用構造函數初始化字符串的另外兩種方式 * 2( 動態指針+拷貝構造函數 )
4> 析構函數( 釋放動態申請的字符串空間 )
5> 重載輸出運算符( << )
6> 重載賦值運算符 * 2( = )
7> 重載下標運算符( [],索引輸出 )
<拓展功能>
1> 字符串長度的比較
2> 字符串的排序功能
3> 字符串的倒置
4> 字符串中指定兩個字符的交換
5> 查找某字符串是否位于指定的字符串中(采用暴力查找)
<細節修改>
1> 使用自定義函數來替換strlen()和strcpy()
1) MyString.h
#pragma once #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string.h> //會借用strlen與strcpy函數實現相應的功能 using namespace std; class MyString { public: MyString(); MyString(const char *const); MyString(const MyString &); ~MyString(); int length()const; //const函數不能修改其數據成員,僅僅起到輸出數據的作用 int size() const; //和length功能一致 const char * getString() const; //直接調用字符串首指針返回 friend ostream & operator << (ostream &, const MyString &); //重載輸出運算符 MyString & operator = (const MyString &); MyString & operator = (const char * ); char & operator [] (const int index); private: char * str; //指向數組首地址(此時為野指針) int len; };
2)MyString.cpp
#include "MyString.h" using namespace std; MyString::MyString() //構造空字符串 { str = new char[1]; str[0] = '\0'; len = 0; } MyString::MyString(const char * const P) //按照動態指針來構造相應的字符串 { if (P) { len = strlen(P); //取長度 str = new char[len + 1]; //開空間 strcpy(str, P); //復制值 } else { MyString(); //如果傳入的字符串為空,直接調用缺省值構造函數 } } MyString::MyString(const MyString & AnotherMyString) //拷貝構造函數,這里的形參使用了const,該形參類中的所有函數都要使用const來修飾 { len = AnotherMyString.length(); str = new char[len + 1]; strcpy(str, AnotherMyString.str); } int MyString::length() const //求長度成員函數 { 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 語句 } MyString & MyString::operator=(const char * P) { delete[] str; len = strlen(P); str = new char[len + 1]; strcpy(str, P); return *this; // TODO: 在此處插入 return 語句 } char & MyString::operator[](const int index) { if (index > len) //如果索引越界,輸出最后一個字符 { cout << "Warning!!!" << endl; cout << "Out of boundary! The last char is: "; return str[len - 1]; } else { return str[index-1]; } // TODO: 在此處插入 return 語句 } MyString::~MyString() //釋放數組空間 { delete[] str; len = 0; } ostream & operator << (ostream & output, const MyString & str) //重載輸出運算符 { output << str.getString(); return output; // TODO: 在此處插入 return 語句 }
這里需要提到的一點是析構函數中的delete[] str;
<delete[]與delete的區別>
使用new得來的空間使用delete釋放;使用new[]得來的空間使用delete[]釋放;這是永遠不會錯的。
但是更加深入一點去理解:
使用new[]得到的空間如果 動態申請的數據類型時基本數據類型也可以使用delete直接釋放,但是如果使用new[]申請的數據的類型時自定義類型(例如類名),這就必須使用delete[]來進行釋放,只有這樣才能夠調用自定義類型的析構函數進行對自定義類型進行釋放。
除此之外,再提一點關于delete[]的注意事項:
當使用new[]動態生成內存的時候,刪除的時候必須將刪除的指針指向new[]出來的內存的首地址:
#include <iostream> using namespace std; int main() { int *p = new int[3]; *p = 1; p++; *p = 2; delete[]p; cout << "*" << endl; return 0; }
這一段小程序中:
因為p指針不是指向了首地址,所以程序雖然沒報錯,但是無法正常運行!我們可以將申請的首地址保存起來,供刪除的時候使用。
3)test_main.cpp
#include "MyString.h" using namespace std; int main() { MyString a; cout << "【調用缺省構造函數實現初始化】" << endl; cout << "string a = " << a << endl; cout << "Length = " << a.length() << endl << endl; MyString b("123456"); cout << "【調用普通構造函數實現初始化】" << endl; cout << "string b = " << b << endl; cout << "Length = " << b.length() << endl << endl; MyString c(b); cout << "【調用拷貝構造函數實現初始化】" << endl; cout << "string c = " << c << endl; cout << "Length = " << c.length() << endl << endl; MyString d = b; //這里不會再次調用缺省構造函數進行初始化 cout << "【調用 =(對象) 實現賦值】" << endl; cout << "string d = " << d << endl; cout << "Length = " << d.length() << endl << endl; MyString e = "00000000"; cout << "【調用 =(動態指針) 實現賦值】" << endl; cout << "string d = " << e << endl; cout << "Length = " << e.length() << endl << endl; MyString f = "abcdefghijklmn"; char str = f[5]; cout << "【調用 [] 實現索引定位輸出】" << endl; cout << "f[5] = " << str << endl << endl; return 0; }
字符串長度的比較
使用</>/>=/<=等符號進行比較,返回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);
字符串的排序功能
使用類中的成員函數對類中的私有字符串進行從小到大的排序:
A.Sort_String_LB();
A.Sort_String_BL();
字符串的倒置
使用類中的成員函數對類中的私有字符串進行倒置:
A.Reverse();
字符串中指定兩個字符的交換
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> //會借用strlen與strcpy函數實現相應的功能 using namespace std; class MyString { public: //構造函數+析構函數 MyString(); MyString(const char *const); MyString(const MyString &); ~MyString(); //直接調用字符串首指針返回,返回的指針可以直接使用cout<<輸出 const char * getString() const; //求字符串的長度(直接返回類中的私有成員len的值) //const函數不能修改其數據成員,僅僅起到輸出數據的作用 int length()const; int size() const; //重載賦值運算符,使得可以使用對象與"xxxxxx"來賦值 MyString & operator = (const MyString &); MyString & operator = (const char * ); //重載下標運算符 char & operator [] (const int index); //重載輸出運算符 friend ostream & operator << (ostream &, const MyString &); //字符串長度比較 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); //字符串內部內容的冒泡排序(ASCII碼),Little->Big void Sort_String_LB(); void Sort_String_BL(); //對字符串進行倒置 void Reverse(); //交換字符串中兩個字符的位置 void ChangeTwoCharPosition(int firstposition, int secondposition); //查詢某字符串是否是指定字符串的子串(暴力模式) bool Find(char *search_string); private: char * str; //指向數組首地址(此時為野指針) int len; //字符串的長度 };
MyString.cpp
#include "MyString.h" using namespace std; MyString::MyString() //構造空字符串 { str = new char[1]; str[0] = '\0'; len = 0; } MyString::MyString(const char * const P) //按照動態指針來構造相應的字符串 { if (P) { len = strlen(P); //取長度 str = new char[len + 1]; //開空間 strcpy(str, P); //復制值 } else { MyString(); //如果傳入的字符串為空,直接調用缺省值構造函數 } } MyString::MyString(const MyString & AnotherMyString) //拷貝構造函數,這里的形參使用了const,該形參類中的所有函數都要使用const來修飾 { len = AnotherMyString.length(); str = new char[len + 1]; strcpy(str, AnotherMyString.str); } int MyString::length() const //求長度成員函數 { 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 語句 } MyString & MyString::operator=(const char * P) { //delete[] str; len = strlen(P); str = new char[len + 1]; strcpy(str, P); return *this; // TODO: 在此處插入 return 語句 } char & MyString::operator[](const int index) { if (index > len) //如果索引越界,輸出最后一個字符 { cout << "Warning!!!" << endl; cout << "Out of boundary! The last char is: "; return str[len - 1]; } else { return str[index-1]; } // TODO: 在此處插入 return 語句 } 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 << "輸入下標越界,數組實際長度為: " << 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每次可以往后移動一位 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() //釋放數組空間 { delete[] str; len = 0; } ostream & operator << (ostream & output, const MyString & str) //重載輸出運算符 { output << str.getString(); return output; // TODO: 在此處插入 return 語句 }
Test_Possess.cpp
#include "MyString.h" using namespace std; int main() { MyString a; cout << "【調用缺省構造函數實現初始化】" << endl; cout << "string a = " << a << endl; cout << "Length = " << a.length() << endl << endl; MyString b("123456"); cout << "【調用普通構造函數實現初始化】" << endl; cout << "string b = " << b << endl; cout << "Length = " << b.length() << endl << endl; MyString c(b); cout << "【調用拷貝構造函數實現初始化】" << endl; cout << "string c = " << c << endl; cout << "Length = " << c.length() << endl << endl; MyString d = b; //這里不會再次調用缺省構造函數進行初始化 cout << "【調用 =(對象) 實現賦值】" << endl; cout << "string d = " << d << endl; cout << "Length = " << d.length() << endl << endl; MyString e = "00000000"; cout << "【調用 =(動態指針) 實現賦值】" << endl; cout << "string d = " << e << endl; cout << "Length = " << e.length() << endl << endl; MyString f = "abcdefghijklmn"; char str = f[5]; cout << "【調用 [] 實現索引定位輸出】" << endl; cout << "f[5] = " << str << endl << endl; //測試字符串的大小比較功能 MyString A1 = "123456789"; MyString B1 = "4321"; MyString C1 = "456"; MyString D1 = "456789"; if (A1 >= B1) { cout << "A1>=B1" << endl; } else { cout << "A1<B1" << endl; } //測試字符串的排序功能 B1.Sort_String_LB(); cout << B1 << endl; //測試字符串的倒置功能 A1.Reverse(); cout << A1 << endl; //測試指定兩個字符的交換 A1.ChangeTwoCharPosition(1, 9); cout << A1 << endl; //判斷某字符串是否為指定字符串的子串 if (D1.Find("678")) { cout << "Successful!" << endl; } else { cout << "Fail!" << endl; } return 0; }
本次更新了 "取消了strlen()與strcpy()的使用,在間接調用該接口的自定義函數中,使用自定義方法實現這兩個接口的功能"
這里僅僅給出了替換部分部分示例,其他部分也可按照相同原理替換:
MyString::MyString(char * P) //按照動態指針來構造相應的字符串 { char * temp_P = P; //使得指針指向的內存重置 if (P) { int xx_length = 0; while (*P != '\0') { xx_length++; P = P + sizeof(char); } len = xx_length; P = temp_P; //len = strlen(P); //取長度 str = new char[len + 1]; //開空間 strcpy(str, P); //復制值 } else { MyString(); //如果傳入的字符串為空,直接調用缺省值構造函數 } }
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 語句 }
( 附加:對于自定義的類,需要盡量減少對其他頭文件的需求。)
到此,關于“怎么利用C++實現Mystring類”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。