【STL】C++ string基本使用

发布时间:2023年12月21日

目录

一 概念

二 常见构造

三 string类对象的容量操作

1 size 和 length

2 capacity

3 reverse

4 resize

5 clear

6 empty

四?string类对象的访问及遍历操作

1 operator [ ]

2 begin + end

3 rbegin +?rend

4 范围for?

五?string类对象的修改操作

1 push_back

2 append

3 operator+=

4 insert?

5 erase

6 replace?

7 swap?

8 pop_back

六 string其他操作

1 c_str

2 find

3 rfind

4 find_first_of + find_last_of

5 find_first_not_of + find_last_not_of

6 substr

七 string补充?

1 getline

2 to_string

3 stoi


一 概念

C++/C++11中std::string是个模板类,它是一个标准库。使用string类型必须首先包含<string>头文件。作为标准库的一部分,string定义在命名空间std中。

std::string是C++中的字符串。字符串对象是一种特殊类型的容器,专门设计来操作字符序列

二 常见构造

int main()
{
???????string s1; //空字符串
???????string s2("hello world");// 构造string类对象

???????string s3(10, 'x');//包含n个字符

???????string s4 = s2;//拷贝构造
???????string s5(s2);//拷贝构造

???????string s6 = "hello string";//隐形转换
???????const string& s7 = "hello const string";//临时对象具有常属性
???????cout << s1 << endl;
???????cout << s2 << endl;
???????cout << s3 << endl;
???????cout << s4 << endl;
???????cout << s4 << endl;
???????cout << s6 << endl;
???????cout << s7 << endl;

???????//这些类是可以改变的
???????s1 = s2;
???????cout << s1 << endl;

???????s1 = "world";
???????cout << s1 << endl;

???????s1 = 'x';
???????cout << s1 << endl;

???????return 0;
}

三 string类对象的容量操作

1 size 和 length

size_t size() const;

size_t length() const;

size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()

int main()
{
???????string s1("hello world");
???????cout << s1.size() << endl;
???????cout << s1.length() << endl;

???????return 0;
}

输出结果: 11?? 11

2 capacity

size_t capacity() const;
int main()
{
	string str("Test string");
	cout << "size: " << str.size() << "\n";
	cout << "length: " << str.length() << "\n";
	cout << "capacity: " << str.capacity() << "\n";
	return 0;
}

3 reverse

void reserve (size_t n = 0);

为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。(只影响容量, 不影响数据)

int main()
{
	string s1("hello world");
	cout << s1.capacity() << endl;

	s1.reserve(500);//需要多少空间, 提前开好
	cout << s1.capacity() << endl;

	s1.reserve(100);//在vs2022下 空间容量不会缩小
	cout << s1.capacity() << endl;

	return 0;
}

4 resize

void resize (size_t n);

void resize (size_t n, char c);

resize(size_tn) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用\0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。

既影响容量 也影响数据

int main()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	cout << s1 << '\n' << endl;

	// > capacity --> 扩容+尾插
	//s1.resize(100);
	s1.resize(100, 'x');
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	cout << s1 << '\n' << endl;

	// size < n < capacity? -> 尾插
	string s2("hello world");
	cout << s2.size() << endl;
	cout << s2.capacity() << endl;
	cout << s2 << endl;
	s2.resize(12);
	cout << s2.size() << endl;
	cout << s2.capacity() << '\n' << endl;

	// n < size -> 删除数据,保留前n个
	string s3("hello world");
	cout << s3.size() << endl;
	cout << s3.capacity() << endl;
	cout << s3 << endl;
	s3.resize(5);
	cout << s3 << endl;
	cout << s3.size() << endl;
	cout << s3.capacity() << '\n' << endl;

	string s5;
	s5.resize(100, '#');
	cout << s5 << endl;

	return 0;
}

5 clear

void clear();

?将string中有效字符清空,不改变底层空间大小。

int main()
{
	string s("hello world");
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	s.clear();
	cout << s << endl;
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	return 0;
}

6 empty

bool empty() const;

?返回字符串是否为空(即其长度是否为 0)。

int main()
{
	string s("hello world");
	cout << s.empty() << endl;

	s.clear();
	cout << s.empty() << endl;
	return 0;
}

四?string类对象的访问及遍历操作

1 operator [ ]

char& operator[] (size_t pos);

const char& operator[] (size_t pos) const;

int main()
{
???????//operator [] 
???????string s1("hello world");
???????for (size_t i = 0; i < s1.size(); i++)
???????{
??????????????cout << s1[i] << " ";
??????????????//底层是这样-->cout << s1.operator[](i) << " "
???????}
???????cout << endl;
???????s1[0] = 'x';
???????cout << s1 << endl;
}

?补充:

字符串中元素的访问是允许的,一般可使用两种方法访问字符串中的单一字符:下标操作符[]?和?成员函数at()。

两者均返回指定的下标位置的字符。第 1 个字符索引(下标)为 0,最后的字符索引为 length()-1。

需要注意的是,这两种访问方法是有区别的:

  • 下标操作符 [] 在使用时不检查索引的有效性,如果下标超出字符的长度范围,会示导致未定义行为。对于常量字符串,使用下标操作符时,字符串的最后字符(即 '\0')是有效的。对应 string 类型对象(常量型)最后一个字符的下标是有效的,调用返回字符 '\0'。

  • 函数 at() 在使用时会检查下标是否有效。如果给定的下标超出字符的长度范围,系统会抛出 out_of_range 异常。

int main()
{
	try
	{
		string s1("hello world");
		cout << s1.at(10) << endl;
		cout << s1.at(11) << endl;
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}

	return 0;
}

下标操作符 [] 和函数 at() 均返回字符的“引用”?

2 begin + end

iterator begin();? ? ?const_iterator begin() const;

iterator end();? ? ? ? const_iterator end() const;

begin()函数返回一个迭代器,指向字符串的第一个元素

end()函数返回一个迭代器,指向字符串的末尾(最后一个字符的下一个位置)

int main()
{
	string s1("hello world");
	// iterator用法像指针
	string::iterator it = s1.begin();
	while (it != s1.end())// s.end()指向'\0'
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	reverse(s1.begin(), s1.end());//左闭右开区间
	cout << s1 << endl;

	const string s2("hello world");
	s1[0] = 'x';
	//s2[0] = 'x' --> error
	cout << s1 << endl;

	//遍历s2
	string::const_iterator itt = s2.begin();
	while (itt != s2.end())
	{
		cout << *itt << " ";
		++itt;
	}
}

const_iterator it 本质保护迭代器指向的数据 *it不能修改

const iterator it 包含的迭代器本身不能修改? it不能修改 不符合我们的需求

对于迭代器可以遍历顺序表, 链表, 栈等数据结构

3 rbegin +?rend

reverse_iterator rbegin();? const_reverse_iterator rbegin() const;

reverse_iterator rend();? ? ?const_reverse_iterator rend() const;

rbegin()返回一个逆向迭代器,指向字符串的最后一个字符。

rend()函数返回一个逆向迭代器,指向字符串的开头(第一个字符的前一个位置

void func(const string& s)
{
	string::const_reverse_iterator it = s.rbegin();
	while (it != s.rend())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

int main()
{
	string s1("hello world");
	string::reverse_iterator it1 = s1.rbegin();
	while (it1 != s1.rend())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
	func(s1);
	return 0;
}

4 范围for?

int main()
{
???????string s1("hello world");
???????for (auto e : s1)
???????{
??????????????cout << e << " ";
???????}
???????cout << endl;

???????return 0;
}

五?string类对象的修改操作

1 push_back

void push_back (char c);

将字符附加到字符串

int main()
{
???????string s1("hello");
???????s1.push_back('#');
???????cout << s1 << endl;
???????return 0;
}
//输出 hello#

2 append

string& append(const string& str);

string& append(const string& str, size_t subpos, size_t sublen);

string & append(const char* s);

string& append(const char* s, size_t n);

string& append(size_t n, char c);

string s1("123"), s2("abc");
s1.append(s2);? // s1 = "123abc"
s1.append(s2, 1, 2);? // s1 = "123abcbc"
s1.append(3, 'K');? // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3);? // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)
int main()
{
???????string s1("hello");
???????s1.push_back(' ');
???????s1.append("world");
???????cout << s1 << endl;

???????string s2 = "xxxx";
???????s2.append(s1);
???????cout << s2 << endl;

???????s2.append(++s1.begin(), --s1.end());
???????cout << s2 << endl;

???????return 0;
}

3 operator+=

string& operator+= (const string& str);

string & operator+= (const char* s);

string& operator+= (char c);

int main()
{
	string s1("hello");
	string s2("world");

	string ret1 = s1 + s2;
	cout << ret1 << endl;

	string ret2 = s1 + "xx";
	cout << ret2 << endl;

	string ret3 = "xx" + s1;
	cout << ret3 << endl;

	string ret4 = 'a' + s1;
	cout << ret4 << endl;

	return 0;
}

4 insert?

string& insert (size_t pos, const string& str);

string& insert (size_t pos, const char* s);

string& insert (size_t pos, const char* s, size_t n);

string& insert (size_t pos, size_t n, char c);

insert 成员函数可以在 string 对象中插入(头插)另一个字符串,返回值为对象自身的引用

int main()
{
	string s1("Limitless"), s2("00");
	s1.insert(2, "123");//在p0位置插入字符串
	cout << s1 << endl;

	s1.insert(3, s2);
	cout << s1 << endl;

	s1.insert(3, 5, 'X');//在p0位置插入n个字符
	cout << s1 << endl;

	s1.insert(3, "abc", 2);//在p0位置插入字符串前两个字符
	cout << s1 << endl;
	return 0;
}

?5 erase

sequence(1)
string& erase(size_t pos = 0, size_t len = npos);

character(2)
iterator erase(const_iterator p);

range(3)
iterator erase(const_iterator first, const_iterator las
?

三种用法:

(1)erase(pos, n); 删除从pos开始的n个字符,比如erase(0, 1)就是删除第一个字符

(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)

(3)erase[first, last); 删除从first到last之间的字符(first和last都是迭代器)

int main()
{
	string s1("hello world");
	s1.erase(9, 1);
	cout << s1 << endl;

	s1.erase(4);//不指明n, 默认把4位置(包括4位置)后面所有的删除
	cout << s1 << endl;

	s1.erase(s1.begin());
	cout << s1 << endl;


	s1.erase(s1.begin(), s1.end() - 1);
	cout << s1 << endl;
	return 0;
}

6 replace?

替换字符串中以字符?pos?开头的部分,并替换跨越len?字符

string& replace (size_t pos, size_t len, const string& str);

string& replace (iterator i1, iterator i2, const string& str);

int main()
{
	string s1("hello world hello yf");
	cout << s1 << endl;

	s1.replace(5, 2, "abc");//s1 pos位置开始往后2个位置被abc覆盖
	cout << s1 << endl;
	return 0;
}

7 swap?

void swap (string& str);

int main()
{
	string s2("hello world");
	string s3("yf");
	s2.swap(s3);

	cout << s2 << endl;
	cout << s3 << endl;
	return 0;
}

8 pop_back

尾删

void pop_back();

int main()
{
	string s2("hello? world hello yf");
	s2.pop_back();
	cout << s2 << endl;
	return 0;
}

六 string其他操作

1 c_str

const char* c_str() const;

c_str()是封装的String类中的一个函数,它返回当前字符串的首字符地址。换种说法,c_str()函数返回一个指向正规C字符串的指针常量,内容与本string串相同。这是为了与C语言兼容,在C语言中没有string类型,故必须通过string类对象的成员函数c_str()把string对象转换成C中的字符串样式。

注意:一定要使用strcpy()等函数来操作c_str()返回的指针

int main()
{
???????char* c;
???????string s = "1234";
???????c = s.c_str();// --> error
???????//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理,同时编译器将会报错
???????return 0;
}

?改正如下

int main()
{
???????char* cstr;
???????string str("Please split this phrase into tokens");
???????cstr = new char[str.size() + 1];
???????strcpy(cstr, str.c_str());
???????cout << cstr << endl;
}

2 find

size_t find(const string& str, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t find(const char* s, size_t pos, size_t n) const;
size_t find(char c, size_t pos = 0) const;

string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos。(返回值可以看成是一个int型的数)(从前向后找)

int main()
{
	string s1("hello world");
	string s2("world");
	cout << s1 << endl;

	//1.从下标0位置开始找字符
	size_t pos1 = s1.find(' ', 0);
	cout << pos1 << endl;

	//2.从下标0位置找字符串
	size_t pos2 = s1.find("world", 0);
	cout << pos2 << endl;

	//3.从下标0位置找string
	size_t pos3 = s1.find(s2, 0);
	cout << pos3 << endl;

	//从下标0位置开始找s前n个的字符串
	size_t pos4 = s1.find("woaaa", 0, 2);
	cout << pos4 << endl;
	return 0;
}

3 rfind

查找字符串中最后一次出现的内容(从后向前找)

size_t rfind(const string& str, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos = npos) const;
size_t rfind(const char* s, size_t pos, size_t n) const;
size_t rfind(char c, size_t pos = npos) const;

int main()
{
	string s1("hello world world");
	cout << s1.size() << endl;
	string s2("world");

	//1.从下标5位置往前开始找字符
	size_t pos1 = s1.rfind(' ', 5);
	cout << pos1 << endl;

	//2.从下标最后一个元素位置往前找字符串
	size_t pos2 = s1.rfind("world");
	cout << pos2 << endl;

	//3.从下标最后一个元素位置往前找string
	size_t pos3 = s1.rfind(s2);
	cout << pos3 << endl;

	//从下标16位置开始往前找s前n个的字符串
	size_t pos4 = s1.rfind("woaaa", 16, 2);
	cout << pos4 << endl;
	return 0;
}

4 find_first_of + find_last_of

size_t find_first_of(const string& str, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos, size_t n) const;
size_t find_first_of(char c, size_t pos = 0) const;

size_t find_last_of(const string& str, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos, size_t n) const;
size_t find_last_of(char c, size_t pos = npos) const;

字符串中搜索与其参数中指定的任何字符匹配的第一个字符。

字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。

int main()
{
	string s("hello world hello yf");
	cout << "lenth == " << s.size() << endl;

	//找l或者l 第一次出现的位置
	size_t pos1 = s.find_first_of("ll");
	cout << pos1 << endl;

	//找l或者o 第一次出现的位置
	size_t pos2 = s.find_first_of("lo");
	cout << pos2 << endl;

	//找l或者o 最后一次出现的位置
	size_t pos3 = s.find_last_of("lo");
	cout << pos3 << endl;

	//从下标5往前找
	size_t pos4 = s.find_last_of('o', 5);
	cout << pos4 << endl;

	return 0;
}

5 find_first_not_of + find_last_not_of

字符串中搜索与其参数中指定的任何字符都不匹配的第一个字符。

字符串中搜索与其参数中指定的任何字符都不匹配的最后一个字符。

size_t find_first_not_of(const string& str, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos, size_t n) const;
size_t find_first_not_of(char c, size_t pos = 0) const;

size_t find_last_not_of(const string& str, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos = npos) const;
size_t find_last_not_of(const char* s, size_t pos, size_t n) const;
size_t find_last_not_of(char c, size_t pos = npos) const;

int main()
{
	string s("hello world hello yf");
	cout << "lenth == " << s.size() << endl;

	//找第一次不是 l 或者 l 的位置
	size_t pos1 = s.find_first_not_of("ll");
	cout << pos1 << endl;

	//找第一次不是 l 或者 o 的位置
	size_t pos2 = s.find_first_not_of("lo");
	cout << pos2 << endl;

	//找最后一次不是 l 或者 o 的位置
	size_t pos3 = s.find_last_not_of("lo");
	cout << pos3 << endl;

	//从下标5往前找
	size_t pos4 = s.find_last_not_of('o', 5);
	cout << pos4 << endl;

	return 0;
}

find 和find_first_of? ?find_last_of? find_first_not_of? ? find_last_not_of 的共同点:

查找成功时返回所在位置,失败返回string::npos的值,string::npos一般是MAX_INT(即2^32 - 1)

不同点:

find():?查找字符串中第一次出现字符c、字符串s的位置;

find_first_of()等: 查找字符串中字符c、字符数组s中任意一个字符出现的位置。

6 substr

string substr (size_t pos = 0, size_t len = npos) const;

?返回一个新构造的对象,其值初始化为此对象的子字符串的副本

int main()
{
	string s("hello world");
	size_t pos = s.find("world");
	cout << pos << endl;

	string sub = s.substr(pos);
	cout << sub << endl;

	return 0;
}

七 string补充?

1 getline

输入字符串 但是有空格的时候

当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。以下面的语句为例:

int main()
{
	string s;
	getline(cin, s);
	cout << s << endl;
	size_t pos = s.rfind(' ');
	if (pos != string::npos)
	{
		cout << s.size() - pos - 1 << endl;
	}
	else
	{
		cout << s.size() << endl;
	}

	return 0;
}

2 to_string

返回表示为?val?的字符串

int main()
{
	string s1 = to_string(123);
	string s2 = to_string(100.1111);
	cout << s1 << endl;
	cout << s2 << endl;

	return 0;
}

补充:

对于将数字转换为字符串来说

可以用 itoa

char * itoa ( int value, char * str, int base )

int main()
{
	int i;
	char buffer[33];
	printf("Enter a number: ");
	scanf("%d", &i);
	itoa(i, buffer, 10);
	printf("decimal: %s\n", buffer);
	itoa(i, buffer, 16);
	printf("hexadecimal: %s\n", buffer);
	itoa(i, buffer, 2);
	printf("binary: %s\n", buffer);
	return 0;
}

输出:

Enter a number: 1750
decimal: 1750
hexadecimal: 6d6
binary: 11011010110

3 stoi

解析?str?并将其内容解释为指定基数的整,该整数作为?int?值返回.

int main()
{
	string s1("123");
	string s2("100.11111");

	int ret1 = stoi(s1);
	int ret2 = stoi(s2);
	cout << ret1 << endl;
	cout << ret2 << endl;
	return 0;
}

补充:

对于字符串的话 可以用aoti?

int atoi (const char * str)

分析 C 字符串,将其内容解释为整数,该整数作为 类型的值返回

本节的内容很多, 但是难度不大, 根据代码很容易上手, 但是STL的string的某些设计还是有些缺陷的, 会感觉要记住的很多, 我觉得不用全部去记, 记住肯定是记不住的, 把本节写到的这些记住就可以了, 因为其他没讲到的我们实际当中也不怎么会用, 要用的时候再去查一下也无妨, 我们最主要的是理解用法就可以了.

继续加油!

文章来源:https://blog.csdn.net/yf214wxy/article/details/135109992
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。