2

我正在使用 c++ 和 XE8。给定以下代码:

String __fastcall RemoveCharsFromString(String &str, const String &c)
{
    for(unsigned int i=0; i<c.Length(); ++i)
    {
        str.Delete(std::remove(str[0], str.LastChar(), c[i]), str.LastChar());
    }
}

收到的错误:

  • 使用str.Delete(remove(str[0], str.LastChar(), c[i]), str.LastChar());结果

    无法将“int”转换为“const char *”

    for循环内的错误。

  • 使用str.Delete(std::remove(str[0], str.LastChar(), c[i]), str.LastChar());结果

    找不到“删除(wchar_t,wchar_t*,wchar_t)”的匹配项

    for循环内的错误。

搜索 SO 和网络,据我了解,当使用双引号编写代码时,通常会收到此错误。我不相信这种情况适用于这种情况。

返回类型String是 Embarcadero 的UnicodeString. 可在此处找到详细信息:RAD Studio VCL 参考 - UnicodeString 类

4

1 回答 1

3

在 C++Builder 中,String指的是XE8System::String中的别名。System::UnicodeString

您的代码中有很多错误。

System::String::Delete()方法需要一个索引和一个计数作为输入,但这不是您要传递给它的内容。您期望Delete()像 STLstd::wstring::erase()方法一样工作,但事实并非如此。

您没有考虑到System::String::operator[]基于 1 的情况。它不是基于 0 的,就像您的代码所假设的那样。

System::String::LastChar()方法返回指向字符串中最后一个 UTF-16 编码的 Unicode 字符的指针。它不会像您的代码所假设的那样返回指向字符串的空终止符的指针。

您正在调用将 s 范围作为输入的 STLstd::remove()算法,将iterator指定值的所有副本移动到范围的末尾,然后返回一个新iterator的到“已删除”值已移动到范围内的位置(所以它们可以erase()从拥有 s 的容器中获取iterator)。你不能混合你试图做的方式System::String::Delete()std::remove()如果你真的想使用std::replace(),你需要像这样使用它:

String __fastcall RemoveCharsFromString(String &str, const String &c)
{
    for(int i = 1; i <= c.Length(); ++i)
    {
        const Char *start = str.c_str();
        const Char* end = start + str.Length();
        Char* ptr = std::replace(start, end, c[i]);
        str.Delete(1 + std::distance(start, ptr), std::distance(ptr, end));
    }
}

话虽如此,Embarcadero 的 RTL 有自己的System::Sysutils::StringReplace()功能,您可以使用它来代替std::replace()

#include <System.SysUtils.hpp>

String __fastcall RemoveCharsFromString(String &str, const String &c)
{
    for(int i = 1; i <= c.Length(); ++i)
    {
        str = StringReplace(str, c[i], L"", TReplaceFlags() << rfReplaceAll);
    }
}

c或者,如果您需要在字符串中考虑 UTF-16 代理项(std::remove()不考虑):

#include <System.SysUtils.hpp>
#include <System.Character.hpp>

String __fastcall RemoveCharsFromString(String &str, const String &c)
{
    int i = 1; 
    while (i <= c.Length())
    {
        String chr;
        if (IsSurrogatePair(c, i))
            chr = c.SubString(i, 2);
        else
            chr = c.SubString(i, 1);
        str = StringReplace(str, chr, L"", TReplaceFlags() << rfReplaceAll);
        i += chr.Length(); 
    }
}
于 2016-05-11T20:24:51.273 回答