解决你关于C++字符串的疑惑

C++ 字符串梳理

0、概要

先介绍C++继承的C风格字符串,再重点说明C++自己发展的string类。最后谈谈两者之间的联系和区别。

1、C- 字符串

1.1、字符数组即是字符串

C++在C之上发展而来,并且保证任何C程序都是合法的C++程序,所以C++必须支持C风格的字符串,即C-string。

C并没有string类型,而是通过char数组实现字符串,即:字符串是以空字符\0结尾的字符数组

char charr[] = {'H', 'e', 'l', 'l', 'o', '\0'};  //遵循数组的初始化方式
char charr1[] = "Hello"; //更加方便实用,C在存储的时候自动在末尾添加空字符\0

上面两个语句声明并初始化了一个字符串"Hello"。

本质上,C只有字符数组没有字符串。C将字符串拆解成字符数组,存储在连续的存储单元内,数组名记录了第一个字符的位置,空字符\0代表了字符串结尾。如下例:

char charr2[] = {'H', 'e', 'l', '\0', 'l', 'o','\0'};    //charr2="Hel"
char charr3[] = {'H', 'e', 'l', 'l', 'o'};               //charr3会一直读取到内存上的\0为止

1.2、C-style 字符串的简单使用

	//C-style字符串的简单使用
    char chars1[15] = {'H', 'e', 'l', 'l', 'o', ' ', '\0'}; //数组方式初始化
    char chars2[] = "C++";                           //字符串常量初始化
    char chars3[20];  //不初始化必须给出数组大小
        
    //字符串连接
    strcat(chars1,chars2);    //chars1="Hello C++"
    cout<<chars1<<endl;
    //字符串复制
    strcpy(chars3,chars1);   //chars3=chars1="Hello C++"
    cout<<chars3<<endl;
    //字符串比较(0表示相等)
    cout<<"chars1 == chars3 ? "<<strcmp(chars1,chars3)<<endl;
    //字符串大小
    cout<<"chars2 有 "<<strlen(chars2)<<" 字符,"    //3个字符
            <<"占 "<<sizeof chars2<<" 字节."<<endl;      //4个字节

2、C++ string类

C的字符数组有很多不便,尤其是字符数组的大小必须固定,定义的时候,大了浪费内存,小了字符串的存储越界,并且不支持字符数组之间的赋值等操作,所以C++标准库提供了string类作为字符串类,在string头文件中。

从定义上:

typedef basic_string<char> string

string类其实是一个实例化的模板类。

2.1、常用方法

  1. 构造器:

    • 默认空串:string()
    • 复制已有字符串:string(const string& str)
    • 复制已有C字符串:string(const char* s)
    • 截取子串:string(const string& str, size_t pos, size_t len=npos)
    • 从C字符串提取前缀:string(const char* s, size_t n)
    • 填充n个字符c:string(size_t n, char c)
  2. **赋值(=):**string支持string类型、C字符串类型、字符串常量、char类型的赋值。

    string s1="Hello";     //字符串常量赋值
    string s2=s1;          //string类型赋值
    char[] chs[]="C++";
    string s3=chs;         //char[]类型赋值
    string s4='A';         //char类型赋值
    string s5=65;          //s5="A",65,对应的字符为A,char类型赋值
    
  3. 大小与容量:

    string对象会根据字符串的大小调整分配空间大小,但是并不是每一次都调整大小,导致string有3个大小相关的量:(1)size(length): 当前的字符串长度;(2)capacity(容量):当前分配的内存空间可存储的最大字符串长度,会根据字符串的值变动发生变化;(3)max_size(最大值):当前系统理论上支持的最大字符串长度,限制capacity,capacity超过时发生length_error。实际应用中,只关心size的大小,其它两个常常不用。

    • 获取字符串长度:size()length(),效果一样
    • 判断是否为空empty()
    • 改变字符串长度:resize(size_t n)resize(size_t n, char c)。n < s.size()时,截取前面n个字符;n>s.size()时,填充字符c直到n个字符,没有指明c则用空字符\0填充。
    • 获取当前容量:capacity()
    • 获取支持的字符串最大长度:max_size()
    • 手动分配容量:reserve(size_t n=0)
  4. 成员获取:

    • 成员获取方法(推荐):at(size_t pos), 返回下标为pos的字符。
    • 下标运算符[ ]:s[pos]表示下标为pos的字符。
    • 首尾字符:front()back()

    at()方法和 [ ] 运算符的区别在于前者进行下标检测,后者没有,推荐使用前者。但是后者可以作为左值。

  5. 字符串修改:

    • 插入:insert()。insert() 有多种重载方式,支持插入字符、字符串、插入重复字符串等。

      string str="to be question";
      string str2="the ";
      string str3="or not to be";
      
      str.insert(6,str2);                 // to be (the )question
      str.insert(6,str3,3,4);             // to be (not )the question
      str.insert(10,"that is cool",8);    // to be not (that is )the question
      str.insert(10,"to be ");            // to be not (to be )that is the question
      str.insert(15,2,':');               // to be not to be(::) that is the question
      
    • 追加:append().可以看成在末尾插入,不用指明插入位置,其它使用与insert()一样。

    • 替换:replace()

      string str="Hello World";
      str.replace(6,5,"C++");          //"Hello C++"
      str.replace(5,1,'+');            //"Hello+C++",替换当个字符只能这样,或者str[5]='+'
      
    • 删除:erase(size_t pos, size_t len=npos).删除pos开始的len个字符,没有指明len会把pos之后的全删除。len为1即可删除单个字符。

    • 清空:clear().

    • push和pop一个字符:push_back(char c)pop_back(),分别在末尾剔除和添加字符。

  6. 字符串操作:

    • 获取子串:substr(size_t pos=0, size_t len=npos)

    • 转化为c-style字符串:c_str().

    • 获取字符序列数组:data()。与c_str()的区别在于后者包含最后的空字符\0,前者没有。

    • 复制:`copy( char* s, size_t len, size_t pos=0)

      string str="This is a string";
      char chars[20];
      str.copy(chars, 10, 6);     //chars="string"
      
    • 赋值:assign()可以把字符串或其子串赋给目的字符串。

    • 查找:

      • find()rfind(),前者返回第一个找到的位置,后者(right find)从右查找第一个(即最后一个)位置。
      • find_first_of()find_last_of().查找单个字符时,与上面一致。当参数为字符串时,表示查找字符串中任意一个字符
      • find_first_not_of()find_last_not_of(), 意思明确。
      string str="This is a string";
      str.find("string");         //10
      str.find_first_of("string");   //2,第三个字符i符合。
      
  7. 字符串比较:

    字符串的比较是以字典排序为基础的。如:’‘ABC’’ > “ab” > “abc”。

    • 比较符号:string类支持>, <, >=, !=等进行比较,还能和c-string比较。
    • compare()方法:支持部分比较,如果前者在

3、C-string和string类

本质上,二者是完全不一样的。C-string是字符串数组,本质上是数组,string是面向对象衍生出来的类。 这种不同,导致很多使用方式的不同,C-string需要借助函数完成,而string对象往往依靠成员方法实现。如:strlen(chars)str.size()

在C++中,字符串更推荐使用string类,它较C-string有很多优点:面向对象思想、动态空间分配、使用方便等。

但是,C++也无法抛弃C-string,难免会有交叉使用,你看各种string成员都支持了C-string。

3.1、二者的转化

很多时候,两者还是无法通用的,比如很多老函数只支持C-string参数。所以有必要额外注意一下二者的转化。

char cstr[20]="This is a string";
string str(cstr);     //C-string转为string
cstr=str.c_str();     //string转为C-string
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值