C++ 字符串

C++ 字符串

C++ 提供了以下两种类型的字符串表示形式:

C 风格字符串

C++ 引入的 string 类类型(string class type)

C语言没有提供字符串类型,使用元素类型为char的数组代替,具体而言,字符串一般用一维字符数组来存放,还可以用二维字符数组可以存放多个字符串。

C++ 大大增强了对字符串的支持,除了可以使用C风格的字符串,还可以使用内置的 string 类。string 类处理起字符串来会方便很多,完全可以代替C语言中的字符数组或字符串指针。

一、C 风格字符串

C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持。字符串实际上是使用 null 字符 '\0' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

下面的声明和初始化创建了一个 "Hello" 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 "Hello" 的字符数多一个。

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

依据数组初始化规则,您可以把上面的语句写成以下语句:

char greeting[] = "Hello";

以下是 C/C++ 中定义的C风格字符串的内存表示示意:

使用C风格字符串时,您不需要把 null 字符放在字符串常量的末尾。C++ 编译器会在初始化数组时,自动把 '\0' 放在字符串的末尾。

输出上面的字符串的代码:

#include <iostream>

using namespace std;

 int main ()

{

   char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

   cout << greeting << endl;

   return 0;

}

运行之,参见下图:

C语言没有提供字符串类型,使用元素类型为char的数组代替,具体而言,字符串一般用一维字符数组来存放,还可以用二维字符数组可以存放多个字符串。

字符数组定义的一般格式为:

一维字符数组:char 数组名[整型常量表达式];

二维字符数组:char 数组名[整型常量表达式1][整型常量表达式2];

如: char cA[10],cB[2][15];

字符数组的初始化与赋值与一般数组的很相似,但也有其特殊之处。

一维字符数组的初始化

如下例:

char cA[5]={ ' a', 'b', 'c', 'd', 'e'};

这是最基本的初始化方式。在初始化时要注意数组元素存放的是字符,因此用单引号而不是用双引号,如下面的初始化:

char cA[5]={ " a","b","c","d","e"}; //错误初始化方式

这时每个元素的初值变成了字符串,这显然是错误的。

当字符数组用来存放字符串时,要注意字符串中包含了一个字符串结束标志'\0',这个结束标志也要占用一个单元。其初始化方式有以下几种:

☆用{ }列出初值列表实现。如:

char s1[5]={ 'a', 'b', 'c', 'd', '\0'};

s1中存放的是字符串"abcd"

☆用字符串常量直接初始化。如:

char s1[5]= "abcd";

这种方式初始化时,一定要注意数组的长度和字符串的长度的关系:字符串长度不包含结束符'\0',数组长度要把结束符算在其内,因此数组的长度要大于字符串的长度。如下面的操作是错误的:

char s1[5]= "abcde"; /*数组的空间不够存放字符串*/

☆ 省略数组的大小,进行初始化。这是根据初值中字符的个数确定数组的长度。如:

char s2[]="hello";

它等价于 char s2[6]= "hello";

赋值

与一般数组赋值相同,不能将一个字符串直接赋值给一个数组名,只能对字符数组的元素逐个赋值。如:

char sC[6];

要给它赋值为"hello",只能如下方式:

sC[0]= 'h',sC[1]= 'e',sC[2]= 'l',sC[3]= 'l',sC[4]= 'o',sC[5]= '\0';

而不能是:sC="hello";

也不能是:sC[6]= "hello";

注意:C/C++语言中,无论是字符数组还是数值型数组在程序中只能给它的元素赋值。

字符数组的输入输出

其它类型的数组元素在输入输出时,只能逐个元素实现输入输出,但用字符数组来存放字符串时,可以进行整体的输入输出,当然也可以使用循环将字符数组中的字符一个一个处理输入输出。

一维字符数组的输入输出

例、元素类型为char的数组输入输出例

#include <iostream>

using namespace std;

int main ()

{

   char s[10];

   cout << "请输入字符串:" ;

   cin >>s;  //scanf(" %s",s);

   cout << "字符串是:" << s << endl; // printf("符串是是: %s ",s);

   

   return 0;

}

运行之,参见下图:

C风格字符串将字符串放在字符数组中,并以空字符'\0'结束,一般利用指针来操作这些字符串。尽管C++支持C风格字符串,但建议在C++程序中尽量不要使用它们。一些用于操作C风格字符串的标准库函数定义在cstring头文件中,是C语言头文件string.h的C++版本。

1)字符串复制函数:

    char *strcpy(char *s,const char ct)

返回值是指向复制后字符串中首字符的指针。。

例子

#include <iostream>

//#include <string.h>

#include <cstring>

using namespace std;

int main ()

{

   char str[] = "just test";

   char des[20];

  

   //cout << strcpy(des, str)<< endl;  //本句和下面两句效果相同,但下面两句更直观说明 strcpy()的含义

   strcpy(des, str);

   cout << des<< endl;

   return 0;

}

运行,参见下图:

2)字符串连接函数:char *strcat(char *s,const char *ct)

将串ct复制到串s的后面,形成一个长串。例如:

#include <iostream>

//#include <string.h>

#include <cstring>

using namespace std;

int main ()

{

   char str1[]="李小明";

   char str2[]="是大学生";

  

   //cout << strcat(str1,str2)<< endl;  //本句和下面两句效果相同

   strcat(str1,str2);

   cout <<str1<< endl;

   return 0;

}

运行,参见下图:

3)字符串比较函数:int strcmp(const char *cs,const char ct)。

两字符串比较是按字典排序方法进行。两个字符串从第一个字符比较起,如果相同,则比较第二个字符,依此类推,直到不同。哪个字符串对应的字符的ASCII码值大,串就大。如果两串直到结束符都相同,则一样大。若两个字符串相等,则返回0;串cs大,则返回正整数;串ct大,则返回负整数。

#include <iostream>

//#include <string.h>

#include <cstring>

using namespace std;

int main ()

{

   char strA[] = "Hello world";

   char strB[] = "Hello, world";

   cout << strcmp(strA, strB)<< endl;

   return 0;

}

运行,参见下图:

4)求字符串长度函数:int strlen(const char *s)

这里求出的串长度不包含串结束符在内。而sizeof运算符包括结束符,还包括没有使用的单元。

#include <iostream>

//#include <string.h>

#include <cstring>

using namespace std;

int main ()

{

   char str[] = "Hello world";

   cout << strlen(str) << endl;

   return 0;

}

运行,参见下图:

现在简要介绍二维字符数组

二维字符数组的初始化

与其它二维数组初始化一样,有以下几种方式:

☆用初值列表方式。如:

char s3[2][4]={{ ' a', 'b', 'c', '\0'},{' m', 'n', 'l', '\0'}};

☆用字符串常量方式。如:

char s3[2][4]={ " abc"," mnl"};

☆省略第一维大小的方式来初始化。如:

char s3[][4]={{ ' a', 'b', 'c', '\0'},{' m', 'n', 'l', '\0'}};

char s3[][4]={ " abc","mnl"};

根据分行赋值的大括号{}的个数或常量字符串的个数确定第一维的大小为2。

二维字符数组的输入输出

二维字符数组的每一行可以用来存放一个字符串,因此可以将二维字符数组看成是一个一维数组,数组中的元素为字符串,即被看作是字符串数组。如:

char ss[3][10];

数组ss可以被看作是用来存放3个字符串的字符串数组,每个字符串的长度不超过9。这时,对数组中字符串的引用,只使用第一个下标。即:

ss[0]:表示第一个字符串的首地址;

ss[1]:表示第二个字符串的首地址;

ss[2]:表示第三个字符串的首地址;

元素类型为char的二维数组输入输出例:

#include <iostream>

using namespace std;

int main ()

{

   char ss[3][10];

   int i;

   for(i=0;i<3;i++)

       {

           cout << "请输入字符串:" ;

        cin >>ss[i];  //scanf(" %s",ss[i]);

         } 

      

   for(i=0;i<3;i++) 

       cout << "字符串" << i + 1 << "是:"<< ss[i] << endl; // printf("字符串%d是:%s ",,i+1,ss[i]);

   

   return 0;

}

运行,参见下图:

二、C++ 中的 String 类

使用 string 类需要包含头文件<string>

https://cplusplus.com/reference/string/  】

C++ 标准库提供了 string 类类型(string class type),支持上述所有的操作,另外还增加了其他更多的功能。我们将学习 C++ 标准库中的这个类,现在让我们先来看看下面这个实例:

现在您可能还无法透彻地理解这个实例,因为到目前为止我们还没有讨论类和对象。所以现在您可以只是粗略地看下这个实例,等理解了面向对象的概念之后再回头来理解这个实例。

#include <iostream>

#include <string>

using namespace std;

int main ()

{

   string str1 = "Hello";

   string str2 = "World";

   string str3;

   int  len ;

   // 复制 str1 到 str3

   str3 = str1;

   cout << "str3 : " << str3 << endl;

   // 连接 str1 和 str2

   str3 = str1 + str2;

   cout << "str1 + str2 : " << str3 << endl;

   // 连接后,str3 的总长度

   len = str3.size();

   cout << "str3.size() :  " << len << endl;

   return 0;

}

运行之,参见下图:

定义 string 变量(对象)的方法:

string s1;

string s2 = "c plus plus";

string s3 = s2;

string s4 (5, 's');

变量 s1 只是定义但没有初始化,编译器会将默认值赋给 s1,默认值是"",也即空字符串。

变量 s2 在定义的同时被初始化为"c plus plus"。与C风格的字符串不同,string 的结尾没有结束标志'\0'。

变量 s3 在定义的时候直接用 s2 进行初始化,因此 s3 的内容也是"c plus plus"。string 变量也可以用C风格的字符串进行赋值。

变量 s4 被初始化为由 5 个's'字符组成的字符串,也就是"sssss"。

当我们需要知道字符串长度时,可以调用 string 类提供的 length() 函数。如

string s = "http://c.biancheng.net";

int len = s.length(); //结果为22。string 的末尾没有'\0'字符,所以 length() 返回的是字符串的真实长度,而不是长度 +1。

string 类为我们提供了一个转换函数 c_str(),该函数能够将 string 字符串转换为C风格的字符串,并返回该字符串的 const 指针(const char*)。例如

string path = "D:\\demo.txt";

path.c_str()

string 字符串的输入输出

string 类重载了输入输出运算符,可以像对待普通变量那样对待 string 变量,也就是用>>进行输入,用<<进行输出。例:

#include <iostream>

#include <string>

using namespace std;

int main(){

    string s;

    cin>>s;  //输入字符串

    cout<<s<<endl;  //输出字符串

    return 0;

}

下面介绍字符串的常见操作。

☆访问字符串中的字符的例:

#include <iostream>

#include <string>

using namespace std;

int main(){

    string s = "abcDEF1234";

    for(int i=0,len=s.length(); i<len; i++){

        cout<<s[i]<<" ";

    }

    cout<<endl;

    s[4] = '6';

    cout<<s<<endl;

    return 0;

}

运行之,参见下图:

☆字符串的拼接

有了 string 类,我们可以使用+或+=运算符来直接拼接字符串,非常方便,就不需要使用C语言中的 strcat()、strcpy()、malloc() 等函数来拼接字符串了,不用担心空间不够会溢出问题了。

可以用+运算符来拼接字符串时,运算符的两边可以都是 string 字符串,也可以是一个 string 字符串和一个C风格的字符串,还可以是一个 string 字符串和一个字符数组,或者是一个 string 字符串和一个单独的字符。例:

#include <iostream>

#include <string>

using namespace std;

int main(){

    string s1 = "Hello ";

    string s2 = "World";

    char s3[] = "世界";

    string s5 = s1 + s2;

    string s6 = s1 + s3;

   

    cout<<s5<<endl<<s6<<endl;

   

    return 0;

}

运行输出如下:

☆string 字符串的增删改查

C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的插入、删除、更改、查询等操作。

插入子字符串函数

insert (size_t pos, const string& str);

pos 表示要插入的位置,也就是下标;str 表示要插入的字符串,它可以是 string 字符串,也可以是C风格的字符串。

删除子字符串函数

erase (size_t pos = 0, size_t len = npos);

pos 表示要删除的子字符串的起始下标,len 表示要删除子字符串的长度。如果不指明 len 的话,那么直接删除从 pos 到字符串结束处的所有字符(此时 len = str.length - pos)。

提取子字符串函数

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

pos 为要提取的子字符串的起始下标,len 为要提取的子字符串的长度。

字符串插入、删除、提取子字符串的例

#include <iostream>

#include <string>

using namespace std;

int main(){

    string s1, s2, s3, s4, s5;

    s1 ="1234567890";

    s2 = "aaa";

    s1.insert(5, s2); //插入字符串

    cout<< s1 <<endl;

    s3 ="1234567890";

    s3.erase(8); //删除字符串

    cout<< s3 <<endl;

    s4 ="1234567890";

    s5 = s4.substr(4, 3); //提取子字符串

    cout<< s5 <<endl;

    return 0;

}

运行输出如下:

字符串查找

string 类提供了几个与字符串查找有关的函数:find() 函数、rfind() 函数、find_first_of() 函数

在此仅介绍find() 函数,其它可上网查阅。

find()函数两种原型为:

find (const string& str, size_t pos = 0)

find (const char* s, size_t pos = 0)

第一个参数为待查找的子字符串,它可以是 string 字符串,也可以是C风格的字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。

find()函数的例子

#include <iostream>

#include <string>

using namespace std;

int main(){

    string s1 = "first second third";

    string s2 = "second";

    int index = s1.find(s2,5);

    if(index < s1.length())

        cout<<"Found at index : "<< index <<endl;

    else

        cout<<"Not found"<<endl;

    return 0;

}

运行输出如下:

附录:

C++语言之输入输出深入介绍 https://blog.csdn.net/cnds123/article/details/126358415

C语言printf和scanf函数的格式控制符介绍https://blog.csdn.net/cnds123/article/details/121372599

C字符串与C++字符串的对比 https://blog.csdn.net/cnds123/article/details/119186596

  • 23
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值