【实验5】c++MyString类实现
如何用c语言实现CString的构造函数、析构函数和赋值函数?
如何⽤c语⾔实现CString的构造函数、析构函数和赋值函数?编写类String的构造函数、析构函数和赋值函数已知类String的原型为:class String{public:String(const char*str=NULL);//普通构造函数String(const String&other); //拷贝构造函数~String(void); //构析函数String&operate=(const String&other); //赋值函数Private:Char *m_data; //⽤于保存字符串};请编写String的上述4个函数。
String::String(const char*str=NULL){if(str == NULL){Init();return ;}int nLen = SafeStrlen(str) + 1;if (nLen != 1){m_data = new char[nLen];memset(m_data, 0, nLen);memcpy(m_data, lpsz, nLen*sizeof(char));}else Init();}String::String(const String&other){int len = SafeStrlen(other.m_data) + 1;m_data = new char[len];memset(m_data, 0, len);memcpy(m_data, other.m_data, len);}String::~String()// free any attached data{if(m_data)delete []m_data;}const String& String::operator=(const String& other){char* pOldData = m_data;int len = SafeStrlen(other.m_data) + 1;if( len != 1 ){m_data = new char[len];memset(m_data, 0, len);memcpy(m_data, other.m_data, len);if(pOldData) delete[]pOldData;return *this;}if(pOldData) delete[]pOldData;Init();return *this;}void String::Init(){m_data = new char[1];*m_data = '/0';}int String::SafeStrlen(LPCTSTR lpsz){return (lpsz == NULL) ? 0 : strlen(lpsz); }。
c语言中string的用法
c语言中string的用法在C语言中,字符串(string)是一组字符的序列,以null字符('\0')结尾。
字符串在实际编程中非常常见,因此了解如何使用字符串是至关重要的。
首先,我们可以使用字符数组来表示和处理字符串。
例如,我们可以声明一个字符数组来存储一个字符串:```cchar str[50] = "Hello, World!";```在上述例子中,我们声明了一个名为`str`的字符数组,大小为50,并将字符串"Hello, World!"赋值给它。
要注意的是,C语言中的字符串是以null字符('\0')结尾的,这个字符表示字符串的结束。
在声明和初始化字符数组时,编译器会自动在末尾添加null字符。
我们可以使用一个特殊的函数`strlen()`来获取字符串的长度。
该函数返回字符串中字符的数量,不包括null字符。
```cint length = strlen(str);```在上述示例中,我们将字符串`str`的长度存储在变量`length`中。
C语言中还提供了一些用于处理字符串的函数,例如`strcpy()`、`strcat()`和`strcmp()`等。
- `strcpy()`函数用于将一个字符串复制到另一个字符串中:```cchar destination[50];strcpy(destination, str);```在上述示例中,我们将`str`字符串复制到`destination`字符串中。
- `strcat()`函数用于将一个字符串附加到另一个字符串的末尾:```cchar str1[50] = "Hello, ";char str2[] = "World!";strcat(str1, str2);```在上述示例中,我们将`str2`字符串附加到`str1`字符串的末尾。
c++string 案例
c++string 案例《C String案例》一、概述C String是C语言中用于处理字符串的基本数据类型。
在C语言中,字符串通常以字符数组的形式存储,可以通过指针来访问和操作。
本案例将通过一个简单的示例来介绍C String的使用方法。
二、案例描述本案例将演示如何使用C String来创建一个简单的字符串,并进行一些基本的操作,如拼接、查找、替换和格式化等。
三、实现步骤1. 引入头文件:使用`<stdio.h>`头文件中的`printf()`函数和`string.h`头文件中的`strcpy()`函数等字符串操作函数。
2. 声明变量:声明一个字符数组变量`str`来存储字符串,以及一个指针变量`p`来指向字符串的起始位置。
3. 输入字符串:使用`scanf()`函数从用户输入中获取一个字符串,并将其存储在`str`变量中。
4. 输出原字符串:使用`printf()`函数输出原字符串,以便验证输入的正确性。
5. 拼接字符串:使用`strcat()`函数将一个子字符串拼接到原字符串的末尾。
6. 查找子字符串:使用`strstr()`函数查找指定子字符串在原字符串中的位置。
7. 替换子字符串:使用`strreplace()`函数替换原字符串中的指定子字符串。
8. 格式化字符串:使用`sprintf()`函数将一个浮点数格式化为字符串,并将其存储在`str`变量中。
9. 输出处理后的字符串:使用`printf()`函数输出处理后的字符串,以验证操作是否正确。
四、代码实现下面是一个简单的C代码实现,用于演示上述操作:```c#include <stdio.h>#include <string.h>int main() {char str[100]; // 声明字符数组变量str来存储字符串char *p = str; // 声明指针变量p指向str的起始位置char sub_str[] = "world"; // 子字符串float num = 3.14; // 浮点数int i;// 输入字符串并输出原字符串printf("请输入一个字符串:");scanf("%s", str);printf("原字符串为:%s\n", str);// 拼接字符串strcat(str, sub_str);printf("拼接后的字符串为:%s\n", str);// 查找子字符串并输出位置(如不存在则输出-1)i = strstr(str, sub_str);if (i != -1) {printf("子字符串位置:%d\n", i - p); // 计算子字符串在原字符串中的位置(从起始位置开始算起)} else {printf("未找到子字符串\n");}// 替换子字符串并输出替换后的结果(如不存在则不替换)if (strstr(str, "hello") != NULL) { // 检查是否需要替换子字符串 int j = strreplace(str, "hello", "world"); // 替换子字符串为"world"printf("替换后的结果为:%s\n", str); // 输出替换后的结果(包括替换后的新子字符串)} else {printf("未找到需要替换的子字符串\n");}// 格式化字符串并输出结果(如格式化失败则输出错误信息)if (sprintf(p, "%f", num) > 0) { // 将浮点数格式化为字符串并存储在p指向的位置上(不包括尾部的空字符)printf("格式化后的结果为:%s\n", p); // 输出格式化后的结果(包括格式化后的新子字符串)} else {printf("格式化失败\n"); // 输出错误信息(包括可能的错误原因)}return 0;}```五、运行结果及分析当运行上述代码时,程序将提示用户输入一个字符串,并根据要求进行一系列操作。
c语言string类的常用方法
c语言string类的常用方法在C语言中,字符串通常表示为字符数组,而不是像C++中的`std::string`类。
但我们可以使用一些函数来处理字符串,这些函数在``库中定义。
以下是C语言中处理字符串的一些常用方法:1. `strlen()`: 返回字符串的长度,不包括终止字符'\0'。
```csize_t len = strlen("Hello"); // len 为 5```2. `strcpy()`: 将一个字符串复制到另一个字符串。
```cchar src[] = "Hello";char dest[10];strcpy(dest, src); // dest 现在是 "Hello"```3. `strcat()`: 将一个字符串连接到另一个字符串的末尾。
```cchar src1[] = "Hello";char src2[] = ", World!";strcat(src1, src2); // src1 现在为 "Hello, World!" ```4. `strcmp()`: 比较两个字符串。
```cchar str1[] = "Hello";char str2[] = "World";if (strcmp(str1, str2) < 0) {printf("str1 is less than str2\n");} else if (strcmp(str1, str2) > 0) {printf("str1 is greater than str2\n");} else {printf("str1 is equal to str2\n");}```5. `strstr()`: 在字符串中查找子字符串。
c,,实验报告,用string类申明字符串对象实现数组的转置
c,,实验报告,用string类申明字符串对象实现数组的转置C++程序设计实验报告C++实验报告实验一1. 实验要求(1)编写一个函数把华氏温度转换为摄氏温度,转换公式如下C=(F-32)*5/9(2)编写重载函数Max1可分别求两个整数,三个整数,两个双精度数,三个双精度数的最大值。
(3)使用系统函数pow(x,y)计算xy的值,注意包含头文件math.h。
(4)用递归的方法编写函数求Fibonacci级数,观察递归调用的过程2. 实验内容及实验步骤(1)编写函数float Convert(float TempFer),参数和返回值都为float类型,实现算法C=(F-32)*5/9,在main()函数中实现输入、输出。
程序名:lab3_1.cpp。
(2)分别编写四个同名函数max1,实现函数重载,在main()函数中测试函数功能。
程序名:lab3_2.cpp(3)在main()函数中提示输入两个整数x、y,使用cin语句得到x、y的值,调用pow(x,y)函数计算x的y次幂的结果,再显示出来。
程序名:lab3_4.cpp(4)编写递归函数int fib(int n),在主程序中输入n的值,调用fib函数计算Fibonacci级数。
公式为fib(n)=fib(n-1)+fib(n-2),n2;fib(1)=fib(2)=1。
使用if语句判断函数的出口,在程序中用cout语句输出提示信息。
程序名:(转载于: 写论文网:c,,实验报告,用string类申明字符串对象实现数组的转置)lab3_5.cpp(5)使用debug中的Step Into追踪到函数内部,观察函数的调用过程。
3.源程序Lab3_1#includeiostreamusing namespace std;float fun(float x){ float y;y=(x-32)*5/9;return y;}void main(){ float f,c;cout请输入华氏温度: ;cinf;c=fun(f);cout对应的摄氏温度为: cendl; }运行结果Lab3_2#includeiostreamusing namespace std;int Max1(int x,int y){ return (xy?x:y);}int Max1(int x,int y,int z){ int h,k;h=(xy?x:y);k=(hz?h:z);return k;}double Max1(double x,double y) {return (xy?x:y);}double Max1(double x,double y,double z) { double h,k;h=(xy?x:y);k=(hz?h:z);return k;}void main(){ int i,j,k;double l,m,n;cout请输入两个整数: ;cinij;cout最大数为: Max1(i,j)endl;cout请输入三个整数: ;cinijk;cout最大数为: Max1(i,j,k)endl;cout请输入两个双精度数: ;cinlm;cout最大数为: Max1(l,m)endl;cout请输入三个双精度数: ;cinlmn;cout最大数为: Max1(l,m,n)endl;}运行结果Lab3_3#includeiostream#includecmathusing namespace std; void main(){ double p,x,y;cinxy;p=pow(x,y);coutpendl;}运行结果Lab3_4#includeiostream.hint fib(int n);int main(){int n,answer;coutEnter number:endl; cinn;cout\n\n;answer=fib(n);coutansweris thenth Fibonacci number\nendl;return 0;}int fib(int n){coutProcessing fib(n)…endl;if(n3){coutReutrn 1!\n;return(1);}elsecoutCall fib(n-2)and fib(n-1).\nendl;return(fib(n-2)+fib(n-1));}运行结果4.实验体会其实这次实验涉及C++的内容并不多,主要练习的只是C++中的输入输出和重载函数的应用。
c++中string的常用方法及其功能
c++中string的常用方法及其功能摘要:1.C++ string 简介2.C++ string 常用方法概述- 构造函数与析构函数- 字符串操作方法- 字符串匹配与查找- 字符串编辑与转换3.具体方法详解- 字符串长度- 字符串切片- 字符串连接- 字符串查找- 字符串替换- 字符串大小写转换- 字符串编码和解码4.实战应用案例5.总结与拓展正文:C++中string的常用方法及其功能在C++编程中,string类是处理字符串的核心库。
它为开发者提供了许多实用的方法,使得字符串操作更加简单便捷。
本文将介绍C++ string类的常用方法及其功能,并给出实战应用案例。
1.C++ string 简介C++ string 类是C++ Standard Library 中的一个容器类,用于存储和处理字符串。
它提供了许多实用的方法,用于操作字符串,如构造、匹配、编辑等。
使用string 类可以让我们在编写程序时不再需要使用传统的C语言字符数组,从而降低了内存占用和编程复杂度。
2.C++ string 常用方法概述2.1 构造函数与析构函数string 类提供了多种构造函数,如默认构造函数、拷贝构造函数、从C字符串构造等。
析构函数用于在对象销毁时释放内存。
2.2 字符串操作方法string 类提供了许多用于操作字符串的方法,如:- length:获取字符串长度- size:获取字符串长度- empty:判断字符串是否为空- push_back:向字符串末尾添加字符- pop_back:删除字符串末尾的字符2.3 字符串匹配与查找- find:查找子字符串在字符串中首次出现的位置- rfind:查找子字符串在字符串中最后一次出现的位置- count:计算子字符串在字符串中出现的次数- index:返回子字符串在字符串中首次出现的位置- last_index:返回子字符串在字符串中最后一次出现的位置2.4 字符串编辑与转换- substring:获取字符串子串- insert:在指定位置插入字符或子字符串- append:向字符串末尾添加字符或子字符串- remove:删除指定位置的字符或子字符串- replace:替换字符串中的子串- truncate:截断字符串2.5 字符串大小写转换- to_lower:将字符串转换为小写- to_upper:将字符串转换为大写2.6 字符串编码和解码- getBytes:获取字符串的字节数组- setBytes:设置字符串的字节数组- codePointAt:获取指定位置的字符编码- codePointBefore:获取指定位置前一个字符的编码3.具体方法详解在此部分,我们将详细介绍上述方法的具体使用和功能。
C++自己实现一个String类
C++⾃⼰实现⼀个String类C++⾃⼰实现⼀个String类(构造函数、拷贝构造函数、析构函数和字符串赋值函数)#include <iostream>#include <cstring>using namespace std;class String{public:// 默认构造函数String(const char *str = nullptr);// 拷贝构造函数String(const String &str);// 析构函数~String();// 字符串赋值函数String& operator=(const String &str);private:char *m_data;int m_size;};// 构造函数String::String(const char *str){if(str == nullptr) // 加分点:对m_data加NULL 判断{m_data = new char[1]; // 得分点:对空字符串⾃动申请存放结束标志'\0'的m_data[0] = '\0';m_size = 0;}else{m_size = strlen(str);m_data = new char[m_size + 1];strcpy(m_data, str);}}// 拷贝构造函数String::String(const String &str) // 得分点:输⼊参数为const型{m_size = str.m_size;m_data = new char[m_size + 1]; //加分点:对m_data加NULL 判断strcpy(m_data, str.m_data);}// 析构函数String::~String(){delete[] m_data;}// 字符串赋值函数String& String::operator=(const String &str) // 得分点:输⼊参数为const{if(this == &str) //得分点:检查⾃赋值return *this;delete[] m_data; //得分点:释放原有的内存资源m_size = strlen(str.m_data);m_data = new char[m_size + 1]; //加分点:对m_data加NULL 判断strcpy(m_data, str.m_data);return *this; //得分点:返回本对象的引⽤}。
定义一个串类CMyString
定义一个串类CMyString/*定义一个串类CMyString,建立适当的构造函数字符串使用指针保存字符串必须实现如下操作,字符串比较、求串的长度、判断串是否为空、将串置空、字符串赋值(包括两个字符串类复制,一个字符串赋值到CmyString对象)求字符串中的一个字符或改变字符串中的一个字符(采用重载[]),完成串的赋值与合并(重载+),得到表示字符串的指针地址*/#include#include#includeusing namespace std;class CMyString{public:char *str;int len;public:CMyString( ){str = NULL;len = 0;}CMyString(char *p){str=p;len=strlen(str);}CMyString(CMyString &c);~CMyString(){}int Length();friend void compare(CMyString c1,CMyString c2);void isEmpty();void clear();void Display();/**/friend CMyString operator+(CMyString &c1,CMyString &c2){CMyString s;s.str=new char[strlen(c1.str)+strlen(c2.str)+1];strcpy(s.str,c1.str);strcat(s.str,c2.str);s.len=strlen(s.str);return s;}char & operator[](int n){static char ch=0;if(n>len-1){cout<<"整数下表越界"<<endl;< p="">return ch;}else return *(str+n);}};/**/CMyString::CMyString(CMyString &c) { str=new char[strlen(c.str)+1];strcpy(str,c.str);}int CMyString::Length(){return len;}void CMyString::isEmpty(){if(str!=NULL)cout<<str<<"字符串不为空"<<endl;< p=""> elsecout<<str<<"字符串为空"<<endl;< p="">}void CMyString::clear(){this->str=NULL;this->len=0;}/**/void CMyString::Display (){if(str!=NULL)cout<<str<<endl;< p="">elsecout<<"字符串为空"<<endl;< p="">}void compare(CMyString c1,CMyString c2) {if(strcmp(c1.str,c2.str)>0)cout<<c1.str<<"大于"<<c2.str<<endl;< p=""> if(strcmp(c1.str,c2.str)<0)cout<<c1.str<<"小于"<<c2.str<<endl;< p=""> if(strcmp(c1.str,c2.str)==0)cout<<c1.str<<"等于"<<c2.str<<endl;< p=""> }int main(){system("color 2b");char s1[100],s2[100];bool f=true;int a;CMyString str1(s1),str2(s2);CMyString str3,str4;while(1){if(f){system("color 2b");cout<<" --------------------------------------------"<<endl;< p="">cout<<" |**********[]链表操作**********|"<<endl;< p="">//cout<<" |**********[]输入字符串**********|"<<endl;< p=""> cout<<" |**********[1]输出字符串**********|"<<endl;< p=""> //cout<<" |**********[3]求字符串的长度**********|"<<endl;< p="">cout<<" |**********[2]字符串赋值**********|"<<endl;< p=""> cout<<" |**********[3]比较字符串大小**********|"<<endl;< p="">cout<<" |**********[4]合并字符串**********|"<<endl;< p=""> cout<<" |**********[5]判断字符串是否为空**********|"<<endl;< p="">cout<<" |**********[6]将字符串置空**********|"<<endl;< p=""> cout<<" |**********[7]返回**********|"<<endl;< p="">cout<<" --------------------------------------------"<<endl;< p="">cout<<"输入数字8结束:"<<endl;}< p="">cout<<"请输入操作数:";cin>>a;f=false;if(a==8)break;if(a>0&&a<8){CMyString str1("chian"),str2("american");CMyString str3,str4;switch(a){case 1:{/*cout<<"输入字符串s1:";cin.getline(s1,50);cout<<<"输入字符串s2:";cin.getline(s2,50);cout<<endl;}break;<="" p=""> case 2:{*/CMyString str1("chian"),str2("american");CMyString str3,str4;cout<<"字符串str1为:";str1.Display();cout<<"字符串str2为:";str2.Display();cout<<"字符串str1的长度为:";cout<<str1.length()<<endl;< p="">cout<<"字符串str2的长度为:";cout<<str2.length()<<endl;}break;< p="">case 2:{cout<<"将Str1赋值给str3后输出str3:";str3=str1;str3.Display ();}break;case 3:{cout<<"判断字符串str1与str2的大小:";compare(str1,str2);}break;case 4:{cout<<"将字符串str1与str2合并并输出:"; str4=str1+str2;str4.Display ();}break;case 5:{cout<<"判断字符串str2是否为空:";str2.isEmpty();}break;case 6:{cout<<"将字符串str1置空:";str1.clear();str1.Display ();}break;case 7:break;}}}return 0;}</str2.length()<<endl;}break;<></str1.length()<<endl;<></endl;}<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></c1.str<<"等于"<<c2.str<<endl;<> </c1.str<<"小于"<<c2.str<<endl;<> </c1.str<<"大于"<<c2.str<<endl;<> </endl;<></str<<endl;<></str<<"字符串为空"<<endl;<></str<<"字符串不为空"<<endl;<> </endl;<>。
自己实现C++String类
自己实现C++String类简单String类功能实现一般是要求实现构造函数、拷贝构造函数、赋值函数、析构函数这几个非常重要的部分。
因为String里涉及动态内存的管理,默认的拷贝构造函数在运行时只会进行浅复制,即只复制内存区域的指针,会造成两个对象指向同一块内存区域的现象。
如果一个对象销毁或改变了该内存区域,会造成另一个对象运行或者逻辑上出错。
这时就要求程序员自己实现这些函数进行深复制,即不止复制指针,需要连同内存的内容一起复制。
具体代码如下:/******************Author : 杨永利data : 2020-06-28*******************/#include <string.h>#include <assert.h>#include <iostream>using namespace std;class String{public:String(const char *str = NULL);//通用构造函数String(const String &str);//拷贝构造函数(深赋值)~String();//析构函数String operator+(const String &str) const;//重载+String& operator=(const String &str);//重载=String& operator+=(const String &str);//重载+=bool operator==(const String &str) const;//重载==char& operator[](int n) const{assert(n <= length - 1); return data[n]; }//重载[](内联函数)size_t size() const{ return length; }//长度接口(内联函数)const char* c_str() const{ return data; }//数据接口(内联函数)friend istream& operator>>(istream &is, String &str);//输入friend ostream& operator<<(ostream &os, String &str);//输出private:char *data;//字符串size_t length;//长度};String::String(const char *str){if(str == NULL){length = 0;data = new char[1];*data = '\0';}else{length = strlen(str);data = new char[length + 1];strcpy(data, str);}}String::String(const String &str){length = str.size();data = new char[length + 1];strcpy(data, str.c_str());}String::~String(){delete []data;length = 0;}String String::operator+(const String &str) const {String newString;newString.length = length + str.size(); newString.data = new char[newString.length + 1]; strcpy(newString.data, data);strcat(newString.data, str.data);return newString;}String& String::operator=(const String &str){if(this == &str){return *this;}delete []data;length = str.size();data = new char[length + 1];strcpy(data, str.c_str());return *this;}String& String::operator+=(const String &str) {if(str.size() == 0){return *this;}length += str.size();char *t_data = new char[length + 2];strcpy(t_data, data);strcat(t_data, str.c_str());delete []data;data = t_data;return *this;}bool String::operator==(const String &str) constif(length == str.size() && !strcmp(data, str.c_str())) {return true;}return false;}istream& operator >>(istream &is, String &str) {char temp[1024];is >> temp;str.length = strlen(temp);str.data = new char[str.length + 1];strcpy(str.data, temp);return is;}ostream& operator<<(ostream &os, String &str) {os << str.data;return os;}int main(){String s;cin >> s;cout << s << ": " << s.size() << endl;char a[] = "Hello", b[] = "World!";String s1(a), s2(b);cout << s1 << " + " << s2 << " = " << s1 + s2 << endl;String s3 = s1 + s2;if (s1 == s3)cout << "First: s1 == s3" << endl;s1 += s2;if (true == (s1 == s3))cout << "Second: s1 == s3" << endl; cout<<s1[3]<<endl;return 0;}运行结果如下:。
C++string数据类型的实现
C++string数据类型的实现1 #include <cstdlib>2 #include <cstring>34class Mystring5 {6public:7 Mystring(const char * pdata)8 {9if(pdata==NULL)10 {11 data = new char[1];12 *data = '\0';13 }14else15 {16int len = strlen(pdata);17 data = new char[len+1];18 strcpy(data,pdata);19 }20 }21 Mystring(const Mystring &str)22 {23int len = strlen(str.data);24 data = new char[len+1];25 strcpy(data,str.data);26 }2728 Mystring &operator=(const Mystring &str)29 {30if(this!=&str)31 {32 Mystring strTemp(str);33char *pTemp = strTemp.data;34 strTemp.data = this->data;35this->data = pTemp;36 }37return this;38 }39 ostream & operator<<(ostream &os,const Mystring &str)40 {41 os<<str.data;42return os;43 }44 Mystring & operator+(const Mystring & str)const45 {46if(str.data!=NULL)47 {48int len1 = strlen(str.data);49int len2 = strlen(this->data);50 Mystring strTemp(*(this->data));//创建⼀个临时对象保存原来对象的数据51delete []data;//删除原来的数据52 data=NULL;53 data = new char[len1+len2+2];//开闭新的空间54 strcpy(data,strTemp.data);//复制55 strcat(data,str.data);//拼接56 }57return this;58 }5960char & operator[](int index)//char返回引⽤,是为了我们之后可以修改字符串61 {62int len = strlen(data);63if(index>len||index<0)64 {65 perror("index is not in the cope!");66 exit(0);67 }else68return *((this->data)+index);69 }7071 ~Mystring()72 {73delete []data;74 }75private:76char * data;77 };。
C++实现MyString的示例代码
C++实现MyString的⽰例代码MyString的构造、析构、拷贝构造、赋值运算class String{char* str;public:String(const char* p = NULL) :str(NULL){if (p != NULL){str = new char[strlen(p) + 1];//strlen()计算⾄'\0'截⾄的字符数strcpy(str, p);}else{str = new char[1]; //额外提供⼀个空间*str = '\0';}}~String(){if (str != NULL){delete[] str;}str = NULL;}//ostream& operator<<(const String* const this, ostream &out)ostream& operator<<(ostream& out)const //重载插⼊操作符{if (str != NULL){out << str;}return out;}String(const String& s):str(NULL){//str = s.str; 浅拷贝是同⼀个空间,会造成⼀个空间释放两次//深拷贝str = new char[strlen(s.str)+1];strcpy(str, s.str);}String& operator=(const String& s){if(this != &s){delete[]str;str = new char[strlen(s.str)+1]strcpy(str,s.str);}return *this;}};ostream& operator<<(ostream& out, const String& s){s << out;//s.operator<<(cout);//operator<<(&s1,cout);return out;}int main(){String s1("123");s1 << cout;//s1.operator<<(cout);//operator<<(&s1,cout);cout << s1 << endl;//operator<<(cout, s1);}前⾯之所以对空指针构建对象提供⼀个空间的原因:使其在赋值重载中只有指向堆区⼀种情况进⾏处理通过此⽅式进⾏等号运算符重载,然后调动拷贝构造对s2进⾏重写构造输出流重写class String{char* str;public:String(const char* p = NULL) :str(NULL){if (p != NULL){str = new char[strlen(p) + 1];strcpy(str, p);}else{str = new char[1]; //额外提供⼀个空间*str = '\0';}}~String(){if (str != NULL){delete[] str;}str = NULL;}//ostream& operator<<(const String* const this, ostream &out)ostream& operator<<(ostream& out)const //重载插⼊操作符{if (str != NULL){out << str;}return out;}};int main(){String s1("123");s1 << cout;//s1.operator<<(cout);//operator<<(&s1,cout);}在这⾥通过改写前的代码operator<<(&s1,cout);不难看出,将cout初始化out,随后将this.str输出⾄outostream& operator<<(ostream& out)const此处只能使⽤引⽤,因为cout在ostream类中进⾏转移,该类将拷贝构造函数定义为保护访问属性,⽆法使⽤cout初始化out,继⽽只能使⽤引⽤;同样若我们不想使⽤实参去初始化形参,可以将拷贝构造函数定义为私有或保护类型若希望输出符合cout << s1 << endl;此种形式,需要再写⼀个全局函数class String{char* str;public:String(const char* p = NULL) :str(NULL){if (p != NULL){str = new char[strlen(p) + 1];strcpy(str, p);}else{str = new char[1]; //额外提供⼀个空间*str = '\0';}}~String(){if (str != NULL){delete[] str;}str = NULL;}//ostream& operator<<(const String* const this, ostream &out)ostream& operator<<(ostream& out)const //重载插⼊操作符{if (str != NULL){out << str;}return out;}};ostream& operator<<(ostream& out, const String& s){s << out;//s.operator<<(cout);//operator<<(&s1,cout);return out;}int main(){String s1("123");s1 << cout;//s1.operator<<(cout);//operator<<(&s1,cout);cout << s1 << endl;//operator<<(cout, s1);}通过此种形式进⾏翻转,继⽽达到符合cout << s1 << endl;的形式MyString加号运算符重载int main(){String s1("123");String s2("456");String s3;s3 = s1 + s2;S3 = s1 + "789";s3 = "789" + s1;}分别写三个加号运算符重载,来对应上⾯的三个情况(类+类、类+字符串、字符串+类)String operator+(const String& s)const{char *p = new char(strlen(this->str) + strlen(s.str) + 1);strcpy(p, this->str);strcat(p, s.str);return String(p);}第⼀个为成员函数,但是存在内存泄漏,需要进⾏下⾯的步骤在私有成员变量中,创建⼀个新的构造函数,直接将p给到str,⽽没有创建新的空间;并且在加号运算符重载进⾏修改使其调⽤私有的构造函数private:String(char*p,int)//两个参数与公有构造区分{str = p;}public:String operator+(const String& s)const{char *p = new char(strlen(this->str) + strlen(s.str) + 1);strcpy(p, this->str);strcat(p, s.str);return String(p,1);}这样就解决了原本内存泄漏的问题接下来完成剩余两个等号运算符重载String operator+(const char* s)const{char* p = new char(strlen(this->str) + strlen(s) + 1);strcpy(p, this->str);strcat(p, s);return String(p, 1);//return *this + String(s)//上⾯的⽅式更⽅便,但是会构造两个临时对象}此处需要写在类外,并且需要类内添加友元函数friend String operator+(const char* t, const String s);String operator+(const char* t, const String s){char* p = new char(strlen(s.str) + strlen(t) + 1);strcpy(p, s.str);strcat(p, t);return String(p, 1);//return String(p) + s; 与上⾯同理,并且不需要友元函数}讨论⼀个衍⽣问题class String{private:char* str;public:String(const char* p = NULL) :str(NULL){if (p != NULL){str = new char[strlen(p) + 1];strcpy(str, p);}else{str = new char[1]; //额外提供⼀个空间*str = '\0';}}~String(){if (str != NULL){delete[] str;}str = NULL;}String(const String& s){//str = s.str; 浅拷贝是同⼀个空间,会造成⼀个空间释放两次//深拷贝str = new char[strlen(s.str)];strcpy(str, s.str);}String& operator=(const String& s){if (this != &s){delete[]str;str = new char[strlen(s.str)];strcpy(str, s.str);}return *this;}};String fun(){String s2("456");return s2;}int main(){String s1;s1 = fun();return 0;}讨论此程序执⾏的过程总共创建了多少个对象:主函数运⾏⾸先开辟main函数栈帧,创建s1对象,默认构造只有⼤⼩为⼀的空间存放“\0”;之后执⾏fun()函数,分配fun栈帧,然后创建s2对象,创建⼀个堆区,str指向堆区空间;并且将按值返回,需要构建⼀个临时对象(将亡值);将亡值概念:表达式过程中所产⽣的不具有名字的⼀个实体,叫做将亡值;将亡值的⽣存期仅在表达式的调⽤过程中,表达式调⽤结束,将亡值就会结束构建临时对象调⽤拷贝构造,fun函数结束,s2⽣存期结束,调动析构函数;⾸先释放s2调⽤资源,再归还s2空间;回到主函数,把将亡值赋值给s1调⽤赋值语句,接着调⽤将亡值的析构函数进⾏释放这个过程中总共创建了三个对象,分别是s1、s2、将亡值对象那么如果我们对fun以引⽤进⾏返回String& fun(){String s2("456");return s2;}int main(){String s1;s1 = fun();return 0;}当以引⽤返回,就不会返回⼀个s2的备份,从引⽤底层来看会返回s2的地址;这样会从⼀个已死亡对象来获取数据,继⽽会得到随机值随后介绍的右值拷贝构造与右值赋值语句可以解决这个问题到此这篇关于C++实现MyString的⽰例代码的⽂章就介绍到这了,更多相关C++ MyString内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
C++实现MyString类
MyString.h#pragma once#include <iostream>#include <cstring>using namespace std;class MyString{public:MyString(char *pstr="");MyString(const MyString& str);~MyString();void ShowString(); //显示字符串void Add(const MyString& str); //与另外一个相加void Copy(const MyString& str); //从另外一个拷贝int GetLength() const;private:char *m_buf;};MyString.cpp#include "MyString.h"MyString::MyString( char *pstr){if(pstr){m_buf = new char[strlen(pstr) +1];strcpy(m_buf, pstr);}else{m_buf = new char[1];*m_buf = '\0';}}MyString::MyString( const MyString& str){m_buf = new char[ strlen(str.m_buf) +1 ];strcpy( m_buf, str.m_buf);}MyString::~MyString( ){delete[] m_buf;}void MyString::ShowString( ){if(*m_buf!= '\0'){cout<< m_buf <<endl;}else{cout << "This is a NULL string" << endl;}}void MyString::Add(const MyString& str){if( *str.m_buf = '\0' )return;int nLength = GetLength();char *pTmp = new char[ nLength];strcpy(pTmp, m_buf );delete [] m_buf;m_buf = new char[ (nLength-1) + str.GetLength() ];strcpy(m_buf, pTmp);strcat( m_buf, str.m_buf);delete[] pTmp;}void MyString::Copy(const MyString& str){delete [] m_buf;m_buf = new char[ strlen(str.m_buf) +1 ];strcpy( m_buf, str.m_buf);}int MyString::GetLength() const{return strlen(m_buf)+1;}main.cpp#include"MyString.h"int main(){MyString str("hi ");MyString str2("You are welcome!");str.ShowString();str.Add(str2);str.ShowString();return 0;}。
字符串封装,mystring类,用C++实现
字符串封装,mystring类,⽤C++实现封装了多次mystring,但是为了防⽌遗忘,特写篇⽂章备查包括三个⽂件,mystring.h,mytring.cpp,测试⽂件:main.cpp测试平台,vs2013mystring.h#ifndef __MYSTRING_H__#define __MYSTRING_H__#define _CRT_SECURE_NO_WARNINGS#include<iostream>using namespace std;class mystring{public:/*带默认参数的构造函数*/mystring(const char *str = NULL);/*拷贝构造函数*/mystring(const mystring &other);/*虚析构函数*/virtual ~mystring();/*赋值运算符重载*/mystring & operator=(const mystring &other);/*获得C风格字符串*/char *getCstring();/*运算符重载*/char operator[](int i);bool operator<(const mystring &other);bool operator>(const mystring &other);bool operator==(const mystring &other);/*字符串连接符*/mystring & operator+=(const mystring &other);/*字符串重载输⼊输出运算符*/friend ostream &operator<<(ostream &out, mystring &str);friend istream &operator>>(istream &in, mystring &str);private:char *m_pstr;};#endifmytring.cpp#include"mystring.h"/*带默认参数的构造函数*/mystring::mystring(const char *str){if (str == NULL){m_pstr = new char[1];*m_pstr = '\0';}else{int len = strlen(str);m_pstr = new char[len + 1];/*strcpy会连带字符串结束符⼀起拷贝*/strcpy(m_pstr, str);}}/*拷贝构造函数*/mystring::mystring(const mystring &other){int len = strlen(other.m_pstr);m_pstr = new char[len + 1];strcpy(m_pstr, other.m_pstr);}/*虚析构函数*/mystring::~mystring(){delete[]m_pstr;}/*赋值运算符重载,返回引⽤的⽬的&是为了连等式*/mystring & mystring::operator=(const mystring &other){if (this == &other)return *this;delete[]m_pstr;int len = strlen(other.m_pstr);m_pstr = new char[len + 1];strcpy(m_pstr, other.m_pstr);return *this;}/*获得C风格字符串*/char *mystring::getCstring(){/*只能通过成员函数来操作私有成员*/return m_pstr;}/*重载运算符*/char mystring::operator[](int i){if (i>=0&&i<=strlen(m_pstr)){return m_pstr[i];}}bool mystring::operator<(const mystring &other){return (strcmp(this->m_pstr, other.m_pstr)<0 ? true : false); }bool mystring::operator>(const mystring &other){return (strcmp(this->m_pstr, other.m_pstr)>0 ? true : false); }bool mystring::operator==(const mystring &other){return (strcmp(this->m_pstr, other.m_pstr) == 0 ? true : false); }/*字符串连接符*/mystring & mystring::operator+=(const mystring &other){int len = strlen(m_pstr)+strlen(other.m_pstr);char *temp = new char[len + 1];/*先拷贝*/strcpy(temp, m_pstr);/*再连接*/strcat(temp, other.m_pstr);delete[]m_pstr;m_pstr = temp;return *this;}/*字符串重载输⼊输出运算符*/ostream &operator<<(ostream &out, mystring &str){return out << str.m_pstr;}istream &operator>>(istream &in, mystring &str){char buf[256];in >> buf;/*调⽤C风格参数构造函数创建对象*/str=mystring(buf);return in;}main.cpp#include "mystring.h"int main(){/*测试空串*/mystring str1;cout << "str1=" << str1 << endl;;/*测试⽤C风格字符串来构造*/mystring str2("hello world");cout << "str2="<<str2 << endl;/*测试拷贝构造函数*/mystring str3(str2);cout << "str3=" << str3 << endl;/*测试赋值运算符重载*/str1 = str3;cout << "赋值之后,str1=" << str1 << endl;/*测试getCstring()*/cout << "str3的C风格字符串: "<<str3.getCstring()<<" 长度为: "<<strlen(str3.getCstring()) << endl; mystring str4 = "i love you";cout << str4 << endl;/*测试str[i]*/cout << str4[3] << endl;/*测试> < == +=*/cout << "str4 > str3 "<< (str4 > str3) << endl;cout << "str4 < str3 " << (str4 < str3) << endl;cout << "str4 == str3 " << (str4 == str3) << endl;cout << "str2 == str3 " << (str2 == str3) << endl;cout << "str4 += str3 " << (str4 += str3) << endl;/*测试cin,cout*/mystring str5;cin >> str5;cout << str5 << endl;system("pause");return0;}。
详解C++中实现继承string类的MyString类的步骤
详解C++中实现继承string类的MyString类的步骤昨天师兄⼜出了道测试题,让我们实现类似于string类的没有MyString类,刚开始很头疼,可是真正在⾃⼰写代码的时候⼜很兴奋的发现,这个过程真的是个很宝贵的机会,让我⼜有机会可以很好的熟悉回顾C++的很多知识—类设计,构造析构函数,成员函数,友元函数,引⽤,重载,字符串操作,动态内存分布。
于是昨天花了半天时间写了300多⾏代码,并认真的进⾏了相关测试、修改和总结。
因为内容有点丰富,所以想分⼏次写出来,条理也清楚些。
类的空间分配:类给它的每个对象都分配了独⽴的空间去存储它的数据成员,所有的对象公共的访问类⽅法进⾏操作。
同时在对象的独⽴空间中,不包括数据成员动态分配的空间,对象只是记录了动态分配空间的地址(所以在析构函数调⽤的时候只是删除了对像空间,同时需要⽤new来删除动态分配的地址)。
⼀、类声明—mystring.h:1. 构造函数:专门⽤于构建新对象,给成员数据分配必要的内存空间并将值赋给新对象的成员数据。
默认构造函数:在未提供显式初始化值时,被⽤来创建对象的构造函数(所以它⼀般没有参数)MyString();复制构造函数:⽤于将⼀个对象复制到新创建的对象中(当然这个被复制的对象必须已经存在)。
MyString(const MyString &str);给定了⼀定初始化参数的构造函数:参数列表中的值会⼀次赋给新创建对象的各个成员函数:MyString(const char*str);2.析构函数:当对象过期时删除对象所占的内存空间,并且当对象创建时有⽤New请求的内存空时,在析构函数中同时要调⽤delete对原来分配的内存空间进⾏释放,以防⽌内存泄露。
~MyString();3.成员函数:重载赋值成员函数:MyString &operator=(const MyString &str); //利⽤已有的string对象通过=给⼀个对象进⾏赋值MyString &operator=(const char*str); //直接⽤常量字符串进⾏赋值⼀般赋值函数:MyString &assign(const MyString&str);MyString &assign(const char*sstr);⼏个处理字符串的成员函数:size_t getsize()const; //返回字符串⼤⼩void clear(); //把字符串清空bool empty(); //判断字符串是否为空void swap(MyString &str); //交换两个字符串int compare(const MyString &str)const; //⽐较2个字符串的⼤⼩//第⼀个const说明显式调⽤的字符串不可更改,括号外⾯的const说明隐式调⽤的字符串不可更改,只读数据int compare(const char*str);追加函数:MyString &operator+=(const MyString&str);MyString &operator+=(const char*str);MyString &append(const MyString&str);MyString &append(const char *str);⽣成字串:MyString substr(size_t pos = 0,n=npos) const;⽣成字串,从第0个位置开始长度为n,若N超过长度,则为输出整个字符串的长度4.友元函数(运算符重载):友元函数⼀般都是在类得声明中进⾏定义,它不属于类得成员函数,但是它和类得成员函数⼀样同样的可以对类得所有数据成员进⾏访问。
c++ string的简单实现
C++ 的`std::string` 是一个非常强大且灵活的类,用于处理字符串。
下面是一个非常简单的`std::string` 实现,只包括一些基本的功能,例如构造函数、添加字符、获取长度、打印字符串等。
```cpp#include <iostream>#include <cstring>class SimpleString {private:char* data;int length;public:// 默认构造函数SimpleString() {data = new char[1];data[0] = '\0';length = 0;}// 带一个字符的构造函数SimpleString(char c) {data = new char[2];data[0] = c;data[1] = '\0';length = 1;}// 带一个字符串的构造函数SimpleString(const char* str) {length = strlen(str);data = new char[length + 1];strcpy(data, str);}// 拷贝构造函数SimpleString(const SimpleString& other) { length = other.length;data = new char[length + 1];strcpy(data, other.data);}// 析构函数~SimpleString() {delete[] data;}// 添加一个字符到字符串末尾void push_back(char c) {char* new_data = new char[length + 2]; strcpy(new_data, data);new_data[length] = c;new_data[length + 1] = '\0';delete[] data;data = new_data;length++;}// 获取字符串长度int size() const {return length;}// 打印字符串void print() const {std::cout << data << std::endl;}};```这个简单的`SimpleString` 类实现了最基本的字符串功能。
实现一个string类(C++)
实现⼀个string类(C++)0 说明 本⽂仅实现string类中⼏种重要、常⽤的功能,旨在掌握C++类设计的关键知识点。
1 知识点构造函数(包括默认构造函数、拷贝构造函数以及⾃定义的其他构造函数)运算符重载友元析构函数C风格字符的操作2 类的设计 为使代码简洁,本⽂采取分⽂件编写模式,类的声明包含在头⽂件"mystring.h"中,成员的实现包含在源⽂件"mystring.h"中,"main.cpp"⽂件是若⼲测试。
2.1 构造函数 类⽐C++中原有的string类,我们可以定义⼀个string对象(不指定初始值),可以⽤⼀个已存在的string对象初始化⼀个新定义的对象,也可以⽤⼀个C风格字符串给⼀个string对象赋值。
为了实现同样的功能,⾃定义的String类需要如下⼏种构造函数:默认构造函数:String(),⽤于直接构建⼀个不指定初值的对象拷贝构造函数:String(const String& s),⽤于初始化新的对象普通有参构造函数:String(const String* s),⽤于以C风格字符串初始化⼀个对象2.2 重载函数 由于String类是我们⾃定义的,所以有必要重载若⼲常⽤运算符以丰富String类所⽀持的功能。
具体地,本⽂将重载⼀下运算符:= 运算符,=运算符给已存在的对象赋值,我们将重载以String对象赋值和以C风格字符串赋值两种形式== 运算符,⽤于判断两个String对象是否相同> 运算符,判断⼀个对象是否⼤于另⼀个对象< 运算符,判断⼀个对象是否⼩于另⼀个对象+= 运算符,将两个对象拼接到⼀起[] 运算符,访问字符串某个位置的元素,分为常量和⾮常量两个版本重载<< 运算符,输出⼀个String对象>> 运算符,实现读⼊⼀个字符流到String对象2.3 普通成员函数 只设计⼀个length()函数⽤于获取字符串的长度。
自己实现简单的string类
⾃⼰实现简单的string类1.前⾔ 最近看了下《C++Primer》,觉得受益匪浅。
不过纸上得来终觉浅,觉知此事须躬⾏。
今天看了类类型,书中简单实现了String类,⾃⼰以前也学过C++,不过说来惭愧,以前都是⽤C来写程序,学的C++基本都忘记了,也说明⾃⼰以前对C++的理解不够深⼊。
基于这些,觉得有必要动⼿来写写C++的⼀些程序了,毕竟C++有很多的功能是C所不具备的。
正好看了课本中String类的简单实现,⽽且string类在C++中的使⽤频率也很⾼,了解其内部的实现是很有必要的。
所以今天打算写个string类,就当做练⼿吧。
2.String类的设计 写类⾸先是定义类的名字,我们实现的string就叫String吧,以防和标准库中的string类冲突。
其次是类中的内部数据,既然是字符串类,必须要把字符串类所代表的字符串保存起来,所以必须定义⼀个存放这些字符的字符数组或者⼀个指向字符数组的指针。
我是⽤后者实现,因为这样更为的灵活,不会因为提前定义数组的⼤⼩⽽限制了能存放到数组中的字符个数。
为了⽅便,可以定义字符串的长度,当然也可以不定义,可以在字符数组的末尾存放0来表⽰字符串的结束,不过每次得到字符串的长度⽐较⿇烦。
最后是类对外的接⼝,根据我们平时使⽤string类的情况,我们⼀般会⽤到接⼝size(), c_str(),还有就是+,=,>>,<<,+=,[],==等操作符。
根据前⾯的分析,可以得到我们要设计的String类中的成员如下所⽰:1class String2 {3public:4 String();5 String(const char *);6 String(const String &);7 String(String &&); //新加的move构造函数89 ~String();1011 String& operator=(const char *);12 String& operator=(const String &);1314bool operator==(const char *);15bool operator==(const String &);1617char &operator[](int);1819 String operator+(const char *);20 String operator+(const char);21 String operator+(const String &);2223 String &operator +=(const char *);24 String &operator +=(const char);25 String &operator +=(const String &);2627int size(){return _size;}28char *c_str(){return _string;}2930 friend istream &operator>>(istream &cin, String &str);31private:32int _size;33char *_string;34 };3.String类的主要实现 我们先来说⼀下构造函数的实现。
Mystring类声明
//名称://功能:MyString类声明//作者://日期:#include <iostream>using namespace std;constint MAXSIZE=100;classMyString //{private:char *str;//char str[MAXSIZE];public:MyString(char *s="");//构造函数MyString(MyString&obj);//拷贝构造函数intstrLen();//返回字符串长度void strLwr();//转为小写字母void strUpr();//转为大写字母void strCat(MyString&s2);//字符串连接intstrCmp(MyString&s2);//字符串比较void strCpy(MyString&s2);//字符串拷贝void show();//显示字符串函数~MyString();//析构函数};//end MyStringMyString::MyString(char *s)//构造函数{intlen=0;char *p=s;while(*p)//求字符串s长度{p++;len++;}//分配空间,放置字符串sstr=new char[len+1];for(int i=0;i<=len;i++)str[i]=s[i];}MyString::MyString(MyString&obj)//拷贝构造函数{intlen=obj.strLen();//求出obj中字符串长度str=new char[len+1];//分配空间for(int i=0;i<=len;i++)//拷贝字符串str[i]=obj.str[i];}intMyString::strLen()//返回字符串长度{intlen=0;char *p=str;while(*p)//求字符串str的长度{len++;p++;}returnlen;}void MyString::strLwr()//转换为小写字母{char *p=str;//str首部while(*p){if(*p>='A'&&*p<='Z')//大写字母时*p+=32;//'a'-'A'p++;}}void MyString::strUpr()//转换为大写字母{char *p=str;//str首部while(*p){if(*p>='a'&&*p<='z')//小写字母时*p-=32;p++;}}intMyString::strCmp(MyString&s2)//字符串比较,{char *p=str;//p指向当前字符串首部char *q=s2.str;//q指向s2字符串首部while(*p&&*q&&*p==*q)//p、q都没指向'\0'且*p不等于*q {p++;q++;}return (*p-*q);}void MyString::strCpy(MyString&s2)//字符串拷贝{intlen=s2.strLen();//第2个字符串长度if(len!=strLen())//如果两个字符串长度不等{delete []str;//释放原有空间str=new char[len+1];//分配新的合适大小的空间}for(int i=0;i<=len;i++)//拷贝字符串str[i]=s2.str[i];}void MyString::strCat(MyString&s2)//字符串连接{char *p=str;char *q=s2.str;int len1=strLen();//当前字符串长度int len2=s2.strLen();//第2个字符串长度char *newstr=new char[len1+len2+1];//连接后字符串所占空间for(int i=0;i<len1;i++)//拷贝第一个字符串newstr[i]=str[i];for(int j=0;j<=len2;j++)//拷贝第二个字符串newstr[len1+j]=s2.str[j];delete []str;//释放原有str指向的空间str=newstr;}MyString::~MyString()//析构函数{delete []str;}void MyString::show()//显示字符串函数cout<<"当前字符串:"<<str<<endl;}int main(){char str1[100];char str2[100];cout<<"请输入第一个字符串:";gets(str1);cout<<"请输入第二个字符串:";gets(str2);MyStrings1(str1);MyStrings2(str2);//测试长度函数cout<<"\n//测试长度函数"<<endl;cout<<"s1长度:"<<s1.strLen()<<endl;cout<<"s2长度:"<<s2.strLen()<<endl;//测试转大写字母cout<<"\n//测试转大写字母"<<endl;s1.strUpr();s1.show();//测试转为小写字母cout<<"\n//测试转为小写字母"<<endl;s1.strLwr();s1.show();//测试字符串比较cout<<"\n//测试字符串比较"<<endl;int result=s1.strCmp(s2);if(result>0)cout<<"s1大于s2"<<endl;else if(result==0)cout<<"s1等于s2"<<endl;elsecout<<"s1小于s2"<<endl;//测试字符串连接函数cout<<"\n//测试字符串连接函数"<<endl;s1.strCat(s2);s1.show();//测试字符串拷贝函数cout<<"\n//测试字符串拷贝函数"<<endl;;s1.strCpy(s2);s1.show();cout<<"//测试完毕!"<<endl;return 0;}。
C++语言string类的实现(完整源代码)
MyString::~MyString() {
delete[] p_str; }
size_t MyString::length() {
return strcmp(lhs.p_str,rhs.p_str)>=0; }
//子串操作
//返回一个 MyString 类型的字符串,它包含源字符串中从下标 pos 开始的 n 个 字符 MyString MyString::substr(size_t pos,size_t n) {
assert(pos+n<=strLength); MyString ret; ret.strLength = n; ret.p_str = new char[ret.strLength+1]; for (size_t i=0;i!=n;++i)
//赋值操作符 MyString& MyString::operator=(const MyString& str) {
if(this!=&str) {
if(strLength<str.strLength) {
delete[] p_str; p_str = new char[str.strLength+1]; } strLength = str.p_str); } return *this; }
//子串操作 MyString substr(size_t,size_t); //添加操作 MyString& append(const MyString&); //插入操作 MyString& insert(size_t,const MyString&); //替换操作 MyString& assign(const MyString&,size_t,size_t); //删除操作 MyString& erase(size_t,size_t);
一个简单实现的string类
⼀个简单实现的string类为了复习c++知识,简单的实现⼀个string类,类名为CMyString 环境说明:windows 7 64位和 CentOS Linux release 7.6.1810 (Core)开发⼯具:Visual Studio 2015 和 g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)CMyString类的头⽂件CMyString.h1 #include <iostream>23 #ifndef __C_MY_STRING__4#define __C_MY_STRING__56class CMyString7 {8public:9//默认构造函数10 CMyString();11//带参数的构造函数12 CMyString(const char* str);13//拷贝构造函数14 CMyString(const CMyString&);15//析构函数16 ~CMyString();1718//重载赋值运算符19 CMyString& operator=(const CMyString&);20 CMyString& operator=(const char*);21//重载[]运算符(可修改)22char& operator[](const int);23//重载[]运算符(不可修改)24const char& operator[](const int) const;25//重载==运算符26bool operator==(const CMyString&) const;27//重载!=运算符28bool operator!=(const CMyString&) const;29//重载>运算符30bool operator>(const CMyString&) const;31//重载<运算符32bool operator<(const CMyString&) const;33//重载>=运算符34bool operator>=(const CMyString&) const;35//重载>=运算符36bool operator<=(const CMyString&) const;37//重载<<运算符38 friend std::ostream& operator<<(std::ostream&, const CMyString &);39private:40char* m_pdata;41 };4243#endif// !__C_MY_STRING__CMyString类的实现⽂件CMyString.cpp1 #include "CMyString.h"2 #include <cstring>3using namespace std;45 CMyString::CMyString()6 {7//创建⼀个空的data,占⼀个字节空间8 m_pdata = new char[1];9 m_pdata[0] = '\0';10 cout << "默认构造函数" << endl;11 }1213 CMyString::CMyString(const char * str)14 {15if (str)16 {17int len = strlen(str);18 m_pdata = new char[len+1];19 strncpy(m_pdata, str, len);20 m_pdata[len] = '\0';21 }22else23 {24//创建⼀个空的data,占⼀个字节空间25 m_pdata = new char[1];26 m_pdata[0] = '\0';27 }28 cout << "带参数的构造函数" << endl;29 }3031 CMyString::CMyString(const CMyString & inString)32 {33int len = strlen(inString.m_pdata);34 m_pdata = new char[len +1];35 strncpy(m_pdata, inString.m_pdata, len);36 m_pdata[len] = '\0';37 cout << "拷贝构造函数" << endl;38 }3940 CMyString::~CMyString()41 {42delete[] m_pdata;43 m_pdata = nullptr;44 cout << "析构函数" << endl;45 }4647 CMyString & CMyString::operator=(const CMyString & instring)48 {49 cout << "重载赋值运算符1" << endl;50//如果是同⼀个对象,不做处理直接返回51if (this == &instring)52 {53return *this;54 }5556//使⽤⼊参通过拷贝构造函数创建⼀个临时对象57 CMyString tmpString(instring);58//修改data指针,当函数结束时,tmpString对象过期,将⾃动调⽤析构函数,把原来当前对象的data地址释放掉 59char* tmpData = tmpString.m_pdata;60 tmpString.m_pdata = m_pdata;61 m_pdata = tmpData;62return *this;63 }6465 CMyString & CMyString::operator=(const char * str)66 {67 cout << "重载赋值运算符2" << endl;68delete m_pdata;69if (str)70 {71int len = strlen(str);72 m_pdata = new char[len + 1];73 strncpy(m_pdata, str, len);74 m_pdata[len] = '\0';75 }76else77 {78//创建⼀个空的data,占⼀个字节空间79 m_pdata = new char[1];80 m_pdata[0] = '\0';81 }82return *this;83 }8485char & CMyString::operator[](const int index)86 {87 cout << "重载[]运算符(可修改)" << endl;88return m_pdata[index];89 }9091const char& CMyString::operator[](const int index) const92 {93 cout << "重载[]运算符(不可修改)" << endl;94return m_pdata[index];95 }9697bool CMyString::operator==(const CMyString & inString) const98 {99 cout << "重载==运算符" << endl;100return !strcmp(m_pdata, inString.m_pdata);101 }102103bool CMyString::operator!=(const CMyString & inString) const104 {105 cout << "重载!=运算符" << endl;106return strcmp(m_pdata, inString.m_pdata);107 }108109bool CMyString::operator>(const CMyString & inString) const110 {111 cout << "重载>运算符" << endl;112return (strcmp(m_pdata, inString.m_pdata) > 0);113 }114115bool CMyString::operator<(const CMyString & inString) const116 {117 cout << "重载<运算符" << endl;118return (strcmp(m_pdata, inString.m_pdata) < 0);119 }120121bool CMyString::operator>=(const CMyString & inString) const122 {123 cout << "重载>=运算符" << endl;124return (strcmp(m_pdata, inString.m_pdata) >= 0);125 }126127bool CMyString::operator<=(const CMyString & inString) const128 {129 cout << "重载<=运算符" << endl;130return (strcmp(m_pdata, inString.m_pdata) <= 0);131 }132133 ostream & operator<<(ostream & os, const CMyString & instring)134 {135 os << instring.m_pdata;136return os;137 }CMystring类的测试⽂件testCMyString.cpp1 #include <iostream>2 #include "CMyString.h"34using namespace std;5int main()6 {7//带参数的构造函数8const CMyString myString1("abc");9//默认构造函数10 CMyString myString2;11//重载赋值运算符212 myString2 = "def";13//默认构造函数14 CMyString myString3;15//重载赋值运算符1,(这个类的内部实现是先调⽤拷贝构造函数⽣成⼀个临时变量,再使⽤临时变量通过把内容给到myString3,再把临时变量析构)16 myString3 = myString2;17//拷贝构造函数18 CMyString myString4(myString2);19 myString3[2] = 'e';2021 cout << myString1 << "\t" << myString2 << "\t" << myString3 << endl;22//由于myString1带了const修饰,因此是不可修改的,调⽤不可修改的重载[]运算符23 cout << myString1[2] << endl;24 cout << (myString1 != myString2) << endl;25 cout << (myString1 == myString2) << endl;26 cout << (myString1 < myString2) << endl;27 cout << (myString1 <= myString2) << endl;28 cout << (myString1 > myString2) << endl;29 cout << (myString1 >= myString2) << endl;30return0;31 }VS2015测试结果:CentOS编译g++ -o testCMyString -std=c++0x ./*.cpp 测试结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ccnu_hupo_cpp_class_tst6exercise2_by:lele_2013_10_30
new不忘delete
Design the string class in the C++ library by providing your own implementation for the following functions (name your class MyString):
MyString();//构造
MyString(const char* cString);//地址不能变
char at(int index) const;//输入数组下标,返回字符
int length() const;//长度
void clear();//清空len=0
bool empty() const;//是否清空?len不变
int compare(const MyString& s) const;//
int compare(int index, int n, const MyString& s) const;
void copy(char s[], int index, int n);
char* data() const;
int find(char ch) const;
int find(char ch, int index) const;
int find(const MyString& s, int index) const;
*/
#include<iostream>
#include<string.h>
using namespace std;
class MyString
{
public:
MyString();
MyString(const char* cString);
char at(int index) const;//
int length() const;
void clear();
bool empty() const;
int compare(const MyString& s) const;
int compare(int index, int n, const MyString& s) const;
void copy(char s[], int index, int n);
char* data() const;
int find(char ch) const;
int find(char ch, int index) const;
int find(const MyString& s, int index) const;
~MyString()
cout<<"delete..."<<endl;
delete []a;
}
private:
char *a;
int len;
};
MyString::MyString(const char* cString)
{
if (cString==NULL)
{
a=new char[1];
a[0]=0;
int len=0;
}
else
{
a=new char [strlen(cString)+1];
strcpy(a,cString);
len=strlen(cString);
}
}
char MyString::at(int index) const
{
if(len==0)
{cout<<"no char in string"<<endl;
return 0;
}
if(index>len)
{
cout<<"the maximun array exceed"<<endl;
return 0 ;
}
else
{
return a[index-1];
}
}
int MyString::length() const
return len;
}
void MyString::clear()
{
if(!a)
{
delete []a;
a=NULL;
}
len=0;
//a=" ";
}
bool MyString::empty() const
{
if(len==0)
return true;
else
return false;
}
int MyString::compare(const MyString& s) const
{
int m=this->len;int n=s.len;
for(int i=0;i<m&&i<n;i++)
{
if(s.a[i]==a[i])
continue;
else if(s.a[i]<a[i])
return 1;
else
return -1;
}
return 0;
}
int MyString::compare(int index, int n, const MyString& s) const {
int m=len,k=s.len;
if(index+n>m||index+n>k)
{
cout<<"cannot compare!"<<endl;
///I dont know how to solve it
}
for(int i=index-1,j=0;i<n+index;i++,j++)
{
if(s.a[j]==a[i])
continue;
else if(s.a[j]<a[i])
return 1;
else
return -1;
}
return 0;
}
void MyString::copy(char s[], int index, int n) {
if(n>=len)
{cout<<"the maximun array exceed"<<endl;} else if(n+index-1>len)
{
cout<<"the maximun array exceed"<<endl;
return;
}
else
{
for(int i=n-1,j=0;i<n+index-1;i++,j++)
s[j]=a[i];
}
}
char* MyString::data() const
{
return a;
}
int MyString::find(char ch) const
{
for(int i=0;i<len;i++)
{
if(ch==a[i])
return i+1;
}
return 0;
}
int MyString::find(char ch, int index) const
{
if(index>len||index<1)
{
cout<<"the index num is should be 1~ "<<len<<endl;
return 0;
}
for(int i=index-1;i<len;i++)
{
if(ch==a[i])
return i+1;
}
return -1;
}
int MyString::find(const MyString& s, int index) const
{
if(index>s.len||index<1)
{
cout<<"the index num is should be 1~ "<<s.len<<endl;
return 0;
}
char ch=s.a[index-1];
for(int i=0;i<len;i++)
{
if(ch==a[i])
return i+1;
}
return 0;
}。