2012-08-10 144 views
0

我正在製作支持多種語言的C程序。該程序使用WCHAR類型而不是字符發送電子郵件。問題是,當我收到的電子郵件和讀它,一些字符無法正確顯示,還有一些英文的像E,M,...這是一個例子:Unicode字符顯示不正確

<!-- language: lang-c --> 
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, payload_source); 
curl_easy_setopt(hnd, CURLOPT_READDATA, &upload_ctx); 

static const WCHAR *payload_text[]={ 
    L"To: <[email protected]>\n", 
    L"From: <[email protected]>(Example User)\n", 
    L"Subject: Hello!\n", 
    L"\n", 
    L"Message sent\n", 
    NULL 
}; 

struct upload_status { 
    int lines_read; 
}; 

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp){ 
    struct upload_status *upload_ctx = (struct upload_status *)userp; 
    const WCHAR *data; 

    if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { 
     return 0; 
    } 

    data = payload_text[upload_ctx->lines_read]; 
    if (data) { 
     size_t len = wcslen(data); 
     memcpy(ptr, data, len); 
     upload_ctx->lines_read ++; 
     return len; 
    } 
    return 0; 
} 
+0

你用什麼樣的環境和編譯器? – AlexLordThorsen 2012-08-10 18:14:02

+0

另外,e和m是什麼樣子?他們有沒有重點超過正常字符? – AlexLordThorsen 2012-08-10 18:15:00

回答

0

memcpy()運行在字節,而不是在字符上。您沒有考慮到sizeof(wchar_t) > 1。它在某些系統上是2個字節,在其他系統上是4個字節。編寫便攜式代碼時,這種可能性使wchar_t成爲不好的選擇。您應該使用Unicode庫,而不是像icu或iconv)。

致電memcpy()時,您需要考慮sizeof(wchar_t)。您還需要考慮到目標緩衝區可能小於您嘗試複製的文本字節的大小。跟蹤lines_read本身是不夠的,您還必須跟蹤複製的當前行的字節數,以便在當前文本行跨越多個目標緩衝區時處理這些情況。

嘗試一些更喜歡這個:

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) 
{ 
    struct upload_status *upload_ctx = (struct upload_status *) userp; 
    unsigned char *buf = (unsignd char *) ptr; 
    size_t available = (size * nmemb); 
    size_t total = 0; 

    while (available > 0) 
    { 
     wchar_t *data = payload_text[upload_ctx->lines_read]; 
     if (!data) break; 

     unsigned char *rawdata = (unsigned char *) data; 

     size_t remaining = (wcslen(data) * sizeof(wchar_t)) - upload_ctx->line_bytes_read; 
     while ((remaining > 0) && (available > 0)) 
     { 
      size_t bytes_to_copy = min(remaining, available); 
      memcpy(buf, rawdata, bytes_to_copy); 

      buf += bytes_to_copy; 
      available -= bytes_to_copy; 
      total = bytes_to_copy; 

      rawdata += bytes_to_copy; 
      remaining -= bytes_to_copy; 

      upload_ctx->line_bytes_read += bytes_to_copy; 
     } 

     if (remaining < 1) 
     { 
      upload_ctx->lines_read ++; 
      upload_ctx->line_bytes_read = 0; 
     } 
    } 

    return total; 
}