zoukankan      html  css  js  c++  java
  • C++中strcpy()函数和strcpy_s()函数的使用及注意事项

    在编写C++程序时,不可避免会遇到strcpy()函数和其安全版本strcpy_s()函数,其实之所以会推出_s版本的函数,就是为了使编程更加安全,然而为了保证安全,也就会更容易使我们编写的代码“被报错”。所以这里来简略说一下strcpy()函数和strcpy_s()函数的使用及注意事项。

    首先,我们知道原函数strcpy()函数和安全版本strcpy_s()函数都是存在于头文件<cstring>中的,所以程序一开始必须要有以下语句:

    #include <cstring>

    其次,原函数strcpy()函数是存在于标准名称空间std中的成员,所以要使用strcpy()函数,还需要加上以下语句:

    using namespace std;

    或者:

    using std::strcpy;

    或者在每次使用strcpy()函数时,前面加上名称空间:

    std::strcpy(str1, str2);

    但是对于最新的编辑器,往往你正常使用strcpy()函数,还是会报错,例如下面这个简单的例子:

     1 // strcpy.cpp -- test the strcpy function and strcpy_s function
     2  
     3 #include "stdafx.h"
     4 #include <iostream>
     5 #include <cstring>
     6  
     7  
     8 int main()
     9 {
    10     char str1[20];
    11     char str2[20];
    12     std::cout << "Please enter str2: ";
    13     std::cin.get(str2, 20);
    14     std::strcpy(str1, str2);
    15     std::cout << "str1 is " << "" " << str1 << "".
    ";
    16     system("pause");
    17     return 0;
    18 }

    正常来说,语法上没有任何问题,但是运行时,Visual Studio 2017 会报错,显示如下:

    意义很简单,就是告诉你,strcpy()函数不安全,必须改为使用strcpy_s()函数,首先不管改成strcpy_s()函数之后会发生什么后续问题,其实从理论上来说,上面的代码语法上和逻辑上来说都是对的,那么怎么避免编辑器强制要求你使用安全版本呢?

    其实解决方法有很多,单单是避免上图中的错误代码4996的情况,可以使用编辑器的选择性提供warning功能,在include语句前面加上下句:

    #pragma warning( disable : 4996)

    但是这种解决方法有时候不能解决问题,例如VS2017我就试过好像不行,那么我们就索性关闭warning功能就好了,完成这个任务的方法是在#include<stdio.h>的前面加上一句,如下所示:

    1 #define _CRT_SECURE_NO_WARNINGS
    2 #include <stdio.h>

    VS2017里面,这句应该是加在头文件“stdafx.h”里面。

    加完之后,再次运行相同的程序,就可以正常运行了,显示结果如下图所示:

    那么解决了不使用安全版本的问题,接下来就来说一下使用安全版本的情况。

    如果我们选择相信编辑器,那么我们就会把strcpy()函数改成使用strcpy_s()函数,改完之后运行首先会遇到以下错误:

    这是因为之前使用strcpy()函数时,我们知道该函数是标准名称空间std的成员,而安全版本strcpy_s并不是该名称空间的成员,所以“std::”应该被去掉,去掉之后再次运行,就会正常运行了。

    但是有时候,编辑器在你去掉“std::”还是会出现错误,错误说明是:1.没有与参数列表匹配的 重载函数"strcpy_s"实例;2."strcpy_s":函数不接受2个参数。

    如下图所示:

    这是因为strcpy_s()函数是有两个版本,用两个参数、三个参数都可以,只要可以保证缓冲区大小。
    三个参数时:

    1 errno_t strcpy_s( 
    2 char *strDestination, 
    3 size_t numberOfElements, 
    4 const char *strSource 
    5 );

    两个参数时:

    1 errno_t strcpy_s( 
    2 char (&strDestination)[size], 
    3 const char *strSource 
    4 ); // C++ only 

    所以,若我们使用new来分配储存空间时,就会出现上面说的不能保证缓冲区大小的问题了。

    看下面的代码:

    1 char * str;
    2 str = new char[4];
    3 strcpy_s(str, "C++");

    语法来说没有什么问题,但是因为str的储存空间是使用new临时分配的,所以并不能保证缓冲区大小,点击运行就会出现上述的两种错误了。

    这种情况的解决方法其实很简单,那就是不符合2个参数的版本就使用3个参数的版本呗。在两个str之间,加上一个参数,标识长度。

    所以完整代码如下:

     1 // strcpy.cpp -- test the strcpy function and strcpy_s function
     2  
     3 #include "stdafx.h"
     4 #include <iostream>
     5 #include <cstring>
     6  
     7  
     8 int main()
     9 {
    10     char str1[20];
    11     char str2[20];
    12     std::cout << "Please enter str2: ";
    13     std::cin.get(str2, 20);
    14     strcpy_s(str1, str2);
    15     std::cout << "str1 is " << """ << str1 << "".
    ";
    16     char * str;
    17     str = new char[20];
    18     strcpy_s(str, strlen(str1)+1, str1);
    19     std::cout << "str is " << """ << str << "".
    ";
    20     system("pause");
    21     return 0;
    22 }

    这里分别使用了2个参数和3个参数的strcpy_s()函数版本。

    后面使用3个参数的版本时,一般的做法就是将长度定为被复制的字符串长度+1,因为strlen()返回字符串长度,但是不包括字符串末尾的空字符,所以+1。

    上述代码运行结果如下图所示:

    以上就是strcpy()函数和strcpy_s()函数的基本使用和注意事项了,希望对大家有所帮助~

  • 相关阅读:
    编程总结2
    编程总结1
    我的三位老师
    《秋季学期学习总结》
    CodeAction_beta02 斐波那契 (多维DP)
    bzoj3029 守卫者的挑战 (多维dp)
    修剪草坪 (单调队列)
    CF734F Anton and School (构造)
    CF359B Permutation (构造)
    CF989C A Mist of Florescence (构造)
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14171979.html
Copyright © 2011-2022 走看看