《白话C++》第10章 Page39 10.3 字符串处理 纯C字符串

10.3.1  std:string

1.纯C字符串

纯C语言使用char * 处理字符串,会自动在字符串最尾部,添加一个零字符‘\0’表示字符串的结束。

这是个绝妙的穿凿,不过也有坏处,比如有时字符串并不一定都是可视字符,如果不可视的内容含有‘\0’会难办;

再比如每一次取其长度,都需要从头到尾计算一次;

最后哪怕是这个‘\0’结尾也不是100%可依赖,C语言中的字符数组,就不会为我们自动添加结束符。

【小提示】:字符串VS字符数组

代码中,abc含有4个元素,最后一个元素视自动添加的 '\0'字符,而abc2含有3个元素

这个特性当然是对的,有时候确实只是想要一个“字符的数组”,而不是要一个“字符串”。

困难在于接下来的是:程序员需要很清楚abc2和abc之间的区别,如果有一个函数:

void foo(char* p);

foo中对p的处理,往往依赖与它结束在  '\0'上的这个事实。但程序员一不小心,就会把abc2传递给它!

纯C字符串最难搞的还是内存管理,常见的如:只是想修改字符串的内容:

char * p = "abc";//好的C++编译环境下会得到编译警告
p[0] = 'A';
...

linux下的执行情况:

这样做,程序会死的......后面再谈

#include <cstring> //strcpy()

.....

//一个初始化,牵涉4个知识点
//1)内存分配
//2)字节尺寸
//3)类型强转
//4)结束字符
char * p = (char*)malloc(9 * sizeof(char));

//strcpy不安全,复杂情况下建议使用strncpy(...)
//前面的‘9’ = "d2school"的长度 + 1
strcpy(p, "d2school");

//往短处改...
//方便,不过占用内存还是9 byte
strcpy(p, "school");

//实际内存不增加,但增加有效内容的字符个数
//立即数很讨厌
p[6] = '-';
//别忘了自己补零
p[7] = '\0';

//往长处改...
//realloc保障原内容还在
p = (char*)realloc(p, 10 * sizeof(char));
strcat(p, "D2");

...

//释放:
free(p);

在C++环境下,以上代码也可以使用new[ ]/delete[ ]处理,但在模拟realloc(保留原有内容时),只会更复杂。

所以,如果程序中有大量字符处理,特别是修改字符串内容的操作,请自行或从别人那里搞一套字符串管理工具,通常都给予复杂的后果。

纯C字符串还有一些小特性是初学者的陷阱,比如用户会直觉地使用“==”来判断两个字符串是否相等,但这样其实是在比较两个字符指针的指向是否相等:

char const * p1 = "ABC";
char const * p2 = "ABC";

if(p1 == p2)
{
    ...
}

除非代码太优化而带来副作用否则以上条件判断理所当然不成立,因为p1和p2各自指向一旦内存(尽管内存中的内容刚好一样)。

编译器还是太优化了

再如,由于需要兼容很长一段历史上C语言没有const修饰的问题编译器允许用普通的char*指向一段其实是不可修改的内存

//其实是:char const* ppp = "Tom";
char* ppp = "Tom";
ppp[1] = 'i';
cout << ppp << endl;

/*上述代码想修改ppp的内容,所以正确写法
是用字符数组(或者在堆中分配)*/
char ppp2[] = "Tom";
ppp2[1] = 'i';
cout << ppp2 << endl;

执行以上代码,通常程序会挂掉,除了const问题之外,还需要理解代码中,ppp是指向一段静态数据段,而ppp2则是在栈中分配内存,再从静态数据段中复制字符串内容……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值