[置顶] C++primer 4.3 C风格字符串--字符数组(strlen、strcpy、strcat)上

时间:2023-01-04 17:29:33

简介

  1. C风格字符串是以空字符null结束的字符数组,因为标准库函数都是根据最后面的null来做是否结束的判断的,所以,后面必须加上一个null

  2. 字符串的比较和比较结果都须使用标准库函数strcmp进行

建议

  1. 在使用标准库函数之前,必须在头文件包含处写上 #include < cstring >

  2. 使用strlen函数计算字符数的时候,返回S的长度,不包括字符串结束符null

  3. 在使用处理C风格字符串的标准库函数strlen时,不要忘记字符串结束符null,一定要加上!!!

  4. 传递给标准库函数strcat和strcpy的第一个实参数必须有足够大的空间存放新生成的字符串,而且不要忘记预留一个null(’\0’)字符

  5. 尽可能使用标准库类型string,少用C风格字符串

===========================================================

一、C风格字符串

1、C风格字符串简介

  1. C风格字符串不能归结为C语言的类型,也不能归结为C++语言的类型,而是以空字符null结束的字符数组
char ca1[]={'C','+','+'};
char ca2[]={'C','+','+','\0'};//有null
char ca3[]="C++";//自动在末尾添加null
const char *cp="C++";//自动在末尾添加null
char *cp1=ca1;//指向数组的第一个元素,但是不是C风格字符串
char *cp2=ca2;//指向一个以null结尾的字符数组的第一个元素
// ca1和cp1都不是C风格字符串,ca1是一个不带结束符null的字符数组,指针指向它,因此,它指向的并不是以null结束的数组。
//其他都是C风格字符串

二、C风格字符串的使用

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

const char *cp="some value";
while(*cp
{
++cp;
}
//如果cp所指的字符数组没有null结束符,则循环失败。这时,循环会从cp指向的位置开始读数,直到遇到内存中某处null结束符为止。

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

  • 常用标准库函数有

    1. strlen(s) :返回S的长度,不包括字符串结束符null

    2. strcmp(s1,s2):比较两个字符串s1和s2是否相同,若相同,返回0若前者大于后者,返回正数,否则返回负数

    3. strcat(s1,s2) :将字符串s2连接到s1后,返回s1;

    4. strcpy(s1,s2):s2复制给s1,返回s1;

  • 使用这些库函数之前要包含头文件 #include < cstring>

  • 字符串的比较和比较结果都须使用标准库函数strcmp;

  • 不要忘记字符串结束符null

    • 标准库函数石strlen总是假定其参数字符串以null字符结束,当调用该标准库函数时系统将会从实参ca指向的内存空间开始一直搜索结束符,直到恰好遇到null为止

    • strlen返回这一段内存空间中总共有多少个字符

  char ca[]={'C','+','+'};
cout<<strlen(ca)<<endl;` //因为没有null结束符,所以这样是不对的
//在这个例子里,ca是一个没有null结束符的字符数组,则计算的结果不可预料。所以要在最后面加上一个' \0 '
  • 调用者必须确保目标字符串具有足够的大小
    • 传递给标准库函数strcat和strcpy的第一个实参数必须有足够大的空间存放新生成的字符串。
    • 在使用strcat和strcpy函数时要预计存放字符串的空间大小的时候,一定要记住算上最后的null字符
char largeStr[16+18+2];
strcpy(largeStr,cp1);//复制cp1到largeStr,返回largeStr
strcat(largeStr," ");//将两个字符串进行连接,返回largeStr
strcat(largeStr,cp2);
cout<<largeStr<<endl;
//问题在于我们经常会算错largeStr需要的大小。
//同样的,如果cp1或cp2所指向的字符串大小发生了变化,largeStr所需要的大小则会计算错误。
//上述代码常会导致安全漏洞,很容易出错。
  • 使用strn函数处理C风格字符串
    • 使用strncat和strncpy比strcat 和strcpy函数更安全
代码:略!!!!

四、尽可能使用标准库类型string

  • 编写两个C风格字符串字面值,把结果存储在一个C风格字符串中,事先一定要算术null字符。
#include <iostream>
#include<string>
#include<vector>
#include<cstring> //使用下面的那些
using namespace std;
int main (){
//先定义两个字符串
const char*cp1="marry and linda";
const char*cp2="are friends";
//计算这两个串的长度,strlen函数是不计算最后面的那个空字符的
size_t len=strlen(cp1)+strlen(cp2);
//定义一个动态数组,预先估计需要的存储空间大小,最后加1的原因是存放一个空字符null在末尾
char * result_str=new char[len+1]; //加1不要忘记
strcpy(result_str,cp1);
strcat(result_str,cp2);strcat(result_str,'\0');


while(*result_str)
cout<<result_str<<endl;
delete [] result_str;//清楚内存空间!!勿忘!!!
return 0;
}
注意到后面的while循环了吗,这个语句在这里其实是有问题的,因为一直都没法结束,一直在输出“marry and linda are friends”。问题就在于这两个字符串连接之后,在最末尾是没有null'\0')结束符的,所以没法判定是否结束就一直在输出。
  • 使用string连接两个字符串
#include <iostream>
#include<string>
#include<vector>
#include<cstring> //使用下面的那些
using namespace std;
int main (){
const string str1("mamjkjasdk");
const string str2("uuuuuuuu");
string result_str;
result_str=result_str+str1;
result_str=result_str+str2;
return 0;
}
显然,使用string对象比使用C风格字符串方便很多。