string的使用介绍

article/2025/8/15 4:17:20

目录

标准库中的string类

string类(了解)

编码介绍

string类的常用接口说明

Member functions

测试一:创建对象

测试二:遍历字符串

Iterators

测试三:反向迭代器(Iterators)

Capacity

测试四:容器相关(Capacity)

测试五:自动扩容

测试六:resize的不同情况

Element access

测试七:字符获取函数(Element access)

Modifiers

测试八:修改类(Modifiers)

测试九:insert与erase

测试十:assign与replace

find的使用

将空格替换成%20

operations

测试十一:c_str

测试十二:substr取一段字符

find_first_of

Non-member function overloads

relational operators (string)

一些题目

917. 仅仅反转字母

415. 字符串相加

387. 字符串中的第一个唯一字符

HJ1 字符串最后一个单词的长度

125. 验证回文串

541. 反转字符串 II

557. 反转字符串中的单词 III

43. 字符串相乘

HJ59 找出字符串中第一个只出现一次的字符

结束语


标准库中的string类

string从发展历史上来说,比STL创建的更早,我们现在通常把它归类到STL里面,但是从发展历史上来看其实不算,这一点从string的实现中可以看出来,相比标准的STL容器,string更加杂乱,标准化不高。

string类(了解)

string类的文档介绍 -- 链接

1. 字符串是表示字符序列的类


2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。


3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。


4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参basic_string)。


5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。编码的本质其实是计算机里面存的值(0、1组成,我们人一般看不懂,所以就有了ASCLL码(256个)来存一些常用的文字字符,建立对应关系,我们在使用的时候就无需知道字符对应的二进制码了,计算机可以帮助我们自己去寻找)

总结: 

1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,

typedef basic_string<char, char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列。

在使用string类时,必须包含#include头文件以及using namespace std;

编码介绍

ASCII_百度百科 (baidu.com)

后面为了解决计算机流通的问题,又引入了Unicode(万国码)

统一码_百度百科 (baidu.com)

而我们中文也有自己的编码,这里面收录了全面的汉字,包括繁体字、生僻字这类较少用到的

GBK字库_百度百科 (baidu.com)

 

默认下Linux系统是使用UTF-8,VS是使用GBK,我们在高级保存选项中可以看到,不过有可能看不到这个选项,需要自己调整出来

在调试下我们会发现GBK编码的一些小细节 

通常我们使用的就是string这一个,不过C++11之后也有其他的类型了

 

string类的常用接口说明

Member functions

测试一:创建对象

string::string - C++ Reference (cplusplus.com)  -- 链接

string::npos - C++ Reference (cplusplus.com)  -- 链接

//string 使用
#include<iostream>
#include<string>
using namespace std;//typedef basic_string<char, char_traits, allocator>string; 库里面是重命名过了
void test_test1()
{//basic_string<char> s1;	这种写法与下面写法是一样的string s1;string s2("hello world");s2 += "!";string s3 = "hello world";	//这里会产生引用类型转换,产生临时对象string s4(10, '*');cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;string s5(s2);string s6 = s2;cout << s5 << s6 << endl;string s7("hello world", 5);cout << s7 <<endl;string s8(s7, 2, 3);cout << s8 << endl;string s9(s7, 2, 30);	//字符串太小,会直接取到最后一个cout << s9 << endl;string s9(s7, 2);	//不给参数,会直接使用npos(是一个静态成员变量-1,不过因为是无符号所以很大)cout << s9 << endl;	//基本上是取到结尾,因为大概没有4G长的字符串吧}
int main()
{test_test1();return 0;
}

测试二:遍历字符串

void test_tring2()
{string s1("1234");	//会自动加\0//遍历//1、下标 []for (size_t i = 0; i < s1.size(); i++){s1[i]++;}//s1[10];	这里是重载,所以这里会检查越界cout << s1 << endl;//2、范围forfor (auto& e : s1){e--;}cout << s1 << endl;string s2 = "abcde";cout << s2.size() << endl;	//到\0就停止不包括\0//反转一下size_t begin = 0, end = s1.size() - 1;	cout << s1.size() << endl;//顾名思义,s1.size()返回字符串大小while (begin < end){swap(s1[begin++], s1[end--]);}cout << s1 << endl;reverse(s1.begin(), s1.end());	//算法里面的逆置,配合迭代器很好用cout << s1 << endl;//迭代器(通用的访问形式,不仅仅是在string里面可以用) -- 一个像指针但是不一定就是指针string::iterator it1 = s1.begin();while (it1 != s1.end()){*it1 += 1;++it1;}it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}cout << end;//vector 我们会发现基本上使用方式是一样的vector<int> v;vector<int>::iterator vit = v.begin();while (vit != v.end()){*vit += 1;++vit;}cout << end;//listlist<int> lt;list<int>::iterator ltit = lt.begin();while (ltit != lt.end()){*ltit += 1;++ltit;}}
int main()
{//test_tring1();test_tring2();return 0;
}

Iterators

迭代器(Iterators)

测试三:反向迭代器(Iterators)

string - C++ Reference (cplusplus.com) -- 链接

//反向迭代器void Print(const string& s)	//使用const保护起来,那么迭代器也要有点不同了
{//遍历读,不支持写string::const_iterator it = s.begin();	//const_iterator是迭代器的名字,下面同理//const string::iterator it = s.begin(); 我们保护的不是迭代器本身,而是迭代器指向的对象,所以这种写法是错误的while (it != s.end()){	//*it += 1; 不支持写了cout << *it << " "; ++it;}cout << endl;//有正向的,当然就有反向的啦string::const_reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";++rit;}cout << endl;
}
void test_tring3()
{string s1("1234");//string::reverse_iterator rit = s1.rbegin();	//反向迭代器auto rit = s1.rbegin();	//我们可以使用auto来简化长度while (rit != s1.rend()){cout << *rit << " ";++rit;}cout << endl;Print(s1);	//传引用
}

不修改内容的迭代器

当然了过长是可以使用auto来自动确定类型的

基于上面的情况,我们发现有些函数提供了两种版本,而有些函数则只能读或者只能写,那么如何区别呢?

Capacity

测试四:容器相关(Capacity)

string::empty - C++ Reference (cplusplus.com)  -- 链接

empty判断是否为空,是就返回ture,否则返回false

测试五:自动扩容

利用reserve提高插入数据的效率,避免增容带来的开销

string::reserve - C++ Reference (cplusplus.com)  -- 链接

测试六:resize的不同情况

string::resize - C++ Reference (cplusplus.com) -- 链接

//resize
void test_string6()
{string s1("hello world");s1.resize(5);cout << s1.size() << endl;cout << s1.capacity() << endl;cout << s1 << endl << endl;string s2("hello world");s2.resize(15);cout << s2.size() << endl;cout << s2.capacity() << endl;cout << s2 << endl << endl;string s3("hello world");s3.resize(30);cout << s3.size() << endl;cout << s3.capacity() << endl;cout << s3 << endl << endl;
}

Element access

测试七:字符获取函数(Element access)

string::at - C++ Reference (cplusplus.com)

Modifiers

测试八:修改类(Modifiers)

//修改类(Modifiers)
void test_string8()
{//string s1("hello world");//s1.push_back(' ');//s1.push_back('!');//s1.append("hello world");//cout << s1 << endl;////string s2("!!!!!!!");//s1.append(s2);//cout << s1 << endl;string s1("hello world");s1 += ' ';s1 += '!';s1 += "hello world";cout << s1 << endl;string s2("!!!!!!!");s1 += s2;cout << s1 << endl;
}

+=的使用

测试九:insert与erase

//insert与erase
void test_string9()
{string s("hello world");s.insert(0, "hello ");cout << s << endl;s.insert(11, "hello");cout << s << endl;s.erase(11, 5);cout << s << endl;s.erase(5, 30);	//超过就会使用npos(缺省值)去删除了cout << s << endl;	
}

测试十:assign与replace

void test_string10()
{string s1("hello world hello world");string s2("hello world hello world");string s3(s2);s1.assign("hello world", 5);cout << s1 << endl;s2.replace(6, 5, "hello");cout << s2 << endl;//将 ' '  替换成%20size_t pos = s3.find(' ');while (pos!=string::npos)    //这样写任何平台都可以使用{s3.replace(pos,1,"20%");pos = s3.find(' ', pos + 3);	//加三跳过%20}cout << s3 << endl;
}

find的使用

将空格替换成%20

operations

测试十一:c_str

void test_string11()
{string file("test.cpp");FILE* fout = fopen(file.c_str(), "r");assert(fout);char ch = fgetc(fout);while (ch != EOF){cout << ch;ch = fgetc(fout);}fclose(fout);
}

测试十二:substr取一段字符

//substr -- 取一串字符
void test_string12()
{//test.cppstring file;cin >> file;//要求取后缀//size_t pos = file.find('.');	从头开始找size_t pos = file.rfind('.');	//这里从尾部开始找更好点if (pos != string::npos){//string suffix = file.substr(pos, file.size() - pos);string suffix = file.substr(pos);cout << suffix;}
}

find_first_of

string::find_first_of - C++ Reference (cplusplus.com)

并不是字面意思,而是找到单词中的某一个字母

Non-member function overloads

relational operators (string)

基于这一点可以知道,最下面的一种情况得特殊处理,不过我们得知道,Date类里面的成员函数左参数会被this抢占无法实现这一项,所以得使用友元函数进行处理

一些题目

917. 仅仅反转字母

class Solution {
public:string reverseOnlyLetters(string s) {int begin = 0;int end = s.size()-1;if(end == 1)return s;while(begin < end){//从左找字母while(begin < end && !isalpha(s[begin])){++begin;}//从右找左字母while(begin < end && !isalpha(s[end])){--end;}//左右交换swap(s[begin],s[end]);//再向后走++begin;--end;}return s;}
};

415. 字符串相加

class Solution {
public:string addStrings(string num1, string num2) {int end1 = num1.size()-1 , end2 = num2.size()-1;int carry = 0;string retStr;retStr.reserve(max(num1.size(),num2.size())+1); while(end1 >= 0 || end2 >= 0){int ret1 = end1 >= 0 ? num1[end1]-'0' : 0;int ret2 = end2 >= 0 ? num2[end2]-'0' : 0;int ret = ret1 + ret2 + carry;carry = ret/10;ret%=10;retStr+= (ret + '0');end1--;end2--;}if(carry == 1)retStr+='1';reverse(retStr.begin(),retStr.end());return retStr;}
};

387. 字符串中的第一个唯一字符

class Solution {
public:int firstUniqChar(string s) {int tmp[26] = {0};size_t sz = s.size();for(auto ch : s){tmp[ch - 'a']++;}for(size_t i = 0; i<sz; ++i){if(tmp[s[i] - 'a'] == 1)return i;}return -1;}
};

HJ1 字符串最后一个单词的长度

#include <iostream>
using namespace std;int main() {string s;getline(cin,s,'\n');    //默认结束符合为\n,当然也可以自己给定int pos = s.rfind(' ');cout<<s.size() - pos - 1 <<endl;return 0;
}

125. 验证回文串

class Solution {
public:bool isPalindrome(string s) {string tmp;int sz = s.size();tmp.reserve(sz+1);for(int i = 0; i<sz; ++i){if(isalnum(s[i]))   //字母和数字都属于字母数字字符,所以使用这个才可以tmp+=tolower(s[i]);}cout<<tmp<<endl;int end = tmp.size()-1;int begine = 0;while(begine<end){if( begine<end && (tmp[begine] != tmp[end]) )return false;begine++;end--;}return true;}
};

541. 反转字符串 II

class Solution {
public:string reverseStr(string s, int k) {int sz = s.size();for(int i = 0; i < sz; i += 2*k)reverse(s.begin()+i, s.begin()+min(i+k,sz));    //迭代器可以跳过return s;}
};

557. 反转字符串中的单词 III

class Solution {
public:string reverseWords(string s) {int sz = s.size();int i = 0;while(i < sz){int start = i;while(i<sz && s[i] != ' ')++i;int left = start, right = i;while(left<right){swap(s[left],s[right-1]);left++;right--;}++i;//跳过空格}return s;}
};

我倾向于这种写法

class Solution {
public:string reverseWords(string s) {int length = s.length();int pos = 0;for(int i = 0; i < length; i++){if (s[i] == ' '){std::reverse(s.begin() + pos, s.begin() + i);pos = i + 1;}}std::reverse(s.begin() + pos, s.end());return s;}
};

43. 字符串相乘

class Solution {
public:string multiply(string num1, string num2) {if(num1 == "0" || num2 == "0") return "0";if(num1 == "1" && num2 != "1") return num2;if(num1 != "1" && num2 == "1") return num1;if(num1.length()<num2.length())swap(num1,num2);int m = num1.length(), n = num2.length();string ret(m+n,'0');for(int i = n-1; i>=0; --i){if(num2[i] == '0')continue;int carry = 0;for(int j = m-1; j>=0; --j){int new_num = (num1[j]-'0')*(num2[i]-'0') + (ret[i+j+1]-'0') + carry;carry = new_num/10;new_num %=10;ret[i+j+1]=(new_num + '0'); }if(carry>0)ret[i]=(carry + '0');}int i = 0;while(ret[i] == '0')i++;return ret.substr(i,m+n-i);}
};

HJ59 找出字符串中第一个只出现一次的字符

#include <iostream>
#include <unordered_map>
using namespace std;int main() {string s;cin >> s;unordered_map<char, int> Hash;for (auto ch : s) {Hash[ch]++;}int i = 0;for(auto it : s){if(Hash[it] ==  1){cout<<it;return 0;}}cout<<-1;return 0;
}

结束语

我最怜君中宵舞,道男儿到死心如铁。看试手,补天裂。
                                                                                《贺新郎·同父见和再用韵答之》


http://chatgpt.dhexx.cn/article/RliIwXJW.shtml

相关文章

STL之string用法详解

2.1 string容器介绍 string也属于STL常用容器之一&#xff0c;因此vector&#xff08;参考博客&#xff09;中的大部分方法与迭代器都适用于string容器。string容器用于保存字符串&#xff0c;使用一组连续的内存单元来存放字符串中的每个字符&#xff0c;因此也支持随机访问与…

String用法详解

string类 声明 string类本不是STL的容器&#xff0c;但是它与STL容器有着很多相似的操作&#xff0c;因此&#xff0c;把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C标准程序库中的string类&#xff0c;是因为他和前者比较起来&#xff0c;不必担心内存是否…

string 的常见用法详解

目录 1.string 的定义 2.string 中内容的访问 3.string 常用函数实例解析 在C语言中&#xff0c;一般使用字符数组 char str[]来存放字符串&#xff0c;但是使用字符串数组有时会显得操作麻烦&#xff0c;在C中加入了string类型。 注意&#xff0c;如果要使用string&#xf…

【C++】STL常用容器总结之十二:string类

13、string类 声明 string类本不是STL的容器&#xff0c;但是它与STL容器有着很多相似的操作&#xff0c;因此&#xff0c;把string放在这里一起进行介绍。 之所以抛弃char*的字符串而选用C标准程序库中的string类&#xff0c;是因为他和前者比较起来&#xff0c;不必担心内…

string的常用用法详解

一般我们在C语言中用到字符串&#xff0c;都是使用字符数组来存放&#xff0c;但是操作字符数组有时候会不便&#xff0c;所以为了方便操作&#xff0c;在C的STL中加入了字符串类型&#xff08;string&#xff09;。 想要复习以往字符数组的相关知识点请点击以下链接&#xff…

对于String的用法详解

目录 一、String的基本用法 二、对于字符串常量池的理解。 三、String类的常见操作。 四、StringBuffer和StringBuilder的使用。 一、String的基本用法 1.1String的创建方法 //第一种创建方法 String str"Hellow"; System.out.println(str);//第二种创建方法 S…

String类的常见用法

目录 1、创建字符串的四种方式&#xff1a;(方式一和方式四最常用&#xff09; 2、字符串的字面量&#xff08;也是字符串的对象&#xff09; 3、字符串比较 4、关于字符串的常量池问题 5、手工入池—String 类提供的 intern 方法 6、字符串的不可变性&#xff1a; 7、修…

非抢占式多级反馈队列优先级调度算法 C++实现

介绍 前段时间比较忙&#xff0c;没有更新&#xff0c;这次的也是操作系统的一个实践作业 C实现非抢占式多级反馈队列优先级调度算法&#xff0c;希望可以帮到你们。 问题介绍 这里我用课件里的内容 1.应设置多个就绪队列&#xff0c;并为每个队列赋予不同的优先级。第一个队…

多级反馈队列算法补充

http://pages.cs.wisc.edu/~remzi/OSTEP/cpu-sched-mlfq.pdf 本文是多级反馈队列&#xff08;multi-level feedback queue&#xff0c;MLFQ&#xff09;算法的一些小补充&#xff08;两个缺陷与修改方法&#xff09;&#xff0c;参考了上面链接。因为自己用中文没有搜到想要的…

操作系统-多级反馈队列

概述 1962年&#xff0c;Corbato首次提出多级反馈队列&#xff0c;应用于兼容时分共享系统(CTSS)。Corbato因在CTSS中的贡献和后来在Multics中的贡献&#xff0c;获得了ACM颁发的图灵奖(Turing Award)。该调度程序经过多年的一系列优化&#xff0c;出现在许多现代操作系统中。 …

操作系统学习(二):浅析多级反馈队列MLFQ

目录 0、引言 1、多级反馈队列&#xff08;MLFQ&#xff09;的基本规则 2、MLFQ的规则具体说明 3、MLFQ调优及其他问题 4、总结 0、引言 在上篇文章操作系统学习&#xff08;一&#xff09;&#xff1a;浅析操作系统进程调度算法中讲到&#xff0c;在一个通用的操作系统中…

多级反馈队列调度算法(附Python3实现代码)

一、多级反馈队列调度算法 多级反馈队列调度算法是进程调度的一种算法&#xff0c;该调度算法可以不用事先知道各种进程所需的执行时间&#xff0c;还可以较好的满足各种类型进程的需要&#xff0c;是目前共认的一种较好的进程调度算法。 那你可能马上就要问了&#xff0c;多…

调度:多级反馈队列

多级反馈队列&#xff08;Multi-level Feedback Queue, MLFQ&#xff09;是有Corbato在1962年提出的&#xff0c;用于兼容时分共享系统。现在其经过多年的优化&#xff0c;已经被应用于很多现代操作系统中。多级反馈队列是为了解决两方面问题。一&#xff1a;优化周转时间。在之…

多级队列调度和多级反馈队列调度算法的实现

多级队列调度算法 操作系统实验导航 实验一&#xff1a;银行家算法 https://blog.csdn.net/weixin_46291251/article/details/115384510 实验二&#xff1a;多级队列调度和多级反馈队列调度算法 https://blog.csdn.net/weixin_46291251/article/details/115530582 实验三&…

多级反馈队列调度算法模拟实现

实验一 多级反馈队列调度算法 一. 主要实现方法和代码介绍 ​ 1.编写进程类,其只包含所需的运行时间和进程编号两个属性,还有一个运行方法,此方法就是将所需的运行时间属性减去.传入的运行时间. ​ 2.创建进程函数:创建maxp个进程,(应该不超过10,在此创建九个,即暂时不进行进…

计操实验 多级反馈队列C语言

计操实验 多级反馈队列C语言 需求&#xff1a; 1.队列4级&#xff0c;每一级的队列长度均为10&#xff1b;第一级的时间片为T&#xff0c;第二级的时间片为2T&#xff0c;第三级的时间片为4T&#xff0c;第四级的时间片为8T&#xff1b;&#xff08;T的大小自己定&#xff09; …

【操作系统】轮转和多级反馈队列

随着计算机的技术逐渐步入家用后&#xff0c;新的调度指标接踵而来&#xff0c;周转时间已经不能满足人们日常工作的需求&#xff0c;更多时候人们更希望计算机能有更好的交互性&#xff0c;使其能更快地去响应任务&#xff0c;由此针对优化响应时间的调度策略也遍地开花&#…

多级反馈队列调度算法(c++)

如果对你有帮助&#xff0c;可以给卑微的博主留个赞、关注、收藏 (不是) (骗一下数据&#xff0c;说不定以后面试就过了&#xff0c;拜谢) 操作系统基本调度算法&#xff0c;多级反馈队列调度算法。在划分时间片的调度算法中&#xff0c;多级反馈队列算法兼顾提高系统吞吐…

多级反馈队列调度算法

实验目的&#xff1a; 在Linux下编程实现多级反馈队列调度算法&#xff0c;采用三级调度策略&#xff0c;所有进程先按到达顺序进入一级队列&#xff0c;按照时间片为2轮转一次&#xff0c;一个时间片内未完成的进程被依次移入二队列尾部。当一级队列中没有进程时&#xff0c;开…

多级反馈队列调度

多级反馈队列 ​ 多级反馈队列&#xff08;Multi-level Feedback Queue&#xff0c; MLFQ&#xff09;&#xff0c;与上个世纪70年代提出&#xff0c;主要应用于时分共享系统。主要解决两方面问题&#xff1a;一个是优化周转时间&#xff0c;一个是要给用户很好的交互体验。ML…