【问题标题】:utf8 character counting not workingutf8 字符计数不起作用
【发布时间】:2014-04-14 03:33:53
【问题描述】:

谁能解释一下为什么第一个功能有效,而第二个无效?

unsigned int utf8_count(char* in)
{
    unsigned int i = 0, c = 0;
    while (in[i])
    {
        if ((in[i] & 0xc0) != 0x80)
            c++;

        i++;
    }

    return c;
}

unsigned int utf8_count(char* in, unsigned int in_size)
{
    unsigned int i = 0, c = 0;
    while (i < in_size)
    {
        if ((in[i] & 0xc0) != 0x80)
            c++;

        i++;
    }

    return c;
}

我了解(in[i] &amp; 0xc0) != 0x80 的作用,但我不明白为什么i &lt; in_size != in[i]

示例字符串:ゴールデンタイムラバー/スキマスイッチ 57 个字节,19 个字符。

为什么utf8_count(in, 57) 返回 57 而不是 19?

示例字符串的二进制表示:

【问题讨论】:

  • 你在为in_size 传递什么?如果传入strlen(in),这两个函数是等价的。
  • 我以字节为单位传递大小。为什么 strlen 以字符返回大小?
  • 例如:ゴールデンタイムラバー/スキマスイッチ 是 57 个字节或 19 个字符。
  • @Luka - 没有现成的函数可以返回这个计数吗?您使用的是什么编译器和操作系统?
  • strlen 在您的示例字符串中应返回 57(或 59,无论字节长度如何),not 19。这个名称有点用词不当。它不知道 UTF8 或任何其他编码;它只是在遇到零值之前计算非零 char 值(通常 = 字节)的数量。

标签: c++ unicode utf-8


【解决方案1】:

您看到的问题与您的示例字符串有关。

ゴールデンタイムラバー/スキマスイッチ 您的示例字节在空字节之前显示 18x '00111111'。 根据我的计算,第一个函数应该返回 18,第二个应该返回更大的数字。你确定你传入的是正确的字符串吗?

我认为您在图像中向我们显示的字节与文本 ゴールデンタイムラバー/スキマスイッチ 不对应(如果只是因为我没有看到在该字符串的开头多次重复相同的字符。

【讨论】:

    【解决方案2】:

    在这里工作得很好..http://ideone.com/oepQg1

    我使用 g++ 4.8.1 和 MSVC 2013 在 Windows 8 上的两个 CodeBlocks 中对其进行了测试。还在 linux 上进行了尝试。有效。他们都打印 19..

    因此,无论您输入什么,它都与您在 OP 中的字符串不同..

    // UTF8Test.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <cstring>
    #include <clocale>
    
    int strlen_u8(const char* str)
    {
        int I = 0, J = 0;
    
        while (str[I])
        {
            if ((str[I] & 0xC0) != 0x80)
            {
                ++J;
            }
            ++I;
        }
        return J;
    }
    
    int strlen_s_u8(const char* str, unsigned int size)
    {
        unsigned int I = 0, J = 0;
        while (I < size)
        {
            if ((str[I] & 0xC0) != 0x80)
            {
                ++J;
            }
            ++I;
        }
        return J;
    }
    
    
    #if defined _MSC_VER || defined _WIN32 || defined _WIN64
    int _tmain(int argc, _TCHAR* argv[])
    #else
    int main(int argc, char* argv[])
    #endif
    {
        #ifdef _MSC_VER
        const char* str = "ゴールデンタイムラバー/スキマスイッチ";
        #else
        const char* str = u8"ゴールデンタイムラバー/スキマスイッチ";
        std::setlocale(LC_ALL, "ja_JP.UTF-8");
        #endif
    
        std::cout << strlen_u8(str) << "\n";
        std::cout << strlen_s_u8(str, strlen(str)) << "\n"; //can use 57 instead of strlen.
        std::cin.get();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      相关资源
      最近更新 更多