自定义实现字符串string的接口

用char*管理String类的内存,new动态分配,在析构函数中delete char*指向的new出来的内存,一个string类需要实现那些接口可参考标准库里的string:  http://www.cplusplus.com/reference/string/string/

  • 实现思路是:在创建String、String需要伸缩(如赋值时需要调整大小、字符串相加也需要更大的空间)时重新new内存,并释放掉原有内存;标准库string的空间是预先分配的,有多余的空间可用,如果string需要伸缩,就开辟新的内存空间。
  • >>重载的思路是:用cin.getline来读取标准输入到字符指针指向的空间——空间有个预设的大小,如100,可以接收包含有空格的字符串
  • String初始化为空字符串("\0"或 ""是等价的),也需要new字符数组,这样才能delete,如果用char *data="\0",不能用delete释放不是new出来的内存
  • []需要重载两个版本,const版本 const char& operator[](size_t index) const; const成员函数的this指针隐式的转换为指向常量的指针: operator(const  String *this, size_t index),const对象只能调用const menber function
  • 不需要重载解引用*和取地址&,它们对自定义的类型也支持
  • +=调用了operator+,问为什么operator+要返回引用,而不能返回对象?
  • 没有实现重载的relational operators
  • 相比标准库,自定义的String实现的接口很少,似乎什么都做不了,只能创建,赋值,输出,访问元素,甚至连标准库里的string开发中也不好用:为什么大多数的C++的开源库都喜欢自己实现一个string
  • new管理内存是否存在memory leak,是否有隐含的错误?

  1 #include<iostream>
  2 #include<string>
  3 #include<vector>
  4 #include<algorithm>
  5 #include<cstdio>
  6 #include<complex>
  7 #include<new>
  8 #include<memory>
  9 #include<exception>
 10 using namespace std;
 11 // interfaces should supported
 12 //用char*管理内存
 13 class String
 14 {
 15 public:
 16     String();
 17     String(const char*s);
 18     String(size_t n, const char c);//用字符c填充String
 19     String(const String&s);
 20     String& operator=(const String&rhs);
 21     String& operator=(const char*c);
 22     char& operator[](size_t index);//要提供[]的两个版本
 23     const char& operator[](size_t index)const;
 24     String & operator*();//解引用重载是多余的,语言本身支持对所有类型的指针解引用,包括了自定义类型
 25     String& operator+(const String&rhs);
 26     String& operator+=(const String&rhs);
 27     bool operator==(const String&rhs);
 28     friend bool operator<(const String&lhs, const String&rhs);
 29     friend ostream& operator<<(ostream& os, const String&rhs);
 30     friend istream& operator>>(istream& in, String&rhs);
 31     size_t size(); //如果是size_t length()会导致。。。。。
 32     bool empty();
 33     const char* c_str();
 34     ~String();
 35 private:
 36     char * data;
 37     size_t length;
 38
 39 };
 40 String::String() //类外面定义menber function ,域作用符
 41 {
 42     this->data = new char[1](); //空字符串 ,strlen对data运算得到的长度为0
 43     data[0] = ‘\0‘;
 44     (*this).length = 0;
 45 }
 46 String::String(const char*s) //允许implicit类型转换
 47 {
 48     // 不能用data=s;这导致创建的String对象与s共享了字符,而不是副本
 49     length = strlen(s);
 50     data = new char[length + 1]();//value initialization,申请了字符指针指向的内存区域
 51     strcpy(data, s);
 52     *(data + length) = ‘\0‘;
 53 }
 54 String::String(size_t n, const char c)
 55 {
 56     length = n;
 57     data = new char[length + 1]();
 58     for (size_t i = 0; i < length;i++)
 59     {
 60         *(data + i) = c;
 61     }
 62     *(data + length) = ‘\0‘;
 63 }
 64 String::String(const String&s)
 65 {
 66     length = s.length;
 67     data = new char[length + 1](); //untill deconstructor to destory newed memory
 68     for (size_t i = 0; i < length;i++)
 69     {
 70         data[i] = s.data[i];
 71     }
 72     data[length] = ‘\0‘;
 73 }
 74 String& String::operator=(const String&rhs)
 75 {
 76     if (this->data == rhs.data) return *this;// 支持*this==rhs的关系比较操作吗?
 77
 78     //assign 不是初始化,不需要申请内存空间,拷贝构造需要 ,但是原String与rhs大小可能不一样
 79     delete[]data; //会导致重复删除data所指内存吗??
 80
 81     length = rhs.length;
 82     data = new char[length + 1]();
 83     //如果发生异常
 84
 85     if (data == NULL)  throw "allocate memory failed in copy ctr";
 86     for (size_t i = 0; i < length; i++)
 87     {
 88         data[i] = rhs.data[i];
 89     }
 90     data[length] = ‘\0‘;
 91 }
 92 char& String::operator[](size_t index)
 93 {
 94     if (index >= length||index<0) throw "out of range";
 95     return data[index];//如果data指向的字符串为"dhaj"这种不可修改的,会导致返回的引用不能有s[i]=‘c‘的修改操作
 96 }
 97 String& String:: operator*()
 98 {
 99     if (this == NULL) throw "dereferrence null pointer ";
100     return *this;
101 }
102 String& String::operator+(const String&rhs)//a+b形式,也不改变a
103 {
104     String s;//不可伸缩,不能用来存a+b的结果
105     int len = strlen(this->data) + strlen(rhs.data);
106     char *p = new char[len + 1]();
107     for (size_t i = 0; i < strlen(this->data); i++)
108     {
109         p[i] = this->data[i];
110     }
111     for (int j = strlen(this->data),i=0; j < len; j++,i++)
112     {
113         p[j] = rhs.data[i];
114     }
115     p[len] = ‘\0‘;
116     String *t = new String(p); //new了一个p,一个t,可以释放掉p,因为t是p的副本
117     delete[]p;
118     return *t;//返回了堆上的引用,再c=a+b这种使用后,c是会析构的,但中间这个看不见的对象不会析构
119 }
120 String& String::operator+=(const String&rhs)
121 {
122     *this = *this + rhs;
123     //释放掉原来的a,申请新空间
124     return *this;
125 }
126 bool String::operator==(const String&rhs)//比较是否相等,而不是相同
127 {
128     if (this->length != rhs.length) return false;
129     int i = 0;
130     for (; (*this).data[i] == rhs.data[i]; i++);
131     if (i != (rhs.length + 1)) return false;
132     else return true;
133 }
134 bool operator<(const String&lhs, const String&rhs)
135 {
136     return true;
137 }
138  ostream& operator<<(ostream& os, const String&rhs) //申明为友元函数。调用方式为cout<<s,申明为men fun,调用形式为s<<cout
139 {
140     os << rhs.data;//输出null pointer会未定义行为
141     return os;
142 }
143  istream& operator>>(istream& is, String&rhs)
144  {//输入一个字符串到字符指针,字符指针需要预先分配一定大小的空间,如何根据输入的字符串调整空间大小
145      delete[]rhs.data;
146      rhs.data = new char[50]();
147      is.getline(rhs.data, 50);//最后位置自动置为‘\0‘,所以最多存49个字符,可接收空格
148      rhs.length = strlen(rhs.data);
149      return is;
150  }
151 size_t String::size()
152 {
153     return length;
154 }
155 bool String::empty()
156 {
157     if (length == 0) return true;
158     else return false;
159 }
160 const char* String::c_str()//返回指向对象局部部分的引用,指针,能用来修改原对象吗?
161 {//如果为空串,也要返回data
162     return data;
163
164 }
165 String::~String()
166 {    //    析构会发生错误吗?
167     //String创建时会new内存,当程序结束或局部String对象退出作用域时调用析构函数,释放该内存
168     delete[]data; //如果String不是new出来的, 指针p指向它,delete p会导致错误,new出来的可以调用delete,这时会调用~String
169     data = NULL;
170 }
171
172 //int  main()
173 //{
174 //    String s;
175 //    cout << s << endl;
176 //    cout << strlen(s.c_str()) << endl;
177 //    String s1 = "whah";
178 //    cout << s1 << endl;
179 //    String s2 = s1;
180 //    cout <<"s2 length:"<< s2.size() << endl;
181 //    s = s2;
182 //    cout << "用s2赋值后的s: " << s << endl;
183 //    String s3(10, ‘c‘);
184 //    cout << "字符填充初始化s3: " << s3 << " " << "s3 len= " << s3.size() << endl;
185 //    s3[0] = ‘a‘;
186 //    cout << "下标修改s3后: " << s3 << endl;
187 //    String s4 = s2 + s3+"ad"; //支持连续的+
188 //    cout << s4 << endl;
189 //    String *sp = &s4;
190 //    cout << *sp << endl;
191 //    cout << strlen((*sp).c_str()) << endl;
192 //    String *q = new String(*sp);
193 //    cout << *q << endl;
194 //    delete q;
195 //
196 //    char *sq = const_cast<char*> (s4.c_str());
197 //    sq[0] = ‘l‘;
198 //    cout << sq << endl;
199 //    cout << s4 << endl;
200 //    const char *cptr = s2.c_str();
201 //    string s5 = "";
202 //    string s6 = "\0";
203 //    cout << s5 << "**" << s6 << s5.size() << s6.size() << endl;
204 //    string str = "jadj";
205 //    char *sptr = const_cast<char *> (str.c_str());
206 //    sptr[0] = ‘d‘;
207 //    cout << sptr << " " << str << endl;
208 //    String s7(s2);
209 //    s7 += s4;
210 //    cout << "s7: " << s7.size() << s7 << endl;
211 //    const String s8("daj");
212 //    //s8[0]; 对const对象的[]调用,不能用non-const menber版本的operator[],要提供 const char& operator[]() const重载版本
213 //    //s8 = "djwajk0";
214 //}
215
216 int main()
217 {
218     string s2;
219     cin >> s2;
220     cout << s2 << endl;
221     String s, s1;
222     cin >> s >> s1;//用Enter间隔字符串,可接含有空格的字符串
223     cout << s <<"\n"<< s1 << endl;
224     cout << s1.size() << endl;
225 }

String类

时间: 2024-08-28 20:39:22

自定义实现字符串string的接口的相关文章

python 字符串 string

字符串 string 语法: a = 'hello world!' b = "hello world!" 常用操作: 1.乘法操作是将字符串重复输出2遍 >>> a='abc'*2 >>> a'abcabc' 2.切片操作,将字符串从索引下标2开始切片取到最后. >>> print("helloworld"[2:]) lloworld 3.in操作,判断字符串abc是否存在于字符串abcdefg中,存在则返回Tr

java学习-关于字符串String

有必要总结记录一下java的学习,否则,永远只是记忆碎片化和always google(费时) 刚好,小伙伴给了一份自己做的review,在学习的过程中,update一下自己的见解和学习内容: 关于String: 1 package string_keywords; 2 /** 3 * 参考url: http://developer.51cto.com/art/201106/266454.htm 4 * 5 * 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.cla

C/C++中字符串String及字符操作方法

本文总结C/C++中字符串操作方法,还在学习中,不定期更新... 字符串的输入方法 1.单个单词可以直接用std::cin,因为:std::cin读取并忽略开头所有的空白字符(如空格,换行符,制表符),读取字符直至再次遇到空白字符,读取终止.所以cin只能读取单个单词.显然可以多次使用cin来获取多个单词: 2.多个单词使用函数std::getline(std::cin, s)请看下面代码: #include <iostream> #include <string> int mai

C#如何生成JSON字符串提交给接口(服务器)

第一章:C#如何拿到从http上返回JSON数据? 第二章:C#如何解析JSON数据?(反序列化对象) 第三章:C#如何生成JSON字符串?(序列化对象) 第四章:C#如何生成JSON字符串提交给接口(服务器)? 上一篇文章中我们写的C#生成JSON字符串,那么我们生成的字符串要干嘛呢?当然是将数据提交给服务器啦.一般用过接口来接受这个JSON. 这里我们会用到第一章中的一个 类.HttpUitls里面的Post方法. 非常简单: public static string Post(string

C++中字符数组和字符串string

字符数组 C++中字符数组用char str[]可以用来表示一个字符串. (1)   数组的大小和字符串的长度. 数组的大小一定要大于字符串的长度,因为系统会自动补上一个'\0'作为字符串的结束标志.当然对于未初始化的也补'\0'. #include <iostream> #include <string> using namespace std; int main() { char str[11] = "I am happy"; // 系统会自动补上'\0'空

istringstream字符串流,实现类似字符串截取的功能,字符串流中的put,str()将流转换成为字符串string

 1. istringstream字符串流 #include <iostream> #include <sstream> #include <string> using namespace std; struct MyStruct { string str1, str2, str3; double db; int num; char ch; }; void main() { string  mystring("china  google microsoft

c/c++日期时间处理与字符串string转换

在c/c++实际问题的编程中,我们经常会用到日期与时间的格式,在算法运行中,通常将时间转化为int来进行计算,而处理输入输出的时候,日期时间的格式却是五花八门,以各种标点空格相连或者不加标点. 首先,在c中,是有一个标准的日期时间结构体的,在标准库wchar.h内,我们可以看到结构体tm的声明如下: 1 #ifndef _TM_DEFINED 2 struct tm { 3 int tm_sec; /* seconds after the minute - [0,59] */ 4 int tm_

字符串String

字符串String思维导图 创建字符串 String类即字符串类型,像基本数据类型一样使用,用双引号括起来进行声明.在Java中用String类的构造方法来创建字符串变量. 1.String() 一个String对象,可表示一个空字符序列. 例 :使用String()方法初始化一个新创建的String对象. String s=new String(); 2.String(char a[]) 用一个字符数组a创建String对象. 例 :使用String(char a[])方法创建String对象

《Javascript权威指南》学习笔记之十一:处理字符串---String类和正则表达式

一.正则表达式的基本语法 1.概念:正则表达式由普通字符和特殊字符(元字符)组成的文本模式,该模式描述在查找字符串主体时待匹配的一个或者多个字符串.正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配. 普通字符包括所有的大小写字母字符.所有数字.所有标点符号及一些特殊符号.普通字符本身可以组成一个正则表达式,也可以和元字符组合组成一个正则表达式:而元字符则具有特殊的含义,包括().[].{}./.^.$.*.+.?...|.-.?:.?=.?! 2.基本语法 3.优先权含义 二.使用