在编写C++程序时,不可避免会遇到strcpy()函数和其安全版本strcpy_s()函数,其实之所以会推出_s版本的函数,就是为了使编程更加安全,然而为了保证安全,也就会更容易使我们编写的代码“被报错”。所以这里来简略说一下strcpy()函数和strcpy_s()函数的使用及注意事项。
首先,我们知道原函数strcpy()函数和安全版本strcpy_s()函数都是存在于头文件
#include
其次,原函数strcpy()函数是存在于标准名称空间std中的成员,所以要使用strcpy()函数,还需要加上以下语句:
using namespace std;
或者:
using std::strcpy;
或者在每次使用strcpy()函数时,前面加上名称空间:
std::strcpy(str1, str2);
但是对于最新的编辑器,往往你正常使用strcpy()函数,还是会报错,例如下面这个简单的例子:
// strcpy.cpp -- test the strcpy function and strcpy_s function
#include "stdafx.h"
#include
#include
int main()
{
char str1[20];
char str2[20];
std::cout << "Please enter str2: ";
std::cin.get(str2, 20);
std::strcpy(str1, str2);
std::cout << "str1 is " << "\" " << str1 << "\".\n";
system("pause");
return 0;
}
正常来说,语法上没有任何问题,但是运行时,Visual Studio 2017 会报错,显示如下:
意义很简单,就是告诉你,strcpy()函数不安全,必须改为使用strcpy_s()函数,首先不管改成strcpy_s()函数之后会发生什么后续问题,其实从理论上来说,上面的代码语法上和逻辑上来说都是对的,那么怎么避免编辑器强制要求你使用安全版本呢?
其实解决方法有很多,单单是避免上图中的错误代码4996的情况,可以使用编辑器的选择性提供warning功能,在include语句前面加上下句:
#pragma warning( disable : 4996)
但是这种解决方法有时候不能解决问题,例如VS2017我就试过好像不行,那么我们就索性关闭warning功能就好了,完成这个任务的方法是在#include
#define _CRT_SECURE_NO_WARNINGS
#include
VS2017里面,这句应该是加在头文件“stdafx.h”里面。
加完之后,再次运行相同的程序,就可以正常运行了,显示结果如下图所示:
那么解决了不使用安全版本的问题,接下来就来说一下使用安全版本的情况。
如果我们选择相信编辑器,那么我们就会把strcpy()函数改成使用strcpy_s()函数,改完之后运行首先会遇到以下错误:
这是因为之前使用strcpy()函数时,我们知道该函数是标准名称空间std的成员,而安全版本strcpy_s并不是该名称空间的成员,所以“std::”应该被去掉,去掉之后再次运行,就会正常运行了。
但是有时候,编辑器在你去掉“std::”还是会出现错误,错误说明是:1.没有与参数列表匹配的 重载函数"strcpy_s"实例;2."strcpy_s":函数不接受2个参数。
如下图所示:
这是因为strcpy_s()函数是有两个版本,用两个参数、三个参数都可以,只要可以保证缓冲区大小。
三个参数时:
errno_t strcpy_s(
char *strDestination,
size_t numberOfElements,
const char *strSource
);
两个参数时:
errno_t strcpy_s(
char (&strDestination)[size],
const char *strSource
); // C++ only
所以,若我们使用new来分配储存空间时,就会出现上面说的不能保证缓冲区大小的问题了。
看下面的代码:
char * str;
str = new char[4];
strcpy_s(str, "C++");
语法来说没有什么问题,但是因为str的储存空间是使用new临时分配的,所以并不能保证缓冲区大小,点击运行就会出现上述的两种错误了。
这种情况的解决方法其实很简单,那就是不符合2个参数的版本就使用3个参数的版本呗。在两个str之间,加上一个参数,标识长度。
所以完整代码如下:
// strcpy.cpp -- test the strcpy function and strcpy_s function
#include "stdafx.h"
#include
#include
int main()
{
char str1[20];
char str2[20];
std::cout << "Please enter str2: ";
std::cin.get(str2, 20);
strcpy_s(str1, str2);
std::cout << "str1 is " << "\"" << str1 << "\".\n";
char * str;
str = new char[20];
strcpy_s(str, strlen(str1)+1, str1);
std::cout << "str is " << "\"" << str << "\".\n";
system("pause");
return 0;
}
这里分别使用了2个参数和3个参数的strcpy_s()函数版本。
后面使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度+1,因为strlen()返回字符串长度,但是不包括字符串末尾的空字符,所以+1。
上述代码运行结果如下图所示:
以上就是strcpy()函数和strcpy_s()函数的基本使用和注意事项了,希望对大家有所帮助~