2012-12-25 216 views
0
#include <iostream> 
using namespace std 
#include <string.h> 
int main(){ 
    char token[] = "some random string"; 
    char c[23]; 
    strcpy(c, token); 
    strncpy(c, token, 5); 
    c[strlen(c)] = '\0'; 
    cout<<c; 
    return 0 ; 
} 

我的輸出是:some random string。但我期望它是:some。任何人都可以解釋爲什麼它的行爲如此嗎?strncpy未按預期工作

+2

我推薦使用'std :: string'。 – Rapptz

回答

3

我認爲你的輸出應該是「一些隨機字符串」,因爲你的兩行代碼什麼都不做,請看評論。

int main(){ 
    char token[] = "some random string"; 
    char c[23]; 
    strcpy(c, token); 
    strncpy(c, token, 5); // Does nothing 
    c[strlen(c)] = '\0'; // Does nothing 
    cout<<c; 
    return 0 ; 
} 

如果要輸出 「一些」,你可以這樣做:

strncpy(c, token, 5); 
c[5] = '\0'; 

函數strncpy()不會自動添加尾隨 '\ 0' 到dest字符串。如果源字符串長度大於len(strncpy的第三個參數),那麼len字符被複制到dest而不結尾'\ 0'。所以你必須通過代碼明確地給出一個結尾的'\ 0'。

+0

在執行了strncpy(c,token,5)之後,c的值應該是一些。如果我錯了,請糾正。 – Kenta

+1

strncpy()不會自動向目標字符串添加尾部'\ 0'。如果源字符串長度大於len(strncpy的第三個參數),那麼最多可以將len個字符複製到dest而不帶尾部'\ 0'。所以你必須通過代碼明確地給出尾部'\ 0'。 – TieDad

+0

如果我必須明確地給出'\ 0'。然後我可以通過在不調用strncpy(..)的情況下使c [4] ='\ 0'來獲得輸出。那麼strncpy(...)的重要性如何? – Kenta

1

您需要在單詞「some」之後終止null,而不是在整個字符串之後終止。 strncpy()函數將複製「一些」到C,但它不一定空終止您的字符串(參見手冊頁strncpy

c[4] = '\0' 
6

它的工作就好了,記住,strncpy does not necessarily null-terminate the string。當你這樣做:

strncpy(c, token, 5); 

它複製前5個字節的tokenc但不空終止結果。此外,這條線是沒用的:

c[strlen(c)] = '\0'; 

strlen(c)查找現有的空終止,並儘快找到一個,你和其他的空終結,這是毫無意義的覆蓋。

在新的代碼,strncpy應該很少,如果有的話使用。它的預期用途(固定長度的緩衝區不一定以空值終止)早已被忽視。更喜歡strlcpy這樣的功能(注意:strlcpy不是標準的;它只適用於類似BSD的系統)。或者,如果您使用C++而不是純C編碼,只需使用std::string並避免這樣的棘手問題。

+0

如果我必須明確地給''0'。然後我可以通過在不調用strncpy(..)的情況下使c [4] ='\ 0'來獲得輸出。那麼strncpy(...)的重要性如何? – Kenta

+0

strncpy的重要性在於避免緩衝區溢出。想想如果目標緩衝區小於源字符串會發生什麼情況。 – drescherjm

+1

雖然我第二個建議。如果這是C++,我會避免使用任何這些,而是​​使用std :: string。 – drescherjm

0

正如其他人已經提到,不像snprintfsprintf,strncpy並不是一個更安全的版本strcpy。它僅僅確保「正好N個字符被複制到目的地(如果源字符串比N短,則使用NUL)」。 (手冊頁)

但是我想你已經注意到,由線

c[strlen(c)] = '\0'; 

這意味着,以確保c null終止。但它實際上毫無意義,因爲strlen使用NUL來確定c的長度。所以這條線幾乎不含「找到NUL並將NUL寫入該位置」。

strncpy的重要性在於複製字符串的certian部分。它不是strcpy的修復,並且在引入snprintf功能之前就存在。