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 << "\".\n"; 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 << "\".\n"; 16     char * str; 17     str = new char[20]; 18     strcpy_s(str, strlen(str1)+1, str1); 19     std::cout << "str is " << "\"" << str << "\".\n"; 20     system("pause"); 21     return 0; 22 }

這里分別使用了2個參數和3個參數的strcpy_s()函數版本。

后面使用3個參數的版本時,一般的做法就是將長度定為被復制的字符串長度+1,因為strlen()返回字符串長度,但是不包括字符串末尾的空字符,所以+1。

上述代碼運行結果如下圖所示:

以上就是strcpy()函數和strcpy_s()函數的基本使用和注意事項了,希望對大家有所幫助~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM