Chinaunix首页 | 论坛 | 博客
  • 博客访问: 426996
  • 博文数量: 53
  • 博客积分: 6243
  • 博客等级: 大校
  • 技术积分: 567
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-08 18:00
文章分类

全部博文(53)

文章存档

2013年(1)

2011年(20)

2010年(28)

2007年(3)

2006年(1)

分类: C/C++

2006-11-15 13:20:54

 
  从 Linux 向 win32 移植程序需要用 wcout 处理宽字符输出。我下载了 STLport 但是用 STLport 中的 wcout 输出中文时乱码。经过 gdb 跟踪我发现 wcout 输出 wchar_t 字符串时,先调用 codecvt  把 wchar_t 字符串转换成 char 字符串,然后输出 char 字符串。但是在我的 mingw 环境中 codecvt 转换中文时出错了,问题锁定在 STLport 中的_fstream.c  文件中的

CODE:
template   __BF_int_type__  basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
和 codecvt.cpp 的

CODE:
codecvt::result
codecvt::do_out(state_type&         /* state */,
                                          const intern_type*  from,
                                          const intern_type*  from_end,
                                          const intern_type*& from_next,
                                          extern_type*        to,
                                          extern_type*        to_limit,
                                          extern_type*&       to_next) const
函数中。

现在我把 codecvt::do_out 改为

CODE:
codecvt::result
codecvt::do_out(state_type&         /* state */,
                                          const intern_type*  from,
                                          const intern_type*  from_end,
                                          const intern_type*& from_next,
                                          extern_type*        to,
                                          extern_type*        to_limit,
                                          extern_type*&       to_next) const {

  ptrdiff_t len = (min) (from_end - from, to_limit - to);

  int len_str;
  wchar_t *pwch = (wchar_t*)(from+len);
  *pwch = L'\0';
  //pwch = (wchar_t*)from;
  pwch = (wchar_t*)from;
  
  len_str = wcstombs(NULL, pwch, 0);

  //printf("len_str = %d\n", len_str);
  //len = len_str;
  wcstombs(to, from, len_str);
  *(to+len_str)='\0';
  
  from_next = from + len;
  to_next   = to   + len_str;
  
  return ok;
}
把  _fstream.c  文件中的

CODE:
template   __BF_int_type__  basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
改为

CODE:
template
__BF_int_type__
basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
  // Switch to output mode, if necessary.
  if (!_M_in_output_mode)
    if (!_M_switch_to_output_mode())
      return traits_type::eof();

  _CharT* __ibegin = this->_M_int_buf;
  _CharT* __iend   = this->pptr();
  this->setp(_M_int_buf, _M_int_buf_EOS - 1);

  // Put __c at the end of the internal buffer.
  if (!traits_type::eq_int_type(__c, traits_type::eof()))
    *__iend++ = _Traits::to_char_type(__c);

  // For variable-width encodings, output may take more than one pass.
  while (__ibegin != __iend) {
    const _CharT* __inext = __ibegin;
    char* __enext         = _M_ext_buf;
    typename _Codecvt::result __status
      = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
                        _M_ext_buf, _M_ext_buf_EOS, __enext);
    if (__status == _Codecvt::noconv) {
      return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
        ? traits_type::not_eof(__c)
        : _M_output_error();
    }

    // For a constant-width encoding we know that the external buffer
    // is large enough, so failure to consume the entire internal buffer
    // or to produce the correct number of external characters, is an error.
    // For a variable-width encoding, however, we require only that we
    // consume at least one internal character
   
    else if (__status != _Codecvt::error &&
             (((__inext == __iend /*__iend = (_CharT*)__inext*/) &&
               (/*__enext - _M_ext_buf == _M_width * (__iend - __ibegin)*/ true)) ||
              (!_M_constant_width && __inext != __ibegin)))
   
    {
        // We successfully converted part or all of the internal buffer.
      ptrdiff_t __n = __enext - _M_ext_buf;

      
      if (_M_write(_M_ext_buf, __n))
        __ibegin += __inext - __ibegin;
      else
        return _M_output_error();
    }
    else
      return _M_output_error();
  }

  return traits_type::not_eof(__c);
}
我的 mingw 环境中的 STLport 中的 wcout 就能输出中文了,谁有同类的环境可以试试这个方法。如有问题请帮我指出或修改。

更正:不用修改
STLport 源码,  wcout 可以正常输出中文以前我漏掉了 
std::wcout.imbue(loc), 在 Linux 中不用
std::wcout.imbue(loc), std::wcout 也能输出中文。但在 mingw / STLport 环境下必须加上 std::wcout.imbue(loc)。


#include <locale>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

char ch_str[100];
wchar_t wch_str[100];
const char *from = ch_str;
const char *from_next = 0;
wchar_t *to = wch_str;
wchar_t *to_next = 0;
mbstate_t cs;

int main( )
{
    std::locale loc("");
    
    std::locale::global(loc);

    snprintf(ch_str, 99, "%s", "测试abc");

    std::use_facet< std::codecvt<wchar_t, char,

                        mbstate_t> >(loc).in(cs,

                       from,

                       from+strlen(from),

                       from_next,

                       to,

                       to+99,

                       to_next);
 
    std::wcout.imbue(loc);
                      
    std::wcout << wch_str << std::endl;

    return 0;
}


阅读(5484) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~