前言

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<string.h>  (C)  、 #include<cstring>

声明:

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 <iostream>
#include <cstring>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 <iostream>
#include <cstring>#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 <iostream>
#include <cstring>#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 <iostream>
#include <cstring>#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 <iostream>
#include <cstring>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 <iostream>
#include <string>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。参考<<C++ Primer>>第5版,P81

(2)string 怎么转 char* ?

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

C字符串操作strcat/strcat_s详解相关推荐

  1. C语言常用字符串操作函数大全详解(strstr,strtok,strrchr,strcat,strcmp,strcpy,strerror,strspn,strchr等)

    参考:string.h中常用字符串操作函数说明(strstr,strtok,strrchr,strcat,strcmp,strcpy,strerror,strspn,strchr等) 作者:一只青木呀 ...

  2. C字符串操作strlen/strnlen_s详解

    前言 strcat.strcpy.strcmp.strlen是C中针对字符串的库函数,这四个函数不安全,然后C针对这个情况整出strcat_s.strcpy_s.strncmp.strnlen_s(这 ...

  3. python3 format函数_Python学习教程:Python3之字符串格式化format函数详解(上)

    Python学习教程:Python3之字符串格式化format函数详解(上) 概述 在Python3中,字符串格式化操作通过format()方法或者f'string'实现.而相比于老版的字符串格式化方 ...

  4. php mysql PDO 查询操作的实例详解

    php mysql PDO 查询操作的实例详解 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...

  5. MongoDB查询性能分析—— explain 操作返回结果详解

    MongoDB 提供 db.collection.explain(), cursort.explain() 及 explain 命令获取查询计划及查询计划执行统计信息. explain 结果将查询计划 ...

  6. format函数_Python学习教程:Python3之字符串格式化format函数详解(上)

    Python学习教程:Python3之字符串格式化format函数详解(上) 概述 在Python3中,字符串格式化操作通过format()方法或者f'string'实现.而相比于老版的字符串格式化方 ...

  7. [转载] python 遍历字符串 字符_python 遍历字符串(含汉字)实例详解

    参考链接: Python字符串| rfind python 遍历字符串(含汉字)实例详解 python 遍历字符串(含汉字)实例详解 s = "中国china" for j in ...

  8. IOS数据库操作SQLite3使用详解(转)

    iPhone中支持通过sqlite3来访问iPhone本地的数据库. 具体使用方法如下 1:添加开发包libsqlite3.0.dylib 首先是设置项目文件,在项目中添加iPhone版的sqlite ...

  9. IOS数据库操作SQLite3使用详解

    sqlite数据库iosdatabasesqlinteger 目录(?)[+] iPhone中支持通过sqlite3来访问iPhone本地的数据库. 具体使用方法如下 1:添加开发包libsqlite ...

最新文章

  1. matlab 工业相机 曝光时间_Matlab CCD工业相机采集图像问题 - 信息科学 - 小木虫 - 学术 科研 互动社区...
  2. Dokan虚拟磁盘开发实战
  3. Flink从入门到精通100篇(二十一)-Apache Flink 与 Apache Hive 的集成
  4. Map集合中的一些具体方法的体现
  5. Linux网络管理基本
  6. python 高阶函数一 概念
  7. linux windows 结构体,Linux下C语言——结构体对齐
  8. python读取xps文件_Python操作PDF-文本和图片提取(使用PyPDF2和PyMuPDF)
  9. 数据库实验八 触发器实验
  10. aop:aspectj-autoproxy
  11. 'wx' is not defined no-undef
  12. 实现一个直播视频app源码的邀请码功能
  13. Google推荐的15条HTML 5代码军规
  14. 数学之英文写作——基本中英文词汇(一般术语、算术与代数的常用词汇)
  15. 玩转华为数据中心交换机系列 | 配置LACP模式的跨设备聚合(单机)
  16. 植物大战僵尸2android最新版,植物大战僵尸2
  17. 美国哪些公司实习生工资高?Facebook每月给5万5
  18. 2020年找工作总结之【自我介绍】
  19. oracle修改数据文件名称
  20. 简诉android源代码编译过程,Android源码编译过程及原理(二)

热门文章

  1. “裸辞”真的就会没前途吗?面对他你是会 “雪上加霜“,还是“绝处逢生“?
  2. C# 使用BitBlt进行窗口抓图的示例
  3. synopsys的rm流程_Synopsys工具简介(转)
  4. 中国国内开源社区发展的困境——以FreeBSD 吧为例
  5. 食品营养成分检测有什么作用
  6. 外贸网站访问速度慢的原因
  7. 什么是 Hudi Timeline (时间线)
  8. Doris之sequence列
  9. 教育——教学管理平台
  10. iOS:2015年07月最新苹果IOS上架App Store商店步骤