2009-09-02 20 views
-1

我有以下字符串:的std :: string的字符引用

index          0 1 2 3 4 5 6 7 
std::string myString with the content of "\xff\xff\xff\x00\xff\x0d\x0a\xf5" 

當我指的myString的[3],我得到預期的 '\ x00的' 價值。

但是當我指的是myString [5]時,我得到兩個值「\ x0d \ x0a」而不是'\ x0d'。

更有趣的是myString [6]值,它是'\ xf5'。這一次就好像\ x0d不存在,並且引用了正確的位置。

我的問題是:std:string對象中的\ x0d字符有什麼特別之處?索引時如何跳過它?這就像這樣計算:

index      0 1 2 3 4 5 5 6 
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5" 

爲註釋,以「\ X0D」字符是第13個ASCII字符「回車」和「\ X0A」是換行符。

更新:它可以是std ::字符串認爲「\ x0d \ x0a」作爲單個字符,因此只佔用字符串中的一個位置?這個'\ x0d'是關於std :: string的「神祕」字符嗎?

附加信息:http://en.wikipedia.org/wiki/Newline

+5

您可以顯示這一個小的,完整的,可編譯程序見http://www.cplusplus.com/reference/string/string/string/?我不明白在訪問索引5時如何得到兩個字符。畢竟,'[]'運算符只返回一個'char'。 – sbi 2009-09-02 08:11:56

+0

是\ x0a換行符?這些可能被視爲一個單一的字符,以使「換行符」在具有不同換行符樣式的系統上保持相同數量的索引(一個),儘管我真的不確定std :: string的內部工作方式,所以我不會將其作爲答案發布。 – 2009-09-02 08:12:44

+0

我會繼續向這個問題添加更多信息。事實上,你的預感可能是對的:'\ x0a'是一個換行符,似乎std :: string將它們當作一個字符:'\ x0d \ x0a'。 – citn 2009-09-02 08:24:29

回答

9

你確定這是與std::string發生了什麼? std::string::operator[]返回一個const char &,那麼如何返回兩個字符('\x0d''\x0a')?

這就是說,"\x0d\x0a"通常用於Windows下的行尾,而只有'\x0a'在Linux下使用,所以在Windows前者向後者的轉換是比較常見的 - 例如,我在考慮行爲當與"wt"聯繫時,電話號碼爲fopen。我猜想類似的事正在發生在你身上。

編輯:根據您對原始問題的評論,我想我可以猜出發生了什麼。

我相信你的字符串並不包含你認爲它包含的內容。你被誤導了,因爲你用來將字符串輸出到一個文件(可能是ofstream?)的機制正在執行行尾轉換。這意味着'\n'(Unix行尾代碼)被轉換爲'\r\n'(Windows行尾代碼)。行尾翻譯的目的是使代碼在操作系統之間更加便攜。您可以通過打開二進制模式的文件來禁止它;對於ofstream,這是通過在打開文件時指定ios_base::binary標誌完成的,但是此標誌在默認情況下未設置。

(用於在不同的操作系統結束行標誌的更多信息請參閱本Wikipedia article)。

這是什麼,我相信是怎麼回事。您的字符串實際上包含

index     0 1 2 3 4 5 6 
myString contents "\xff\xff\xff\x00\xff\x0a\xf5" 

你輸出它是這樣的:

ofstream file("myfile.txt"); 
for(size_t i=0; i<myString.size(); i++) 
    ofstream << myString[i]; 

因爲最終的線平移以上expalined,在myString[5]'\x0a'被輸出爲'\x0d\x0a',並這就是讓你困惑的原因。

+0

確實我使用了類似的機制:std :: ostringstream。此外,如果您可以添加有關此翻譯的更多信息以供將來參考,我將不勝感激。例如,實際上是誰做的,也可能是網絡上的一些鏈接。 – citn 2009-09-02 13:09:11

+0

我已經添加了一個鏈接到一個全面的維基百科文章。至於實際完成行尾轉換的地方,這可能取決於標準庫實現 - 但它可能發生在'ofstream' /'ostringstream'等或其基類之一中。 – 2009-09-02 13:29:46

0

您可能錯用了[]運算符。

[]運算符返回一個常量字符。但是,您可能將其用作指針,從而得到兩個字符 - 我們需要查看您的實際代碼以確認這一點。

0x00是一個C字符串的空終止符,所以這可能是爲什麼你只能得到一個(正確)的字符。

當你得到[4]會發生什麼?

0

在visual studio 2008中,\ x00被認爲是字符串的結尾。所以myString.lenght返回3.當你嘗試訪問myString [5]時,你會得到一個錯誤。

9

這回事錯在這裏有一件事是以下行不會做你所期望的:

std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5"; 

這將調用std::string(const char *)構造函數,它被設計爲一個C風格的空值終止字符串轉換爲C++ std::string。該構造函數從指定指針開始讀取字節,並將它們複製到新的std::string,直到達到空字節(\ x00)。這與C函數的行爲一致,如strlen()

因此,當你的myString被構造時,它由一個長度爲3的字符串組成,字節爲\ xff,\ xff,\ xff。對大於2的索引的訪問是訪問數組末尾的字節(最多會產生運行時錯誤,或者最壞時會產生未定義的行爲)。

。請注意,std::string可容納中間空字節,但你不能使用上面的構造,因爲空字節被解釋爲終止傳遞給構造函數的C風格的字符串初始化這樣的字符串。

這將是值得更改爲其他的\ x00的字節再次嘗試你的代碼,只是爲了看看它是如何不同於你已經描述:

std::string myString = "\xff\xff\xff\x01\xff\x0d\x0a\xf5" 

此外,上述構造後檢查myString.length()看看你得到了什麼。

+0

O.K.意思是,std :: string :: string(const char *)ctor,遍歷C字符串直到'\ 0'。有道理爲什麼我看到MSVC上的行爲。我的壞... – Abhay 2009-09-02 09:20:11

+0

好點 - 我認爲cmdev只是想向我們展示字符串的內容,並沒有給我們實際用於初始化字符串的代碼......但如果這是實際的初始化,你已經解決了這個問題。 – 2009-09-02 09:35:20

+0

這是正確的。我想表現的只是字符串的內容。確切的任務比這個簡單的任務複雜得多。我會添加一條評論。 – citn 2009-09-02 10:09:53

2

您創建的字符串與下面的構造函數:string(char const *)

它接收NUL終止的C字符串。所以它根據第一個0字符找到它的長度。通過調用string(char const *,size_t n)

你應該使用其他構造,指定大小

std::string myString("\xff\xff\xff\x00\xff\x0d\x0a\xf5",8); 

進一步閱讀

相關問題