本质:string是c++类型的字符串,其本质是一个封装好的类
string和char的区别:
1.char 是一个指针
2.string是一个内部封装了char* 的类,管理这个字符串,是一个char型容器
特点:
string类内部封装了很多成员函数
例如:查找find,拷贝copy,删除delete,替换replace,插入insert
string管理char所分配的内存,不用担心赋值越界和取值越界等问题,由类内部负责
string();//创建一个空的字符串例如:string str;
string(const string &str)//使用一个string 对象去初始化另外一个string 对象
string(const char*str)//使用字符串s初始化
string (int n,char c)//使用n个字符串c初始化
下面我们来实验
1.string ()
#include<iostream>
using namespace std;
#include<string>
int main()
{
string s;
cout << s;
}
运行结果:
我们可以发现字符串是空的
2.string (const string&str);
#include<iostream>
using namespace std;
int main()
{
string s = "abvede";
string s1(s);
cout << s1;
}
运行结果:
3.string (const char*str);
#include<iostream>
using namespace std;
int main()
{
string s1("abdedf");
cout << s1;
}
运行结果:
4.string (int n,char c)
#include<iostream>
using namespace std;
int main()
{
string s1(3, 'a');
cout << s1;
}
string &operator=(const char*s)//将char*类型字符串赋值给当前字符串
string &operator=(const string &s)把字符串s赋值给当前字符串
string& operator=(char c)把字符赋值给当前字符串
string &assign (const char*s)把字符串s赋给当前字符串
string &assign(const char*s,int n)把字符串s的前n个字符赋给当前字符串
string &assign(const string&s)把字符串s赋给当前字符串
string &assign(int n,char c)用n个字符赋给当前字符串
string &assign(const string &s,int start,int n)将s从start开始n个字符赋值给字符串
例:string &operator=(const char*s)
#include<iostream>
using namespace std;
int main()
{
string s = "aveddfhf";
cout << s << endl;
return 0;
}
运行结果:
2.string &operator=(const string&s)
#include<iostream>
using namespace std;
int main()
{
string s = "aveddfhf";
string s1;
s1 = s;
cout << s1<< endl;
return 0;
}
运行结果:
3.string&operator=(char c);
#include<iostream>
using namespace std;
int main()
{
string s1;
s1 = 'a';
cout << s1 << endl;
return 0;
}
4.string &assign(const char*s)
#include<iostream>
using namespace std;
int main()
{
string s1;
s1.assign("djfgfjdfgh");
cout << s1 << endl;
}
运行结果:
//string存取字符操作
//char&operator[](int n);通过[]的方式取字符
//char&at(int n);通过at的方式获取字符
例:
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
for (int i = 0; i < str.size(); i++) {
cout << str[i] << endl;
}
}
运行结果:
通过at 的方式来获取:
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
for (int i = 0; i < str.size(); i++) {
cout << str.at(i) << endl;
}
}
运行结果:
我们可以发现两者的运行结果没有取别,拿这两种方式有什么区别吗?
[]和at的区别:
[]访问越界程序会直接挂掉,而at访问越界会抛出异常out_of_range
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
cout << str[100] << endl;
}
运行结果:
我们可以看到此时程序直接崩溃了
通过at的方式来获取:
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
try {
cout << str.at(100) << endl;
}
catch (out_of_range& e) {
cout << e.what() << endl;
}
}
运行结果:
string 中如何访问最后一个元素或者第一个元素
访问第一个元素:
1.通过[]
2.通过at
3.通过成员函数的方法 对象.front();
4.通过迭代器
访问最后一个元素与访问第一个元素类似
1.通过[]
2.通过at
3.通过成员函数的方法
4.通过迭代器
例:
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
cout << str[0] << endl;//通过[]
cout << str.at(0) << endl;//通过at
cout << str.front() << endl;//通过成员函数
cout << *str.begin() << endl;//通过迭代器
return 0;
}
运行结果:
访问最后一个元素:
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
cout << str[str.size() - 1] << endl;
cout << str.at(str.size() - 1) << endl;
cout << str.back() << endl;
cout << *(str.end() - 1) << endl;//注意str.end()返回的是最后一个元素的下一个位置
return 0;
}
运行结果:
2.string对象的几种遍历方式
1.通过[]或者at加for或者while循环遍历
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
for (int i = 0; i < str.size(); i++) {
cout << str[i];
}
}
运行结果:
2.通过迭代器
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
string::iterator it = str.begin();
while (it != str.end()) {
cout << *it;
it++;
}
return 0;
}
运行结果:
3.通过范围for来遍历
#include<iostream>
using namespace std;
int main()
{
string str = "hello world";
for (auto& e : str) {
cout << e;
}
}
运行结果:
4.通过algorithm里面的for_each来遍历
#include<iostream>
using namespace std;
#include<algorithm>
void myprint(char ch) {
cout << ch;
}
int main()
{
string str = "hello world";
for_each(str.begin(), str.end(), myprint);
}
运行结果:
/string 类中的拼接操作
//string &operator+=(const char*str)重载+=
//string &operator+=(const string&str)重载+=
//string &operator+=(const char ch)重载+=
//string &append (const char*str)把字符串str连接到当前字符串结尾
//string &append(const char*str,int n)把字符串str前n个字符连接到当前字符串结尾
//string &append(const string&s)和+=一样
//string&append(const string&s int pos,int n)把字符串s中从pos位置开始的n个字符连接到当前字符串
//string &append(int n,char c)在当前字符串结尾添加n个字符c
在这里就不一一测试
string&operator(const char ch)
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s = "ab";
s += 'c';
cout << s << endl;
}
运行结果:
string&operator+=(const char*str)
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s = "ab";
s += "abcdeff";
cout<<s<<endl;
}
运行结果:
string &append(const char*str,int n);
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s = "ab";
s.append("abcdef", 3);
cout << s << endl;
}
运行结果:
string&append(int n,char ch);
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s = "ab";
s.append(3, '0');
cout << s << endl;
}
运行结果:
//int find(const string&str,int pos=0)const查找str第一次出现的位置,默认从0号位置开始找
//int find(const char*s,int pos=0)查找s第一次出现的位置从pos位置开始找
// int find(const char*s,int pos,int n)从pos位置查找s的前n个字符第一次出现的位置
//int find(const char c,int pos=0)查找字符c第一次出现的位置
//int rfind(const string&str,int pos=npos)const查找str最后一次出现的位置,从pos位置开始找
//int rfind(const char*s,int pos=npos)const 查找s最后一次出现的位置,从pos位置开始找
//int rfind(const char*s,int pos,int n)从pos位置开始查找s前n个字符第一次出现的位置
//int rfind(const char ch,int pos=0)const 查找字符ch最后一次出现的位置
//string &replace (int pos,int n,const string&str)替换从pos位置开始n个字符为字符串
//string &replace (int pos,int n,const char*s)替换从pos开始的n个字符为字符串s
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s1="abcdef";
string s2 = "abc";
int ret = s1.find(s2);
cout << ret;
}
运行结果:
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s1="abcdef";
string s2 = "abc";
int ret = s1.find(s2);
cout << ret;
}
我们在s1中查找s2中从0号位置开始
运行结果:
int rfind(string&s,int pos=npos);
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s1="abcdefabc";
string s2 = "abc";
int ret = s1.rfind(s2);
cout << ret;
}
运行结果:
如果没有找到则会返回-1
find和rfind的区别:
find 是从从左往右找,而rfind是从右往左找
string substr(int pos=0,int n=npos)const 返回由pos开始的n个字符组成的字符串
例
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s1="abcdefabc";
cout << s1.substr(0, 3);
}
运行结果:
/string&insert(int pos,const char*s)插入字符串
//string&insert(int pos,const string&s)插入字符串
//string&insert(int pos,int n,char c)在指定位置插入n个字符c
//string&erase(int pos,int n=npos)删除从pos开始的n个字符
在这里就不测试了可以自己下来测试一下
string.c_str是Borland封装的String类中的一个函数,它返回当前字符串的首字符地址。
c_str函数的返回值是const char的,不能直接赋值给char,所以就需要我们进行相应的操作转化。
#include<iostream>
using namespace std;
#include<algorithm>
int main()
{
string s = "Chelse";
const char* str = s.c_str();
cout << str << endl;
s[1] = 'm';
cout << str << endl;
}
运行结果:
第一个输出 当然是 Chelse;
第二个输出呢: Chelse还是Cmelse呢?
答案是Cmelse。
const char的值应该是个常量啊,怎么还能改变值呢?
这就是很多人遇到的坑儿,也许面试的时候你会顺利的回答出来,但是在实际的工程中,往往掉进坑儿里,难以自拔。
const char, char const*, char* const的区别是什么?老
const char与char const是等价的,指的是指向字符常量的指针,即指针可以改变指向但其指向的内容不可以改变。
而char* const相反,指的是常量指针,即指向不可以改变但指针指向的内容可以改变。因此这里的const char*指向的内容本类是不可以改变的。
那么这里为什么改变了呢?这跟str这个const char的生命周期及string类的实现有关,string的c_str()返回的指针是由string管理的,因此它的生命期是string对象的生命期,而string类的实现实际上封装着一个char的指针,而c_str()直接返回该指针的引用,因此string对象的改变会直接影响已经执行过的c_str()返回的指针引用。
#pragma once
#include<iostream>
using namespace std;
#include<string.h>
#include<assert.h>
namespace ksy {
class string
{
public:
typedef char* iterator;
/*string() :_str(nullptr)
{}
string(char*str)
:_str(str)
{}*/
/*string(const char* str = "")
:_str(new char[strlen(str)+1])
{
strcpy(_str, str);
}*/
/*string&operator=(string& s) {
if (&s != this) {
char* tmp = new char[s.size() + 1];
delete this->_str;
strcpy(tmp, s._str);
_str = tmp;
}
return *this;
}*/
void reserve(int n) {
if (n > _capacity) {
char* newstr = new char[n+1];
strcpy(newstr, _str);
delete[]_str;
_str = newstr;
_capacity = n;
}
}
void resize(int n,char ch='\0') {
if (n < _size) {
_str[n] = '\0';
_size = n;
}
else {
if (n > _capacity) {
reserve(n);
}
for (int i = _size; i < n; i++) {
_str[i] = ch;
}
_size = n;
_str[_size] = '\0';
}
}
iterator begin() {
return _str;
}
iterator end() {
return _str + _size;
}
friend ostream& operator<<(ostream& cout, const string& s);
friend istream& operator>>(istream& cin, string& s);
string(const char* str = "") {
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];//'\0'不是有效字符
strcpy(_str, str);
}
~string() {
delete[]_str;
_str = nullptr;
_size = _capacity;
}
string(const string& s)
:_str(nullptr)
{
string tmp(s._str);
swap(_str, tmp._str);
}
string& operator=(string s) {
if (&s != this) {
swap(_str, s._str);
}
return *this;
}
size_t size() {
return _size;
}
size_t size()const {
return _size;
}
size_t capacity() {
return _capacity;
}
size_t capacity()const {
return _capacity;
}
char& operator[](int i) {
assert(i < _size);
return _str[i];
}
const char& operator[](int i)const {
assert(i < _size);
return _str[i];
}
const char* c_str() {
return _str;
}
void push_back(char ch) {
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;
reserve(newcapacity);
}
_str[_size] = ch;
_size++;
_str[_size] = '\0';
}
void append(const char*str) {
int len = strlen(str);
if (_size + len > _capacity) {
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
string& operator +=(char ch) {
this->push_back(ch);
return *this;
}
string& operator+=(const char* str) {
this->append(str);
return *this;
}
string insert(size_t pos, char ch)
{
assert(pos > 0 && pos < _size);
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : 2 * _capacity;
reserve(newcapacity);
}
int end = _size;
while (_size >= pos) {
_str[end + 1] = _str[end];
end--;
}
_str[pos] = ch;
_size++;
return *this;
}
string& insert(size_t pos, const char* str)
{
assert(pos < _size);
int len = strlen(str);
if (len + _size > _capacity) {
reserve(len + _size);
}
int end = _size;
while (end >= pos) {
_str[end+len] = _str[end];
--end;
}
strncpy(_str + pos, str, len);
_size += len;
return *this;
}
string& erase(size_t pos, size_t len = npos)
{
assert(pos < _size);
if (len >= _size - pos) {
_str[pos] = '\0';
_size = pos;
}
else {
size_t i = pos + len;
while (i <= _size) {
_str[i - len] = _str[i];
++i;
}
_size -= len;
}
return *this;
}
size_t find(char ch, size_t pos = 0)
{
for (int i = pos; i < _size; i++) {
if (_str[i] == ch) {
return i;
}
}
return npos;
}
size_t find(const char* str, size_t pos = 0)
{
char*p=strstr(_str, str);
if (p == nullptr) {
return npos;
}
else {
return p - _str;
}
}
bool operator<(const string& s)
{
int ret= strcmp(_str, s._str);
return ret < 0;
}
bool operator>(const string& s)
{
int ret=strcmp(_str, s._str);
return ret > 0;
}
bool operator<=(const string& s)
{
return *this < s || *this == s;
}
bool operator>=(const string& s)
{
return *this > s || *this == s;
}
bool operator!=(const string& s)
{
return !(*this == s);
}
bool operator==(const string& s)
{
int ret = strcmp(_str, s._str);
return ret == 0;
}
private:
char* _str;
int _size;
int _capacity;
static size_t npos;
};
size_t string ::npos = -1;
ostream& operator<<(ostream& cout, const string& s) {
for (size_t i = 0; i < s.size(); i++) {
cout << s[i];
}
return cout;
}
istream& operator>>(istream& cin, string& s) {
while (1) {
char ch;
ch = cin.get();
if (ch == ' ' || ch == '\n') {
break;
}
else {
s += ch;
}
}
return cin;
}
void test_string() {
string s("hfdf");
/* cout << s << endl;
cout << s.capacity() << " " << s.size();
string s1(s);
cout << s1 << endl;
cout << s1.size() << " " << s1.capacity() << endl;*/
for (auto& e : s) {
cout << e;
}
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_56999918/article/details/120879166
内容来源于网络,如有侵权,请联系作者删除!