2012-08-10 114 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; 
}