Unicode字符的Codepoint?

时间:2015-10-05 02:08:30

标签: c++ unicode

此问题之前已被问过,但它的解决方案取决于我不想依赖的Microsoft基础类。基本上我要做的是将Unicode字符转换为它的等效代码点。

以下是使用MFC的解决方案。有没有办法不使用afxwin.h?

#include <afxwin.h>

#include <iostream>

int main() {
    using namespace std;

    TCHAR   myString[50] = _T("عربى");
    int stringLength = _tcslen(myString); // <----- edit here

    for(int i=0;i<stringLength;i++)
    {
       unsigned int number =myString[i];
       cout<<number<<endl;
    }
}
Output:

1593
1585
1576
1609

2 个答案:

答案 0 :(得分:3)

更新

如果您的编译器支持它,最简单的方法是将常量字符串写为U"عربى"。这会为您提供一组char32_t个字符,其代码点只是用static_cast<uint32_t>()转换的值。要以标准格式打印它们,只需添加U+并打印十六进制值。

在C ++ 14编译器上试试这个(我建议将源文件保存为utf-8)。

#include <cstdlib>
#include <iomanip>
#include <iostream>

using std::cout;

int main()
{
  constexpr char32_t codepoints[] = U"عربى";
  constexpr size_t n = sizeof(codepoints)/sizeof(char32_t);

  cout.setf( cout.hex, cout.basefield );     // Output in hex
  cout.setf( cout.right, cout.adjustfield ); // Prepending
  cout.fill('0');                            // leading zeroes
  // Fixed: Don’t print the terminating U'\0'.
  for ( size_t i = 0; i < n && codepoints[i]; ++i )
    cout << "U+" << std::setw(4) << (unsigned long)codepoints[i] << std::endl;

  return EXIT_SUCCESS;
}

转化

C ++ STL现在有<codecvt>,可以从utf-8或utf-16转换为ucs-32。示例代码(来自http://en.cppreference.com/w/cpp/locale/codecvt_utf16):

#include <fstream>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>

void prepare_file()
{
  // UTF-16le data (if host system is little-endian)
  char16_t utf16le[4] ={0x007a, // latin small letter 'z' U+007a
                        0x6c34, // CJK ideograph "water"  U+6c34
                        0xd834, 0xdd0b}; // musical sign segno U+1d10b
  // store in a file
  std::ofstream fout("text.txt");
  fout.write( reinterpret_cast<char*>(utf16le), sizeof utf16le);
}

int main() 
{
  prepare_file(); // open as a byte stream
  std::wifstream fin("text.txt", std::ios::binary); 
  // apply facet
  fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));

  for (wchar_t c; fin.get(c); )
    std::cout << std::showbase << std::hex << c << '\n';
}

C11和C ++ 11还具有在多字节utf-8和utf-16以及宽字符串之间进行转换的功能(来自这里:http://en.cppreference.com/w/c/string/multibyte/mbrtoc32)。 mbstowcs()功能也可能是相关的。

#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <uchar.h>
#include <assert.h>   

mbstate_t state;

int main(void)
{
  setlocale(LC_ALL, "en_US.utf8");
  char *str = u8"z\u00df\u6c34\U0001F34C"; // or u8"zß水"   
  printf("Processing %zu bytes: [ ", strlen(str));
  for(char* p = str; *p; ++p)
    printf("%#x ", (unsigned char)*p); puts("]");

  char32_t c32;
  char *ptr = str, *end = str + strlen(str);
  int rc;

  while(rc = mbrtoc32(&c32, ptr, end - ptr, &state)) {
    printf("Next UTF-32 char: %#x obtained from ", c32);
    assert(rc != -3); // no surrogate pairs in UTF-32
    if(rc > 0) {
      printf("%d bytes [ ", rc);
      for(int n = 0; n < rc; ++n)
        printf("%#x ", (unsigned char)ptr[n]); puts("]");
      ptr += rc;
    }
  }
}

虽然这些示例使用十六进制代码,但C11和C ++ 11支持Unicode字符串(http://en.cppreference.com/w/cpp/language/string_literal)。由于上面示例中的Unicode是utf-16le,因此将其作为常量写入的标准方法是u"عربى"。您也可以使用U"عربى"将其编码为ucs-32,而不必进行任何代理对转换。

答案 1 :(得分:0)

简单,阅读unicode规范并注意unicode标量,代理和补充字符,自己扩展字形集群。

或者您可以使用今天大多数操作系统中包含的IBM ICU库。

如果问题只是MFC头文件,您可以定义UNICODE,_UNICODE并包含tchar.h。