2012-05-08 35 views
1

我一直在使用C++字符串,並嘗試使用C函數(如strcpy())將char *字符串加載到std::string中。由於strcpy()需要char *作爲參數,我一定要投它該是這樣的:std :: string.c_str()與std :: string有不同的值嗎?

std::string destination; 
unsigned char *source; 
strcpy((char*)destination.c_str(), (char*)source); 

的代碼工作正常,當我在調試器中運行該程序的*source的值存儲在destination,但一些奇怪的原因,它不會與語句打印出

std::cout << destination;

我注意到,如果我用

std::cout << destination.c_str();

值打印正確,一切正常。爲什麼會發生?有沒有更好的方法將unsigned char*char*複製到std::string(字符串流?)這似乎只有當我在複製操作中將字符串指定爲foo.c_str()時纔會發生。

編輯:要回答「你爲什麼要這樣做?」這個問題,我使用strcpy()作爲一個簡單的例子。還有些時候它比分配更復雜。例如,必須使用strncpy()僅將X數量的字符串A複製到字符串B中,或將std::string傳遞給C庫中的函數,該函數將char *作爲緩衝區的參數。

+11

所以,你忽略了你的編譯器給你的錯誤,並決定關閉它,把它轉換爲'(char *)'?你想知道爲什麼你有問題? –

+2

爲什麼你不使用: destination = source; – Morwenn

+0

所有的答案都會問隱含的問題爲什麼?爲什麼? – rerun

回答

4

這是不是在所有的原因有兩個一個好主意:

  1. destination.c_str()是一個const指針,虛擲它的常量和寫入這是不確定的行爲。
  2. 您沒有設置該字符串的大小,這意味着它甚至不會necessealy具有足夠大的緩衝區來存放這很可能會導致訪問衝突的字符串。

std::string有一個構造函數,允許其從char*來構造簡單的寫:

std::string destination = source

8

這裏有你想要的

std::string destination = source; 

你在做什麼是錯的這麼多層次......你寫在std::string內表現......我的意思是......不冷靜人......它比這更復雜,數組被調整大小,只讀存儲器......作品。

+0

找到一個給你。雖然有點不同,它確實涉及:http://stackoverflow.com/questions/6456359/what-is-stdstringc-str-lifetime – chris

0

首先您應該注意,由c_str返回的值是const char*,不得修改。其實它甚至不必指向string的內部緩衝區。

3

那麼你在做什麼,是不確定的行爲。你的c_str()返回一個const char *,並不意味着被分配給。爲什麼不使用定義的構造函數或賦值運算符。

3

std::stringdefines an implicit conversionconst char*std::string ...所以使用它。

您決定放棄一個錯誤,因爲c_str()返回const char*,即它不允許寫入其基礎緩衝區。你盡一切可能來解決這個問題,但它不起作用(你不應該對此感到驚訝)。

c_str()有充分理由返回const char*。你不知道這個指針指向字符串的底層緩衝區。你不知道這個指針指向的是一個足夠容納你的新字符串的內存塊。圖書館正在使用它的界面告訴你應該如何使用c_str()的返回值,並且你完全忽略了這一點。

1

不要做你在做什麼!

我重複一遍!

不要做你正在做的事!

當你做一些奇怪的事情時,似乎有點工作是字符串類實現的結果。你幾乎可以肯定地寫在你不應該和一堆其他假冒的東西。

當你需要用C函數寫入緩衝區有兩種基本方法交互:

std::string read_from_sock(int sock) { 
    char buffer[1024] = ""; 

    int recv = read(sock, buffer, 1024); 
    if (recv > 0) { 
     return std::string(buffer, buffer + recv); 
    } 
    return std::string(); 
} 

或者你可以嘗試Peek方法:

std::string read_from_sock(int sock) { 

    int recv = read(sock, 0, 0, MSG_PEEK); 
    if (recv > 0) { 
     std::vector<char> buf(recv); 
     recv = read(sock, &buf[0], recv, 0); 
     return std::string(buf.begin(), buf.end()); 
    } 
    return std::string(); 
} 

當然,這些都是不是非常強大的版本......但他們說明了這一點。

0

在回答您的編輯:

具有用strncpy()到串A的僅X量複製到串B

如果串A是一個字符數組,並串B是的std :: string,和strlen的(A)> = X,則可以做到這一點:

B.assign(A, A + X); 

傳遞的std :: string到功能從一個C庫第在需要一個char * 作爲一個參數爲緩衝區

如果參數實際上是const char *,您可以使用c_str()了點。但是,如果只是普通的char *,和你使用的是C++ 11兼容的編譯器,那麼你就可以做到以下幾點:

c_function(&B[0]); 

但是,您需要確保有足夠空間字符串的數據(與使用純C字符串相同),您可以通過調用resize()函數來完成此操作。如果函數寫字符的數目不詳的字符串作爲空終止的C字符串,那麼你可能會想以後截斷字符串,像這樣:

B.resize(B.find('\0')); 

您可以安全地做到這一點的原因一個C++ 11編譯器而不是一個C++ 03編譯器就是在C++ 03中,字符串不被標準保證是連續的,但在C++ 11中是這樣的。如果你想在C++ 03中保證,那麼你可以使用std::vector<char>

+0

關於你的建議,傳遞'c_str()'的返回值到一個函數一個char *'...這是一個壞主意。你不知道const char *指向的是什麼。我沒有看到它指出它指向字符串使用的內部緩衝區的地方,所以它甚至可能不起作用,並且API向你大吼那個內存不應該被修改。除非你知道該函數不會修改指針指向的事實,否則不要這樣做。 –

+0

@EdS。 - 我沒有這樣說過的好事。 –

+0

對不起,誤讀:D –

相關問題