欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++中C风格字符串与字符数组实例讲解

程序员文章站 2024-02-01 11:40:10
1 字符串字面值与C风格字符串 在C++中,双引号括起来的零个或多个字符构成字符串字面值,如 “Hello World” 字符串字面值的类型实际上...

1 字符串字面值与C风格字符串

在C++中,双引号括起来的零个或多个字符构成字符串字面值,如

“Hello World”

字符串字面值的类型实际上是由常量构成的数组,编译器在每个字符串的结尾处添加一个空字符(’\0’),因此字符串字面值的实际长度要比它的内容多1。

字符串字面值是一种通用结构的实例,这种结构即是C++由C继承而来的C风格字符串。C风格字符串不是一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法。按此习惯书写的字符串存放在字符数组中,并以空字符结束。

2 字符数组

字符数组的详细解释请参考《C++中字符数组》。可以使用字符串字面值对字符数组进行初始化。

char a[] = “C++”;

在“1字符串字面值与C风格字符串”中提到,字符串字面值的结尾还包含一个空字符,此时数组a的维度是4。

3 操作C风格字符串的函数

处理C风格字符串的函数有strlen()、strcmp()、strcat()以及strcpy()等。这些函数在cstring头文件中定义,cstring是C语言头文件string.h的C++b版本,因此,在使用这些函数时,应该包含cstring头文件。

#include 

4 实战

4.1 问题提出

在CSDN论坛上有朋友提到如下问题:

char *src = "Danny";

const char *addition = "Andy";

strcat(src, addition);

程序报错,而如果将程序改为

char src[] = "Danny";

const char *addition = "Andy";

strcat(src, addition);

则不报错。

4.2 问题分析

4.2.1 内存结构

C++程序在内存中主要分为五个数据段,分别是代码段、数据段、BBS段、堆和栈。其中,数据段中保存的是全局变量和静态变量,字符串字面值也保存在数据段中;而栈中保存的是程序临时创建的局部变量。

4.1.2 处理数据段中的数据

对于当strcat()函数的两个参数都是字符指针时的情况,此时两个字符指针均指向保存在数据段中的字符串字面值,如图1所示。

C++中C风格字符串与字符数组实例讲解

图1 src和addition的内容

从图1中可以看出,字符串字面值”Danny”保存在0x00347838中,而字符串字面值”Andy”保存在0x00347830中。之后通过strcat()函数将”Andy”附加到”Danny”之后,实际上是对程序的数据段进行操作,而程序的数据端是不允许写入的,因此报错信息是“写入位置时发生访问冲突”,如图2所示。

C++中C风格字符串与字符数组实例讲解

图2 报错信息

4.2.2 处理栈中的数据

如果将src定义为字符数组,则此时src保存在栈中,程序允许对栈中的数据进行修改。src的地址如图3所示。

C++中C风格字符串与字符数组实例讲解

图3 src和addition的内容

从图3中可以看出,src的地址是在0x007bf7ec处,该地址位于程序的栈中;而addition的地址是在0x002f7830处,该地址位于程序的数据段中。

此时,虽然strcat()函数不再报错,但是当main()函数返回时,还会弹出栈被破坏的信息,如图4所示。

C++中C风格字符串与字符数组实例讲解

图4 栈被破坏信息

正如“2 字符数组”中提到,数组src的维数是6,使用strcat()函数,将长度为5的字符串字面值“Andy”附加到长度为6的src的后面,那么肯定覆盖了程序堆中的其他数据,因此会弹出堆被破坏的信息。

4.3 问题解决

4.3.1 加大strcat()源维数

如果使用处理字符串字面值的函数strcat(),则需要将源即src的数据维数变大,使其大于等于“DannyAndy” 的长度,即不小于10。例如

char src[11] = "Danny";

4.3.2 使用C++的string类

标准库类型string表示可变长度的字符序列,使用string类型必须首先包含string头文件。

#include 

string src = "Danny";

string addition = "Andy";

src += addition;