hello ,好久不见!
目录
1.void string::Insert(size_t pos, char ch)
2.void string::Insert(size_t pos, const char* str)
3.到底在哪里定义static const size_t npos ?
正文开始——
一、string实现时要注意的细节点
1.void string::Insert(size_t pos, char ch)
void string::Insert(size_t pos, char ch)
{
//对于任何的插入操作都要先判断空间是否充足提前预留足够的空间
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
size_t end = _size+1;
//预留出pos位置的空间进行插入操作
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
_size++;
}
2.void string::Insert(size_t pos, const char* str)
第一种方法
跟我们前面讲的很相似,利用强转来解决类型的问题
void string::Insert(size_t pos, const char* str)
{
//还是先扩容
size_t len = strlen(str);
if (_size + len > _capacity)
{
//扩容
size_t newCapacity = 2 * _capacity;
//扩2倍不够直接需要多少扩多少
if (newCapacity < _size + len)
newCapacity = _size + len;
reserve(newCapacity);
}
int end = _size;
while (end >= (int)pos)
{
_str[end + len] = _str[end];
end--;
}
//将str进行挨个插入
for (size_t i = 0; i < len; i++)
{
_str[pos + i] = str[i];
}
_size += len;
}
第二种方法
是将end-len移到end指向的数据
void string::Insert(size_t pos, const char* str)
{
//还是先扩容
size_t len = strlen(str);
if (_size + len > _capacity)
{
//扩容
size_t newCapacity = 2 * _capacity;
//扩2倍不够直接需要多少扩多少
if (newCapacity < _size + len)
newCapacity = _size + len;
reserve(newCapacity);
}
size_t end = _size + len;
while (end >= pos+len) //end-len==pos,end==pos+len,
{
_str[end] = _str[end-len];
end--;
}
//将str进行挨个插入
for (size_t i = 0; i < len; i++)
{
_str[pos + i] = str[i];
}
_size += len;
}
3.到底在哪里定义static const size_t npos ?
(1)所有的.c或者.cpp文件在编译链接的时候都会生成.o文件(VS下叫.obj文件),.h文件在预处理的时候就在两个.cpp文件里面展开了,我们在类域外面定义的npos就会在两个.cpp里面展开,当两个.cpp文件链接合并生成可执行程序的时候,就构成了下面报错里面的重定义,所以当静态成员变量定义和声明分离的时候要在.cpp文件里面定义,不能像以前那样在类里面声明在类外面定义。对于npos要加上const,不可修改。(2)同时npos要在定义的时候给值,对于const对象是只有定义时一次初始化的机会。(3)特殊的一点,对于静态的const(只有整型类型的数据才可以的,这算是一个特殊处理)成员变量可以在声明的时候给缺省值,那么在定义的时候就不可以再给值了。
总结一下,对于这种情况有两种解决办法
4.实现取域名
//取域名
void test_string4()
{
lrq::string s1 = "https://mpbeta.csdn.net/mp_blog/creation/editor/147116669?spm=1000.2115.3001.4503";
size_t pos1 = s1.find(':');
size_t pos2 = s1.find('/', pos1 + 3);
//判断是否找到目标字符
if (pos1 != string::npos && pos2 != string::npos)//npos受类域影响
{
lrq::string domain = s1.substr(pos1 + 3, pos2 - (pos1 + 3));//注意pos1和pos2到底指向哪些个位置
cout << domain.c_str() << endl;
}
}
5.拷贝—拷贝构造和赋值
我们不显示写拷贝构造和赋值拷贝(都是一种赋值行为),编译器默认都会进行浅拷贝。(1)像上面的代码将s1拷贝赋值给s2,编译器默认的浅拷贝会导致s2和s1指向同一块空间,函数结束的时候会先析构s2再析构s1导致同一块空间析构两次就会出现上面的运行崩溃;(2)还会导致内存泄漏,s2之前的空间没有得到释放。(如果一个类需要显示写析构,那么一般就需要写拷贝构造和赋值)
//s1 = s3
string& string::operator=(const string& s)
{
if (this != &s)
{
//上来先将s1给释放掉
delete[] _str;
_str = new char[s._capacity + 1];//预留一个\\0的空间
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
6.流插入
我们输入的是abcd efg,中间包含一个空格字符,但是ch好像并没有从缓冲区里面提取到空格,看下图,记住,cin在直接使用流提取的时候无论输入任何类型,int,char,它都会默认忽略掉空格和换行,规定认为空格和换行都是多个值之间的分割,也就无法判断什么时候结束,所以我们要进行代码的修改。
我们使用istream类里面的get,可以提取到空格和换行
//cin>>str,这个实现的功能和前面讲的getline很像,只不过结束字符不同而已,我们要融会贯通一下
istream& operator>>(istream& is, string& str)
{
str.clear();//清空str里面原来的字符,否则会继续加在str上面,这是实现和STL里面的string::>>一样的效果
char ch;
ch = is.get();
while (ch != ' ' && ch != '\\n')
{
str += ch;
ch = is.get();
}
return is;
}
优化一下:
istream& operator>>(istream& is, string& str)
{
str.clear();
int i = 0;
char buff[256];
char ch;
ch = is.get();
while (ch != ' ' && ch != '\\n')
{
// 放到buff
buff[i++] = ch;
if (i == 255)
{
buff[i] = '\\0';
str += buff;
i = 0;
}
ch = is.get();
}
if (i > 0)
{
buff[i] = '\\0';
str += buff;
}
return is;
}
7.三个swap
二、
2.1 经典的string类问题
string
类进行了简单的介绍,大家只要能够正常使用即可。在面试中,面试官总喜欢让学生自己来模拟实现string
类,最主要是实现
string
类的构造、拷贝构造、赋值运算符重载以及析构函数。大家看下以下string
类的实现是否有问题?
平台声明:以上文章转载于《CSDN》,文章全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,仅作参考。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/lrq13965748542/article/details/147116669



相关文章
- 2025年最新MacBook苹果电脑安装JDK8、JDK11、JDK17、JDK22教程,配置环境变量 + 快速切换JDK版本 2025-04-27
- 解决Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ‘com.sun.tools.javac.tre 2025-04-27
- 2024第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组 2025-04-27
- 详解关于VS配置好Qt环境之后但无法打开ui界面 2025-04-27
- C++之红黑树 2025-04-27
- JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题 2025-04-27
- 【Java开发日记】6个Java 工具,轻松分析定位 JVM 问题 ! 2025-04-27
- 【第52节】Windows编程必学之从零手写C++调试器下篇(仿ollydbg) 2025-04-27
- 2023第十四届蓝桥杯大赛软件赛国赛C/C++ 大学 B 组(真题&题解)(C++/Java题解) 2025-04-27
- 【C++】第十节—string类(完结篇)——详解+代码示例 2025-04-27