当前位置: 首页 > 知识库问答 >
问题:

字符串中的重音符号,如何在单个字符中存储重音字符

拓拔谭三
2023-03-14

我必须编写一个小程序来删除作为输入的字符串中的重音。我还必须创建一个函数,将每个带重音的字符替换为相应的不带重音的字符,我有一个循环,为main中的每个字符调用该函数:

char func (char c)
{
    string acc = "èé";
    string norm = "ee";
    char ret = c;

    for(int i = 0; i < acc.size(); i++)
    {
        if(c == acc[i])
            ret = acc[i];
    }
    return ret;
}

问题是,如果我在main中提供字符串“é”作为输入,则该字符串被视为大小为2的字符串(参见下面的示例),并且上面的函数被调用两次而不是一次。此外,作为函数输入的char不是正确的。我想我在函数中遇到了相同的大小问题。这个重音不应该被视为单个字符吗?(我使用的是UTF-8)

string s = "e";
cout << "size:" << s.size() << endl;
s = "è";
cout << "size:" << s.size() << endl;

OUTPUT
size:1
size:2

我已经用wchar_t ans wstring类型解决了这个问题,但是我需要在一个更复杂的程序中插入这个函数,可能我希望避免更改所有代码来处理wstring。

我需要更改文件编码吗?实际是:

text/x-c; charset=utf-8

是否可以使用普通字符串和字符编写这样的函数?

共有2个答案

孟子墨
2023-03-14

将字符存储在wchar_t中,如下所示

wchar_t text = L'é';

您还可以在wstring中存储特殊字符:

wstring text = L"étoile";

如果您仍然需要将wchar\u t(或wstring)中的潜在特殊字符与char或(字符串)进行比较,则此线程将很好地解释如何进行比较。

田阳泽
2023-03-14

您不应该尝试使用简单循环自己执行此操作,尤其是在代码对安全敏感的情况下。在Unicode中表示相同字符的方法通常不止一种,因此您可能有一个代码点,也可能有两个代码点。例如:

const wchar_t text1[] = { L'e', 0x0301, 0 };
const wchar_t text2[] = { 0x0e9, 0 };

这两个字符串在打印时看起来是等效的(它们都显示e),但它们显然不同,简单的检查将失败。您应该在搜索之前对字符串进行规范化,或者使用现有的函数自动为您进行规范化。

Windows提供NormalizeStringFindString常规,ICU为此提供unorm_compareusearch_first

const wchar_t text1[] = { L'e', 0x0301, 0 };
const wchar_t text2[] = { 0x0e9, 0 };

// Using Windows APIs, try to normalize the string first
int size = NormalizeString(NormalizationKC, text1, -1, nullptr, 0);
if (size == 0)
  throw std::exception("Can't normalize");

auto text3 = std::make_unique<wchar_t[]>(size);
NormalizeString(NormalizationKC, text1, -1, text3.get(), size);

// Print out the three strings - they all look the same
std::wcout << text1 << std::endl;
std::wcout << text2 << std::endl;
std::wcout << text3.get() << std::endl;

// Verify if they are (or are not) equal
if (CompareStringOrdinal(text1, -1, text2, -1, false) == 2)
  std::wcout << L"Original strings are equivalent\r\n";
else
  std::wcout << L"Original strings are not equivalent\r\n";

if (CompareStringOrdinal(text3.get(), -1, text2, -1, false) == 2)
  std::wcout << L"Normalized strings are equivalent\r\n";
else
  std::wcout << L"Normalized strings are not equivalent\r\n";

// Verify if the string text2 can be found
if (FindStringOrdinal(FIND_FROMSTART, text1, -1, text2, -1, TRUE) != -1)
  std::wcout << L"Original string contains the searched-for string\r\n";
else
  std::wcout << L"Original string does not contain the searched-for string\r\n";

if (FindStringOrdinal(FIND_FROMSTART, text3.get(), -1, text2, -1, TRUE) != -1)
  std::wcout << L"Normalized string contains the searched-for string\r\n";
else
  std::wcout << L"Normalized string does not contain the searched-for string\r\n";

// Using ICU APIs, try to compare the normalized strings in one go
// (You can also manually normalize, like Windows, if you want to keep the
// normalized form around)
UErrorCode error{ U_ZERO_ERROR };
auto result = unorm_compare(reinterpret_cast<const UChar*>(text1), -1, 
  reinterpret_cast<const UChar*>(text2), -1, 0, &error);
if (!U_SUCCESS(error))
  throw std::exception("Can't normalize");

if (result == 0)
  std::wcout << L"[ICU] Normalized strings are equivalent\r\n";
else
  std::wcout << L"[ICU] Normalized strings are NOT equivalent\r\n";

// Try searching; ICU handles the equivalency of (non-)normalized
// characters automatically.
auto search = usearch_open(reinterpret_cast<const UChar*>(text2), -1, 
  reinterpret_cast<const UChar*>(text1), -1, "", nullptr, &error);
if (!U_SUCCESS(error))
  throw std::exception("Can't open search");

auto index = usearch_first(search, &error);
if (!U_SUCCESS(error))
  throw std::exception("Can't search");

if (index != USEARCH_DONE)
  std::wcout << L"[ICU] Original string contains the searched-for string\r\n";
else
  std::wcout << L"[ICU] Original string does not contain the searched-for string\r\n";

usearch_close(search);

这将产生以下输出:

é
é
é
Original strings are not equivalent
Normalized strings are equivalent
Original string does not contain the searched-for string
Normalized string contains the searched-for string
[ICU] Normalized strings are equivalent
[ICU] Original string contains the searched-for string
 类似资料:
  • 问题内容: 如何从字符串中删除重音符号?尤其是在IE6中,我有类似以下内容: 但是IE6困扰着我,似乎不喜欢我的正则表达式。 问题答案: 使用ES2015 / ES6 String.Prototype.Normalize(), 这里发生两件事: 根据Unicode规范形式,将组合的字形分解为简单的字形。在中端起来表示为+ 。 现在,使用正则表达式字符类来匹配U + 0300→U + 036F范围,

  • 问题内容: 我正在尝试从PHP字符串中的字符中删除重音符号,作为使字符串在URL中可用的第一步。 我正在使用以下代码: 我期望的输出将是这样的: 但是,不是将重音字符音译,而是将它们替换为问号: 我在网上可以找到的所有内容都表明,设置语言环境将解决此问题,但是我已经这样做了。我已经检查了以下详细信息: 服务器支持我设置的语言环境(包含在产生的列表中) 服务器的iconv版本(包含在产生的列表中)支

  • 问题内容: 我无法在Redis数据库中设置和检索带有重音符号的字符串。 带重音符号的字符被编码,如何将它们放回原处? 问题答案: Redis服务器本身将所有数据存储为二进制对象,因此它不依赖于编码。服务器将只存储客户端发送的内容(包括UTF-8字符)。 以下是一些实验: c3a9是’é’char的表示。 实际上,数据已正确存储在Redis服务器中。但是,当它在终端中启动时,Redis客户端会解释输

  • 问题内容: (据我所知)Android中是否有任何方法都没有java.text.Normalizer从字符串中删除任何重音符号。例如,“éàù”变成“ eau”。 如果可能,我想避免解析String来检查每个字符! 问题答案: 在Android中可用(无论如何都是最新版本)。您可以使用它。 编辑 供参考,这里是如何使用: (从下面评论中的链接粘贴)

  • 首先,请原谅我英语不好。这不是我的母语(这是我的问题之一,稍后你会看到原因)。 我正在Java中制作一个方法,建议计算字符串的元音。输入来自windows提示符,因为我分别使用javac和java命令编译和执行。 我已经写了一些代码来解决这个问题,但我无法计算带有重音符号的元音。例如。当我尝试“canción”时,它的输出只计算 2 个元音。 我正在使用扫描仪作为输入法。 我尝试比较两个字符串,因

  • 问题内容: 我有一个webapp,它在MySQL数据库中存储法语文本(可能包含重音字符)。通过PHP直接检索数据时,带重音的字符变得乱码。例如: 因此,我使用(或)将字符串转换为html实体,一切都很好。但是,当我输出包含重音字符和HTML元素的数据时,事情变得更加复杂。例如,被转换为浏览器,因此浏览器无法理解。 如何同时正确显示重音字符和正确解析HTML? 谢谢! 问题答案: 也许你可以看看和