字符串字面值

时间:2021-01-01 14:42:41

字符串字面值的类型就是const char类型的数组。

标准库函数strlen用于计算C风格字符串的字符个数,不包括null结束符。

一、字符字面值

字符字面值: 'A' //single quote:character literal
字符串字面值: "A" //double quote:character string literal.包含字母A和空字符的字符串

1.string literal:字符串直接量

cout<<"hello"<<endl;

代码中通过包含“hello”字符串自身来将其输出,并为包含该字符串的变量。

2.字符串直接量可以复制给变脸,但是与字符串直接量相关联的内存空间位于只读部分,因此它是敞亮字符数组。

char* ptr = "hello";
ptr[1] = 'a' ; //crash! attempts to write to read-only memory.

因此,当引用字符串直接量的时候使用指向const的字符数组:

const char* ptr = "hello";
ptr[1] = 'a' ; //bug! attempts to write to read-only memory.

3. 当将字符串直接量赋值给字符数组的初始值的时候,由于字符数组值存放于栈中,不允许引用其他地方的内存,因此编译器会将字符串直接量复制到栈的数组内存中。因此,可以进行相应的修改。

char stackArray[] = "hello";
stackArray[1] = 'a';

二、C++风格字符串

C++风格字符串:使用C++风格字符串的时候,要将它当做是一个普通的类型,如int,这样反而会避免将string作为一个类来理解所带来的很多问题。

1.支持<cstring>中许多函数完成的同样操作。

2.字符串定义:   

string myString = "hello";

3.操作符 = :复制字符串,比如:

string newone = original;

会将后者复制给前者,不会出现两个变量同样指向一个内存的情况。

4.可以向int一样使用==之类的操作符。

5.可以改变字符串中的某一个字符。如:

string myString = "hello";
myString[0] = 'l' ;

这种操作是允许的。

三、C风格字符串

字符串字面值的类型实质是const char类型的数组。C++从C语言继承下来的一种通用结构是C风格字符串,而字符串字面值就是该类型的实例。C风格字符串是以null结束的字符串数组:

char ca1[]={'C', '+', '+'}; // no null, not C-style string
char ca2[]={'C', '+', '+', '\0'}; // explicit null
char ca3[]="C++"; // null terminator added automatically
const char *cp="C++"; // null terminator added automatically
char *cp1=ca1; // points to first element of a array, but not C-style string
char *cp2=ca2; // points to first element of a null-terminated char array

ca1和cp1都不是C风格字符串:ca1是一个不带结束符null的字符数组,而指针cp1指向ca1,因此,它指向的并不是以null结束的数组。其他的声明则都是C风格字符串。

2.1 C风格字符串的使用

C++语言通过(const) char *类型的指针来操纵C风格字符串。

const char *cp = "some value"; // 一个C风格字符串
while(*cp) //判断cp当前指向的字符是true还是false,true表明这是除null外的任意字符
{
// do something to *cp
++cp;
}

2.2 C风格字符串的标准库函数

     下面列出了C语言标准库提供的一系列处理C风格字符串的库函数。要使用一下这些标准库函数,必须包含响应的C头文件:
    #include <cstring> 
cstring是string.h头文件中的C++版本,而string.h是C语言提供的标准库
字符串字面值
//操纵C风格字符串的标准库函数(参数类型省略,都是char *类型):
strlen(s) // 返回s的长度,不包括字符串结束符null
strcmp(s1, s2) //当s1<s2时,返回值<0 ,当s1=s2时,返回值=0 ,当s1>s2时,返回值>0
strcat(s1, s2) // 将字符串s2连接到s1后,并返回s1
strcpy(s1, s2) // 将s2复制给s1,并返回s1
strncat(s1, s2, n) // 将s2的前n个字符连接到s1后面,并返回s1
strncpy(s1, s2, n) // 将s2的前n个字符复制给s1,并返回s1
if(cp1 < cp2) // compares address, not the values pointed to
const char *cp1 = "A string example";
const char *cp2 = "A different string";
int i=strcmp(cp1, cp2); // i is positive
i=strcmp(cp2, cp1); // i is negative
i=strcmp(cp1, cp1); // i is zero
字符串字面值

 

2.3 永远不要忘记字符串结束符null

在使用处理C风格字符串的标准库函数时,牢记字符串必须以结束符null结束:
char ca[]={'C', '+', '+'}; // not null-terminated
cout << strlen(ca) << endl; // disaster: ca isn't null-terminated


2.4 调用者必须确保目标字符串具有足够的大小

一定要计算好目标字符串的大小。防止数组溢出。
字符串字面值
// Dangerous:What happens if we miscalculate the size of largeStr?
char largeStr[16+18+2]; // will hold cp1 a space and cp2
strcpy(largeStr, cp1); // copies cp1 into largeStr
strcat(largeStr, " "); // adds a space at end of largeStr
strcat(largeStr, cp2); // concatenates cp2 to largeStr
// prints A string example A different string
cout << largeStr << endl;
字符串字面值

 

2.5 使用strn函数处理C风格字符串

相对于上面的strcpy,strcat要安全些。但是要向目标数组复制或串接比其size更多的字符,数组溢出的现象仍然会发生。
char largeStr[16+18+2] // to hold cp1 a space and cp2
strncpy(largeStr, cp1, 17); // size to copy includes the null
strncat(largeStr, " ", 2); // pedantic, but a good habit
strncat(largeStr, cp2, 19); // adds at most 18 characters, plus a null

 

2.6 尽可能使用标准库类型string

使用C++标准库类型string,则不存在上述问题。
string largeStr = cp1; // initialize largeStr as a copy of cp1
largeStr += " "; // add space at end of largeStr
largeStr += cp2; // concatenate cp2 onto end of largeStr

此时,标准库负责处理所有的内在管理问题,我们不必再担心每一次修改字符串时涉及到的大小问题。

对大部分的应用而言,使用标准库类型string,除了增强安全性外,效率也提高了,因此应该尽量避免使用C风格字符串。