用 ctre-unicode 匹配一组 unicode 字符
Match a set of unicode characters with ctre-unicode
说,我有一个字符串
char8_t text[] = u8"• test\n - two\n •• three\n-• four\n";
我想用单个 space 替换任意数量的连续空白字符 -
或 •
。我尝试了以下方法:
char8_t* b = text + std::size(text)-1;
for (char8_t* r = text;;) {
auto m = ctre::search<u8R"([\s\-•]+)">(r,b);
if (!m) break;
char8_t* w = m.begin();
r = m.end();
if (r==b) {
b = w;
break;
}
*w++ = ' ';
if (w!=r) {
memmove(w,r,b-r);
b -= r-w;
r = w;
}
}
*b = '[=11=]';
cout << ((char*)text) << endl;
但这会导致
• test two •• three • four
我包括 Hana's GitHub repo 中的 <ctre-unicode.hpp>
。
这是错误还是预期的行为?
起初,我认为问题可能出在将 •
放入 []
中,因为可能 []
只接受单字节字符和转义序列,但我明白了(?:[\s\-]|•)+
的输出与原始 [\s\-•]+
相同。 \P{L}+
结果,我假设是,只删除了一些包含 •
字符的字节:
� test two � � three � four
这是神栓 link。
我对 ctre 库知之甚少,所以我可能在下面使用了一些笨拙的结构,但希望它足够好以达到某个目的。我已经内联评论以解释它在做什么。
#include <ctre-unicode.hpp>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <iterator>
#include <string_view>
template<class T>
T* get_nonconst_ptr(T* b, const T* e) {
// a helper to get a non-const pointer to `e`
return b + std::distance(const_cast<const T*>(b), e);
}
int main() {
char8_t text[] = u8"• test\n - two\n •• three\n-• four\n";
std::u8string_view tv = text; // a view over the part of `text` left to search
while(true) {
auto m = ctre::search<u8R"([\s\-•]+)">(tv);
if(!m) break; // no match, we're done
// where to move to
auto dest = get_nonconst_ptr(text, m.data());
// where to move from
auto src = dest + m.size();
*dest++ = ' '; // replace what was matched with a single space
// get pointer to end
auto end = get_nonconst_ptr(text, tv.end());
std::move(src, end + 1, dest); // do the move, incl. null terminator
// a new view over the rest of `text`:
tv = std::u8string_view(dest, std::distance(src, end));
}
std::cout << reinterpret_cast<unsigned char*>(text) << '\n';
}
输出:
test two three four
我在 github 仓库中打开了一个 issue,作者回复了。
Unicode 操作模式是通过使用 ctre::utf8_iterator
在内部实现的。但在当前的实现中,仅当 search
函数接收 std::u8string_view
作为参数时才会触发 utf8_iterator
的使用。在当前的实现中,一对 char8_t*
不会使 search
使用 utf8_iterator
.
这就是为什么 Unicode example in the readme and Ted Lyngmo's 都在 utf8 模式下工作,但我的原始代码在字节模式下工作。
说,我有一个字符串
char8_t text[] = u8"• test\n - two\n •• three\n-• four\n";
我想用单个 space 替换任意数量的连续空白字符 -
或 •
。我尝试了以下方法:
char8_t* b = text + std::size(text)-1;
for (char8_t* r = text;;) {
auto m = ctre::search<u8R"([\s\-•]+)">(r,b);
if (!m) break;
char8_t* w = m.begin();
r = m.end();
if (r==b) {
b = w;
break;
}
*w++ = ' ';
if (w!=r) {
memmove(w,r,b-r);
b -= r-w;
r = w;
}
}
*b = '[=11=]';
cout << ((char*)text) << endl;
但这会导致
• test two •• three • four
我包括 Hana's GitHub repo 中的 <ctre-unicode.hpp>
。
这是错误还是预期的行为?
起初,我认为问题可能出在将 •
放入 []
中,因为可能 []
只接受单字节字符和转义序列,但我明白了(?:[\s\-]|•)+
的输出与原始 [\s\-•]+
相同。 \P{L}+
结果,我假设是,只删除了一些包含 •
字符的字节:
� test two � � three � four
这是神栓 link。
我对 ctre 库知之甚少,所以我可能在下面使用了一些笨拙的结构,但希望它足够好以达到某个目的。我已经内联评论以解释它在做什么。
#include <ctre-unicode.hpp>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <iterator>
#include <string_view>
template<class T>
T* get_nonconst_ptr(T* b, const T* e) {
// a helper to get a non-const pointer to `e`
return b + std::distance(const_cast<const T*>(b), e);
}
int main() {
char8_t text[] = u8"• test\n - two\n •• three\n-• four\n";
std::u8string_view tv = text; // a view over the part of `text` left to search
while(true) {
auto m = ctre::search<u8R"([\s\-•]+)">(tv);
if(!m) break; // no match, we're done
// where to move to
auto dest = get_nonconst_ptr(text, m.data());
// where to move from
auto src = dest + m.size();
*dest++ = ' '; // replace what was matched with a single space
// get pointer to end
auto end = get_nonconst_ptr(text, tv.end());
std::move(src, end + 1, dest); // do the move, incl. null terminator
// a new view over the rest of `text`:
tv = std::u8string_view(dest, std::distance(src, end));
}
std::cout << reinterpret_cast<unsigned char*>(text) << '\n';
}
输出:
test two three four
我在 github 仓库中打开了一个 issue,作者回复了。
Unicode 操作模式是通过使用 ctre::utf8_iterator
在内部实现的。但在当前的实现中,仅当 search
函数接收 std::u8string_view
作为参数时才会触发 utf8_iterator
的使用。在当前的实现中,一对 char8_t*
不会使 search
使用 utf8_iterator
.
这就是为什么 Unicode example in the readme and Ted Lyngmo's