C++中strcpy()和strcpy_s()函數的使用及注意

此文章轉載自:🔗C++中strcpy()函數和strcpy_s()函數的使用及注意事項🔗,作者:Leonardo Liu

參考資料:

在編寫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. #include "stdafx.h"
  3. #include <iostream>
  4. #include <cstring>
  5. int main()
  6. {
  7. char str1[20];
  8. char str2[20];
  9. std::cout << "Please enter str2: ";
  10. std::cin.get(str2, 20);
  11. std::strcpy(str1, str2);
  12. std::cout << "str1 is " << "\" " << str1 << "\".\n";
  13. system("pause");
  14. return 0;
  15. }

正常來說,語法上沒有任何問題,但是運行時,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()函數是有兩個版本,用兩個參數、三個參數都可以,只要可以保證緩衝區大小。

三個參數時:

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來分配儲存空間時,就會出現上面說的不能保證緩衝區大小的問題了

看下面的代碼:
 

  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. #include "stdafx.h"
  3. #include <iostream>
  4. #include <cstring>
  5. int main()
  6. {
  7. char str1[20];
  8. char str2[20];
  9. std::cout << "Please enter str2: ";
  10. std::cin.get(str2, 20);
  11. strcpy_s(str1, str2);
  12. std::cout << "str1 is " << "\"" << str1 << "\".\n";
  13. char * str;
  14. str = new char[20];
  15. strcpy_s(str, strlen(str1)+1, str1);
  16. std::cout << "str is " << "\"" << str << "\".\n";
  17. system("pause");
  18. return 0;
  19. }

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

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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章