4.5.2 连接以空字符结尾的字符串
strcat()函数用来拼接两个以空字符结尾的字符串。第二个参数指定的字符串被添加到第一个参数指定的字符串后面。下面是使用该函数的一个示例:
- char str1[30]= "Many hands";
- char* str2(" make light work.");
- strcat(str1, str2);
- cout << str1 << endl;
注意,第一个字符串存储在可以容纳30个字符的数组str1中,它远远超过了初始字符串"Many hands"的长度。第一个参数指定的字符串必须有足够的空间来容纳连接后的两个字符串。如果空间不够,肯定会出现灾难性的结果,因为那样函数会重写第一个字符串之外的区域。
|
| (点击查看大图)图 4-9 |
如图4-9所示, 第二个参数指定的字符串的第一个字符重写了第一个参数结尾的空字符,第二个字符串余下的所有字符都被复制过去,包括结尾的空字符。因此,这段代码的输出将为:
- Many hands make light work.
strcat()函数返回第一个参数的指针,因此我们可以将上面那段代码中的后两个语句合并为一个语句:
- cout << strcat(str1, str2) << endl;
wcscat()函数拼接宽字符串,不过其他方面与strcat()函数的运行方式完全相同。
用strncat()函数可以将一个以空字符结尾的字符串的一部分附加到另一个字符串后面。前两个参数分别是目标字符串和源字符串,第三个参数是要从源字符串中附加的字符个数。对于图4-9中定义的字符串,这里有一个使用strncat()的示例:
- cout << strncat(str1, str2, 11) << endl;
执行这个语句后,str1就包含字符串"Many hands make light"。这个运算将str2中的11个字符附加到str1上,重写了str1中结尾的'\0',然后在末尾加上一个'\0'字符。wcsncat()提供的功能与strncat()相同,只是它用于宽字符串。
到目前为止所介绍的拼接字符串的函数都依靠查找字符串中结尾的空字符才能正常运行,因此当处理不受信任的数据时它们也是不安全的。<cstring>中的strcat_s()、wcscat_s()、strncat_s()和wcsncat_s()函数提供了安全的替换方法。举个例子,下面说明了如何用strcat_s()来计算图4-9中显示的运算:
- const size_t count = 30;
- char str1[count]= "Many hands";
- char* str2(" make light work.");
-
- errno_t error = strcat_s(str1, count, str2);
-
- if(error == 0)
- cout << " Strings joined successfully." << endl;
-
- else if(error == EINVAL)
- cout << "Error" Source or destination string is NULL." << endl;
-
- else if(error == ERANGE)
- cout << " Error! Destination string too small." << endl;
方便起见,这里将数组大小定义成了常量count。strcat_s()的第一个参数是目标字符串,将源字符串向这个目标字符串附加第3个参数所指定个数的字符。第二个参数是目标位置上可用的字节总数。这个函数返回一个errno_t类型的整数值来指示拼接情况。如果运算成功,错误返回值为0;如果源或目标是NULL,错误返回值为EINVAL;如果目标长度太小,则返回ERANGE。在发生错误的事件中,目标字符串不会有变化。错误代码值EINVAL和ERANGE都是在<cerrno>头文件中定义的,因此这里需要一个#include指令以及一个<cstring>才能正确地编译上面的代码片段。当然,没有人强迫我们测试函数可能返回的错误代码,如果不定义错误代码,就不需要<cerrno>的#include指令。