C++ String类的基础概念

为什么要学习string类??

C语言中,字符串是以"/0"结尾的一些字符的集合;为了操作方便,C标准库中提供了一些关于str的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问;为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

string类的特点:

1.string是表示字符串的字符串类;
2.string类的接口与常规的接口基本相同,再添加了一些专门用来操作string的常规操作;
3.string类的内部结构为:

class string
{
	char* _str;
	size_t _size;
	size_t _capacity;
};

相当于一个动态增容的管理字符串的顺序表;
4.string类不能操作多字节或变长字符的序列;

string类的使用场景:

string是C++标准库的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行操作,也可以通过文件等手段进行操作。同时C++的算法库对string也有着很好的支持,而且string还和c语言的字符串之间有着良好的接口;(在使用string类时,必须包含#include头文件以及using namespace std;)

具体的关于string类的所有函数的操作及用法,可以多在官网上进行查找学习:
www.cplusplus.com/reference/string/string/?kw=string

string类的具体操作:

1.string类的常用接口说明:
本文主要总结一些关于string类的常用操作符,具体的关于string类的操作可在官网进行查看;

(1)string类的常用构造函数:

constructor 函数名功能说明
string()构造空的string类对象,即空字符串
string(const char * s)用C-string来构造string类对象
string(size_t n char c)string类中包含n个字符c
string(const string&s)拷贝构造函数
#include <iostream>
#include <string>
using namespace std;
//最常用的两个初始化;
int main(){
   std::string s1;         //构造空的string类对象;
   std::string s2("hello world");    //string类的初始化;
   std::string s3(s2);     //拷贝构造;
   std::string s4(100,X);   //打印
   std::string s5(s2,2,7);   //s2中从第二个数起向后取7个字符;
   
   cout<<s1<<endl;
   cout<<s2<<endl;
   cout<<s3<<endl;
   cout<<s4<<endl;
   cout<<s5<<endl;
   return 0;
}
   

(2)string类对象的容量(Capacity)操作:

函数名功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数改成n个,多出的空间用字符c填充
#include<iostream>
#include <string>
using namespace std;
int main(){
   std::string str("hello world");
   cout <<str.size()<<endl;        //字符串中有效字符的个数;
  
   cout<<str.length()<<endl;    //字符串中有效字符的个数;
   
   cout<<str.max_size()<<endl;    //表示最大值有多大,在32位操作系统下永远是42亿;
   
   cout<<str.capacity<<endl;      //容量是动态增容的,并不是要多少就给多少;

   cout <<str<<endl;

    str.clear();                          //clear的作用是清掉所有数据,并不会清理空间;清理空间是交给析构函数进行处理的;
    cout<<str.size()<<endl;
    cout<<str.length()<<endl;
    cout<<str.capacity<<endl;
 
    return 0;
}

该程序输出的结果是:
在这里插入图片描述

关于reserve和resize的功能:

resize功能实现程序;(resize把空间开好后,这些空间就全部已经初始化了;)

#include <iostream>
#include <string>
using namespace std;
int main ()
{
  std::string str ("I like to code in C");
  std::cout << str << '\n';

  unsigned sz = str.size();

  str.resize (sz+2,'+');
  std::cout << str << '\n';

  str.resize (14);
  std::cout << str << '\n';
  return 0;
}
   

程序输出结果为:
在这里插入图片描述
reserve的功能实现程序;
(reserve只管去开空间,如果要让数据进去得用push_back将数据加入到size中)

#include <iostream>
#include <string>
using namespace std;
int main(){
	std::string s("hello");
	//测试reserve是否会改变string中的有效元素个数;
	s.reserve(100);
    cout << s.capacity() << endl;
    cout << s.size() << endl;
 
    // 测试reserve参数小于string的底层空间大小时,是否会将空间缩小;
     s.reserve(50);    
     cout << s.size() << endl;    
     cout << s.capacity() << endl; 
     cout << s << endl;
	return 0;
}

程序结果为:
在这里插入图片描述

//利用reserve提高插入数据的效率,避免增容带来开销;
void TestPushBack() {
    string s;
     size_t sz = s.capacity();    
     cout << "making s grow:\n";    
     for (int i = 0; i < 100; ++i) {        
        s.push_back('c');        
        if (sz != s.capacity()){            
           sz = s.capacity();            
           cout << "capacity changed: " << sz << '\n';        
        }    
     }
 } 



void TestPushBackReserve() {    
   string s;     
   s.reserve(100);    
   size_t sz = s.capacity();       
   cout << "making s grow:\n";    
   for (int i = 0; i < 100; ++i) {        
      s.push_back('c');        
      if (sz != s.capacity()) {            
         sz = s.capacity();            
         cout << "capacity changed: " << sz << '\n';        
      }    
   } 
} 

总结:
(1)size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size();
(2)clear()只是将string中有效字符清空,不改变底层空间大小;如果要改变空间大小需要析构函数;
(3) resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变;
(4)reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小;

(3)string类对象的访问及遍历操作:

函数名功能说明
operator[ ]返回post位置的字符,const string类对象的调用
begin+endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin+rend返回反向迭代器以反向开始 + 将反向迭代器返回到反向结束
范围forC++11支持更简洁的范围for的新遍历方式

operator[]代码的实现操作:

// string::operator[]
#include <iostream>
#include <string>

int main ()
{
  std::string str ("Test string");
  for (int i=0; i<str.length(); ++i)
  {
    std::cout << str[i];
  }
  return 0;
}
编辑并运行

//operator[]主要用于获取字符串中的字符;如果字符串对象是const限定的,则该函数返回一个const char&;否则,它返回一个char&;

#include <iostream>
#include<stdlib.h>
#include <string>
using namespace std;
int main(){
	std::string str1("hello world");
	const std:: string str2("Hello world");
	cout << str1 << " " << str2 << endl;
	cout << str1[0] << " " << str2[0] << endl;
	
	str1[0] = 'H';
	cout << str1 << endl;
	
	//str2[0] = 'h';    //代码编译失败,因为const类型对象不能被修改;
	cout << str2<< endl;
	
	system("pause");
	return 0;
}

程序输出的结果为:
在这里插入图片描述
正向迭代器:begin+end代码实现操作:
(begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器)

#include <iostream>
#include <string>
int main ()
{
  std::string str ("Test string");
  for ( std::string::iterator it=str.begin(); it!=str.end(); ++it){
    std::cout << *it;
  }
  
  std::cout << '\n';
  return 0;
}

代码实现结果:
在这里插入图片描述
反向迭代器:rbegin+rend代码实现操作:
(返回反向迭代器以反向开始 + 将反向迭代器返回到反向结束)

#include <iostream>
#include <string>
#include <stdlib.h>
int main()
{
	std::string str("I am here!!!");
	for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit){
		std::cout << *rit;
	}
	system("pause");
	return 0;
}

代码实现结果:
在这里插入图片描述

string类对象的遍历操作:

void TestString() {    
   string s("hello Bit");    
   // 3种遍历方式:    
   // 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,    
   // 另外以下三种方式对于string而言,第一种使用最多    
  
   // 1. for+operator[]    
   for(size_t i = 0; i < s.size(); ++i)        
   cout<<s[i]<<endl;        
  
  
   // 2.迭代器    
   string::iterator it = s.begin();    
   while(it != s.end()) {        
      cout<<*it<<endl;        
      ++it;    
   }
    
    string::reverse_iterator rit = s.rbegin();    
    while(rit != s.rend()){
       cout<<*rit<<endl; 
    }       

    // 3.范围for
    for(auto ch : s){
       cout<<ch<<endl; 
    }

(4)string类对象的修改操作:

函数名称功能说明
push_back在字符串末尾插入字符c
append在字符串后在追加一个字符串
operator+=在字符串后追加字符串str
c_str返回c 格式字符串
find +npos从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

push_back以及append操作用法:

#include <iostream>
#include <string>
using namespace std;
int main(){
   std::string s("hello world");
   s.push_back('!');     //在str字符串后加!;
   cout<<s<<endl;

   std::string str;
   std::string str2="Writing ";
   std::string str3="print 10 and then 5 more";

//直接追加一个str2的字符串;
   str.append(str2);                       // "Writing "

//后面追加str3第6个字符开始的3个字符串;
   str.append(str3,6,3);                   // "10 "

 //追加字符串形参的前5个字符
   str.append("dots are cool",5);          // "dots "
  
  //直接添加
   str.append("here: ");                   // "here: "
 
  //添加10个'.'
   str.append(10u,'.');                    // ".........."
  
  //添加str3迭代器范围的字符串
   str.append(str3.begin()+8,str3.end());  // " and then 5 more"
 
 //最后这个比较特殊,意思是添加5个'A',实际上参数里面的65对应的asc码就是65 
   str.append<int>(5,0x2E);                // "....."
 
   return 0;
}  
   

operator+=操作用法:

//operator的三种常用操作:
//string&operator + =(const string&str);	
//string&operator + =(const char * s);	
//string&operator + =(char c);
//通过在其当前值的末尾附加其他字符来扩展字符串;

#include <iostream>
#include <string>

int main ()
{
  std::string name ("John");
  std::string family ("Smith");
  name += " K. ";         // c-string
  name += family;         // string
  name += '\n';           // character

  std::cout << name;
  return 0;
}

//运行结果为:John K. Smith

string的字符串操作:

find函数:主要是查找一个字符串是否在调用的字符串中出现过,大小写敏感;

#include <iostream>  
#include <string>         
using namespace std;
int main ()
{
    std::string str ("There are two needles in this haystack with needles.");
    std::string str2 ("needle");

    std::size_t found = str.find(str2);        //从str中找str2中的字符串在str中的第几位;
    if (found!=std::string::npos){             //npos是string里的一个静态成员变量
      std::cout << "first 'needle' found at: " << found << '\n';
    }

    found=str.find("needles are small",found+1,6);
    if (found!=std::string::npos){ 
      std::cout << "second 'needle' found at: " << found << '\n';
    }

    found=str.find("haystack");
    if (found!=std::string::npos){
      std::cout << "'haystack' also found at: " << found << '\n';
    }

    found=str.find('.');
    if (found!=std::string::npos){
      std::cout << "Period found at: " << found << '\n';
    }
  
    str.replace(str.find(str2),str2.length(),"preposition");
    std::cout << str << '\n';

    return 0;
}

输出的程序结果为:
在这里插入图片描述
rfind函数:就是找最后一个出现的匹配字符串,返回的位置仍然是从前往后数的;

#include <iostream>
#include <string>
#include <cstddef>
using namespace std;
int main ()
{
   std::string str ("The sixth sick sheik's sixth sheep's sick.");
   std::string key ("sixth");

   std::size_t found = str.rfind(key);
   if (found!=std::string::npos){
     str.replace (found,key.length(),"seventh");
   }
   std::cout << str << '\n';

   return 0;
}

输出结果为:
在这里插入图片描述
substr函数: 在str中从pos位置开始,截取n个字符,然后将其返回;

#include <iostream>
#include <string>

int main ()
{
   std::string str="We think in generalities, but we live in details.";

//从str字符串的第三个字符开始,截取5个字符,然后进行打印;
   std::string str2 = str.substr (3,5);    //think;

   std::size_t pos = str.find("live");     //查找live是否出现;

   std::string str3 = str.substr (pos);    //从live 开始截取所有的字符;

   std::cout << str2 << ' ' << str3 << '\n';

   return 0;
}

程序执行结果为:
在这里插入图片描述

(5)string类非成员操作:

函数功能说明
operator+尽量少用,因为传值拷贝导致深拷贝效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串
relational operator比较大小

operator函数:用于连接字符串:

#include <iostream>
#include <string>
using namespace std;
int main ()
{
  std::string firstlevel ("com");
  std::string secondlevel ("cplusplus");
  std::string scheme ("http://");
  std::string hostname;
  std::string url;

  hostname = "www." + secondlevel + '.' + firstlevel;
  url = scheme + hostname;

  std::cout << url << '\n';

  return 0;
}

//输出结果为:http://www.cplusplus.com
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值