2016-01-28 19 views
4

我在C應用程序中使用ISO 8859-1(拉丁擴展ASCII字符集)。當我將strcpy/strcat的部分串在一起時,它工作正常。但是當我使用sprintf("%s %s")時,在某些運行時(特別是某些版本的Android)上,當擴展的ASCII字符(特別是é,雖然我沒有嘗試其他字符)被擊中時,字符串將會截斷。sprintf()在某些運行時處理%s擴展ASCII(ISO 8859-1)?

我以爲%s只是應該複製字節,直到被擊中。我懷疑strcpy/strcat的作品,因爲它沒有任何格式化。這裏可能會發生什麼?

我應該注意到,我沒有使用printf()查看文本,而是我自己的文本渲染引擎,它可以很好地處理ISO-8859-1。

更新: 爲了說明問題,我有一個NDK應用程序,它將字符串保存爲C,並將其傳遞給基於OpenGL的文本呈現引擎。如果我將整個字符串作爲char *文字傳遞,它會顯示正常。如果我將sprintf()部分拼接在一起,它會在é字符處截斷。 例如:

char buffer[1024]; 
strcpy(buffer, "This is "); 
strcat(buffer, "the string I want to diésplay."); 

顯示正常。但這:

This is the string I want to di 
+0

你確定這是sprintf()的錯嗎? strlen()說什麼? –

+0

我不知道,因爲我沒有特定的Android設備(衆所周知的三星模型)的用戶遇到此錯誤。在我自己的測試設備上,它工作正常,並且它在iOS和Win32上也能正常工作。所以我想知道如果sprintf()在一些Android運行時將char *視爲UTF-8或其他東西。 – user1054922

+0

讓我澄清一下:你有NDK應用程序,它將字符串傳遞給Java應用程序? –

回答

1

s[n]printf()的行爲規定不同於字符串處理函數如strcpy()strcat()行爲:如

sprintf(buffer, "%s%s", "This is ", "the string I want to diésplay."); 

打印。當提供相同的格式和打印項目時,系列功能都需要產生相同的字節序列。唯一的區別在於發送這些字節的位置。因此,如果您的C庫的構建方式是在通過printf()打印到標準流時對字符串數據執行轉換(可能是轉碼),那麼當通過sprintf()打印到字符串時,它將執行相同的轉換。

「printf」中的「f」用於「格式化」。該標準既沒有說也沒有暗示格式化字符串必須意味着將其字節逐字輸出到輸出,所以像上面我假設的代碼轉換或其他轉換不是不可能的。實際上,the docs for some versions of these functions表示語言環境依賴性(「請注意,所產生的字符串的長度與語言環境有關並且難以預測」),所以特別是代碼轉換是一種真正的可能性。

您所描述的第三方觀察結果的任何具體解釋都必定是推測性的,因爲您沒有提供足夠的代碼或數據來做出自信的診斷。我傾向於懷疑在使用與程序內部使用的字符編碼不同的語言環境中運行程序的問題。如果是這樣,那麼你可以通過改變你運行的語言環境來在本地重現問題,並且你可以通過確保你的程序總是以合適的語言環境運行的方式來解決它。除此之外,您可以使用getlocale()setlocale()函數來幫助您,特別是如果您想限制執行區域設置控制的範圍。

因爲最終你只依賴於printf-family函數而僅僅用於字符串操作,不過,我認爲最好使用問題中提出的解決方法:儘可能使用C的專用字符串操作函數,比如如strcpy()strncat(),執行您的字符串構建。既然你不是依靠你的實際輸出的stdio函數,這應該沒問題。

+0

夢幻般的答案!正是我在找什麼。我會嘗試搞亂地區,看看我是否可以複製它。 – user1054922