有没有办法在 C++ 中检测汉字? (使用升压)
is there a way to detect chinese characters in c++ ? (using boost)
在一个数据处理项目中,我需要检测中文中的拆分词(中文中的单词不包含空格)。
有没有一种方法可以使用本机 C++ 功能或 boost.locale 库来检测汉字?
一般来说,如果您想在 C++ 中完全支持 Unicode,几乎没有办法 ICU。 Boost 提供了对其功能的一些访问(通过 Boost.Locale 和 Boost.Regex),但它需要 Boost 编译时带有 ICU 支持。因此,与其确保目标平台的 Boost 是这样编译的,不如直接使用 ICU API。
如果您正在寻找单词边界,icu::BreakIterator (more specifically, icu::BreakIterator::createWordInstance) is the starting point. You then pass the text to be iterated over via setText and move the iterator via next 等人。 (是的,ICU 这种方式有点不合时宜,因为它起源于 Java 土地)。
或者,如果您不想使用完整的 C++ API,则有 ublock_getCode which will tell you the UBlockCode 个相关代码点。
这是我仅使用 boost 和标准库的尝试:
#include <iostream>
#include <boost/regex/pending/unicode_iterator.hpp>
#include <functional>
#include <algorithm>
using Iter = boost::u8_to_u32_iterator<std::string::const_iterator>;
template <::boost::uint32_t a, ::boost::uint32_t b>
class UnicodeRange
{
static_assert(a <= b, "Proper range");
public:
constexpr bool operator()(::boost::uint32_t x) const noexcept
{
return x >= a && x <= b;
}
};
using UnifiedIdeographs = UnicodeRange<0x4E00, 0x9FFF>;
using UnifiedIdeographsA = UnicodeRange<0x3400, 0x4DBF>;
using UnifiedIdeographsB = UnicodeRange<0x20000, 0x2A6DF>;
using UnifiedIdeographsC = UnicodeRange<0x2A700, 0x2B73F>;
using UnifiedIdeographsD = UnicodeRange<0x2B740, 0x2B81F>;
using UnifiedIdeographsE = UnicodeRange<0x2B820, 0x2CEAF>;
using CompatibilityIdeographs = UnicodeRange<0xF900, 0xFAFF>;
using CompatibilityIdeographsSupplement = UnicodeRange<0x2F800, 0x2FA1F>;
constexpr bool isChineese(::boost::uint32_t x) noexcept
{
return UnifiedIdeographs{}(x)
|| UnifiedIdeographsA{}(x) || UnifiedIdeographsB{}(x) || UnifiedIdeographsC{}(x)
|| UnifiedIdeographsD{}(x) || UnifiedIdeographsE{}(x)
|| CompatibilityIdeographs{}(x) || CompatibilityIdeographsSupplement{}(x);
}
int main()
{
std::string s;
while (std::getline(std::cin, s))
{
auto start = std::find_if(Iter{s.cbegin()}, Iter{s.cend()}, isChineese);
auto stop = std::find_if_not(start, Iter{s.cend()}, isChineese);
std::cout << std::string{start.base(), stop.base()} << '\n';
}
return 0;
}
https://wandbox.org/permlink/FtxKa8D2LtR3ko9t
也许您应该能够将这种方法完善为功能齐全的东西。
我不知道如何通过测试正确地覆盖它,也不确定应该在这个检查中包含哪些字符。
在一个数据处理项目中,我需要检测中文中的拆分词(中文中的单词不包含空格)。 有没有一种方法可以使用本机 C++ 功能或 boost.locale 库来检测汉字?
一般来说,如果您想在 C++ 中完全支持 Unicode,几乎没有办法 ICU。 Boost 提供了对其功能的一些访问(通过 Boost.Locale 和 Boost.Regex),但它需要 Boost 编译时带有 ICU 支持。因此,与其确保目标平台的 Boost 是这样编译的,不如直接使用 ICU API。
如果您正在寻找单词边界,icu::BreakIterator (more specifically, icu::BreakIterator::createWordInstance) is the starting point. You then pass the text to be iterated over via setText and move the iterator via next 等人。 (是的,ICU 这种方式有点不合时宜,因为它起源于 Java 土地)。
或者,如果您不想使用完整的 C++ API,则有 ublock_getCode which will tell you the UBlockCode 个相关代码点。
这是我仅使用 boost 和标准库的尝试:
#include <iostream>
#include <boost/regex/pending/unicode_iterator.hpp>
#include <functional>
#include <algorithm>
using Iter = boost::u8_to_u32_iterator<std::string::const_iterator>;
template <::boost::uint32_t a, ::boost::uint32_t b>
class UnicodeRange
{
static_assert(a <= b, "Proper range");
public:
constexpr bool operator()(::boost::uint32_t x) const noexcept
{
return x >= a && x <= b;
}
};
using UnifiedIdeographs = UnicodeRange<0x4E00, 0x9FFF>;
using UnifiedIdeographsA = UnicodeRange<0x3400, 0x4DBF>;
using UnifiedIdeographsB = UnicodeRange<0x20000, 0x2A6DF>;
using UnifiedIdeographsC = UnicodeRange<0x2A700, 0x2B73F>;
using UnifiedIdeographsD = UnicodeRange<0x2B740, 0x2B81F>;
using UnifiedIdeographsE = UnicodeRange<0x2B820, 0x2CEAF>;
using CompatibilityIdeographs = UnicodeRange<0xF900, 0xFAFF>;
using CompatibilityIdeographsSupplement = UnicodeRange<0x2F800, 0x2FA1F>;
constexpr bool isChineese(::boost::uint32_t x) noexcept
{
return UnifiedIdeographs{}(x)
|| UnifiedIdeographsA{}(x) || UnifiedIdeographsB{}(x) || UnifiedIdeographsC{}(x)
|| UnifiedIdeographsD{}(x) || UnifiedIdeographsE{}(x)
|| CompatibilityIdeographs{}(x) || CompatibilityIdeographsSupplement{}(x);
}
int main()
{
std::string s;
while (std::getline(std::cin, s))
{
auto start = std::find_if(Iter{s.cbegin()}, Iter{s.cend()}, isChineese);
auto stop = std::find_if_not(start, Iter{s.cend()}, isChineese);
std::cout << std::string{start.base(), stop.base()} << '\n';
}
return 0;
}
https://wandbox.org/permlink/FtxKa8D2LtR3ko9t
也许您应该能够将这种方法完善为功能齐全的东西。 我不知道如何通过测试正确地覆盖它,也不确定应该在这个检查中包含哪些字符。