菜鸟笔记
提升您的技术认知

c字符串操作strcat/strcat-ag真人游戏

前言

strcat、strcpy、strcmp、strlen是c中针对字符串的库函数,这四个函数不安全,然后c针对这个情况整出strcat_s、strcpy_s、strncmp、strnlen_s(这个并不是替代stelen的)来弥补。而在c 中一般用string。

这篇文章主要讲:strcat以及如何避免不安全的方法。

1 strcat

1.1 函数功能

把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'

 

1.2  函数声明、参数及返回值

头文件:

#include  (c)  、 #include

声明:

char *strcat(char *dest, const char *src)

参数:

dest -- 指向目标字符串,该数组包含了一个 c 字符串,且足够容纳追加后的字符串
           src  -- 指向要追加的字符串,该字符串不会覆盖目标的字符串

返回值:指向dest的指针

 

1.3 注意

(1)src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。最重要的是,strcat函数不检查这些。

(2)strcat返回值有什么作用? 链式传递:strcat(a, strcat(b, c));

 

1.4 strcat代码演示

#include "stdafx.h"
#include 
#include 
int main(){
	char str1[100] = "hello,";
	char str2[] = "world";
	strcat(str1, str2);
	std::cout << "str1 is " << str1 << "str2 is " << str2 << std::endl;
 	return 0;
}

显示结果:

错误    1    error c4996: 'strcat': this function or variable may be unsafe. consider using strcat_s instead. to disable deprecation, use _crt_secure_no_warnings. see online help for details. 

正如前言里说的,微软已经知道strcat等函数不安全了,直接不让你通过了,而解决措施也告诉我们了。但是这里为了先看看strcat,所以先不用strcat_s。

如何忽略这个警告/错误,措施有以下几种:

(1)第一种:_crt_secure_no_warnings

vs中:项目 - 属性 - 配置 - c/c - 预处理器 - 预处理器定义里添加:_crt_secure_no_warnings

 (2)第二种: 加个预处理命令:#pragma warning(disable:4996)

    这里注意:#pragma warning(disable:4996)要放在#include "stdafx.h"后面!(具体可以百度stdafx的用法)

#include "stdafx.h"
#include 
#include 
#pragma warning(disable:4996)
int main(){
	char str1[100] = "hello,";
	char str2[] = "world";
	strcat(str1, str2);
	std::cout << "str1 is " << str1 << std::endl << "str2 is " << str2 << std::endl;
 	return 0;
}
结果显示:
str1 is hello,world
str2 is world
请按任意键继续. . .

ps:这里如果要用strcat,我还是倾向于第二种方法,因为第一种方法久而久之我们自己给忘了,而第二种方法从程序里就能显而易见,从而提醒自己这是个不安全的函数。

 

前面也说,strcat函数有两个条件,dest的空间要能容纳src,且两者内存不能重叠。

下面分别看下不满足上述两个条件,会发生什么。

(1)dest空间不足

#include "stdafx.h"
#include 
#include 
#pragma warning(disable:4996)
int main(){
	char str1[] = "hello,";
	char str2[] = "world";
	strcat(str1, str2);
	std::cout << "str1 is " << str1 << std::endl << "str2 is " << str2 << std::endl;
 	return 0;
}

从结果可以看出:当dest空间不足时,编译是可以通过的,但是在运行时出错。

 

(2)dest和src内存重叠

#include "stdafx.h"
#include 
#include 
#pragma warning(disable:4996)
int main(){
	char str1[100] = "hello,";
	char *str2 = str1   2;
	strcat(str1, str2);
	std::cout << "str1 is " << str1 << std::endl << "str2 is " << str2 << std::endl;
 	return 0;
}

结果:可以编译,但是无输出。

 

strcat小结:

不安全函数,全靠编程者自己注意。这种函数平常练习为了方便用用,真正写代码的时候还是不要用这种函数,东西多了脑子可能就忽视了。

 

1.5 针对strcat解决措施

(1)用strcat_s函数

1 函数声明:(引用msdn)

errno_t strcat_s(char *strdestination, size_t numberofelements, const char *strsource);

 

2 参数及返回值

参数:

strdestination -- 目标字符串缓冲区
           numberofelements -- 源字符串追加到目标字符串缓冲区后的总大小,单位字节

           strsource -- 源字符串缓冲区 

返回值:

0:成功

einval:目标字符串或者源字符串没有初始化

erange:越界

 

3 注意

strcat_s函数从上面可以看出,做了两个检查,字符串有没有初始化和越界。并没有针对内存重叠做出检查。

第一个参数:合并字符串后的大小。即 源字符串大小 目标字符串的大小 '\0'的大小 ,也就是

numberofelements = strlen(strdestination) strlen(strsource) 1;

 

4 代码演示

#include "stdafx.h"
#include 
#include 
int main(){
	_crtsetreportmode(_crt_error, 0);
	char str1[] = "hello,";
	char str2[] = "world";
	int num = strlen(str1)   strlen(str2)   1;
	errno_t rlt = strcat_s(str1, num, str2);
	if (rlt == 0)
		std::cout << "str1 is " << str1 << std::endl << "str2 is " << str2 << std::endl;
	if (rlt == einval)
		std::cout << "no initialize" << std::endl;
	if (rlt == erange)
		std::cout << "dest's size is small!" << std::endl;
 	return 0;
}

但是结果并不是:dest's size is small!

调试的时候,发现rlt=0,而msdn上著名返回值为0即成功。

这个地方我是真的百思不得其解啊!哪位大佬看到了这篇博客,有想法请一定告诉我! 谢谢!

 

(2)用c 的string函数

#include "stdafx.h"
#include 
#include 
int main(){
	char str1[] = "hello,";
	char str2[] = "world";
	std::string rlt = str1   std::string("")   str2;
	std::cout << rlt << std::endl;
	return 0;
}
输出结果:
hello,world
请按任意键继续. . .

用c 中的string类简单粗暴。

但是要注意以下几点

(1)当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是string。参考<>第5版,p81

(2)string 怎么转 char* ?

char *str = const_cast(rlt.c_str());

网站地图