【问题标题】:How to assign '-' is equal to ' ' for string class compare, is this possible?如何为字符串类比较分配'-'等于'',这可能吗?
【发布时间】:2012-01-04 16:35:06
【问题描述】:

我正在使用#string 中的string.compare 函数比较两个字符串str1 和str2。有没有办法强制班级认为'-' 等同于' '。查看 char_traits 的成员函数,我认为 .assign 可以让我完成此任务,但它的行为就像我在说 str1='-';str1=' ';。我不想重写我自己的字符串处理类。

【问题讨论】:

  • 我认为它通过比较字符值来进行比较;这意味着你必须让它认为45 == 32。能否不复制字符串并将所有出现的'-' 替换为' ',然后进行比较?
  • @Chad:这是一个空格,所以32
  • @LightnessRacesinOrbit 啊!不知道那里有一个空间!
  • @Chad:嗯,没有''这样的东西:P

标签: c++ string class


【解决方案1】:

在比较两个字符串之前复制所有出现的“-”并将其替换为“”怎么样?

【讨论】:

    【解决方案2】:

    库中没有针对此类特定用例的任何内容,但自己很容易做到:

    1. 复制两个字符串。在每个中,将所有'-' 替换为' '。然后对这些字符串进行比较;

    2. 或者,创建您的 自己的 函数,该函数遍历每个字符并与您描述的其他语义进行字典比较。这样做的好处是不需要字符串副本,但会编写更多代码并且可能更容易出错。

    【讨论】:

    • 我相信使用自定义char_traits 是可能的。不就是为了这个吗?
    • @MooingDuck:可能,但是您不需要使用这些特征的新std::basic_string 实例化吗?需要复印吗? (好吧,你可以让字符串最初使用这些特征,但这肯定会违反POLS)或者特征是比较的特征吗?我忘记了。
    • 你说得对,它是一个需要副本的新类。替换它们快得多,或者如您所说使用自定义比较。我也认为它更容易出错。无论哪种方式都需要权衡。
    【解决方案3】:

    有几种可能性,取决于您是否想要这种行为:

    • 一次
    • 在类中编码

    如果您想行为一次:只需使用您自己的(自定义)算法:

    bool isSpace(char i) { return i == '-' or i == ' '; }
    
    int compare(std::string const& left, std::string const& right) {
      typedef std::string::const_iterator ConstIterator;
      typedef std::pair<ConstIterator, ConstIterator> Result;
    
      size_t const size = std::min(left.size(), right.size());
    
      Result const r = std::mismatch(left.begin(),
                                     left.begin() + size,
                                     right.begin(),
                                     [](char a, char b) {
                                       return a == b or (isSpace(a) and isSpace(b));
                                     });
    
      if (r.first == left.begin() + size) { // equal up til the end, shorter wins
        return left.size() < right.size() ? -1 :
              (left.size() == right.size() ? 0 : 1);
      }
    
      // not equal until the end
      return *r.first < *r.second ? -1 : 1;
    }
    

    如果此行为需要在类本身中进行编码,您需要使用basic_string 并提供自定义特征类。

    traits 类提供了一个 static int compare ( const char_type* s1, const char_type* s2, size_t n); 函数,供 std::string::compare 在后台使用。

    例如:

    struct MyTraits: char_traits<char> // too lazy to reimplement everything
    {
      static int compare(const char_type* s1, const char_type* s2, size_t n);
      // definition can be trivially derived from the above version
    };
    
    typedef std::basic_string<char, MyTraits> MyString;
    

    当然,MyString 与其他std::string 完全不兼容。


    坦率地说,如果可以的话,只需“规范化”您的字符串并决定是使用 '-' 还是 ' '。它会让你的生活更轻松。

    【讨论】:

    • 我真的别无选择,我必须处理'-',因为这是我们数据库中名称条目中使用的,但是我们的分析在设置运行时不使用它们,所以我需要我的软件来识别这一点,例如。 PC-Eff T-P 是 PC Eff T P 的等价物,因为它认为它是浊度:P
    • @John:在设计典型架构时,反复出现的一点是将数据的外部表示“调整”为自定义的内存表示。例如,DB 层可以简单地将 '-' 替换为 ' ' ,因为记录被拉入,然后你所有的烦恼都会消失。这种输入的验证/规范化很常见:)
    • 我希望std::basic_string 可以从具有不同字符/特征/分配器的std::basic_string 隐式构造。这会简化很多事情。
    • @MooingDuck:我一般不是隐式构造函数的忠实拥护者,但在这种特殊情况下,我可能会受到诱惑:)
    【解决方案4】:

    一种简单的方法是折叠字符串,即在比较它们之前简单地将所有“-”替换为“”。

    【讨论】:

      【解决方案5】:

      标准 C++ 库为此提供了强大的算法。似乎您想将 std::mismatch() 与自定义谓词一起使用,考虑到 '-' 和 ' ' 是相同的。这看起来像这样:

      bool pred(char c0, char c1) {
          return c0 == c1
                || (c0 == '-' && c1 == ' ')
                || (c0 == ' ' && c1 == '-');
      }
      
      std::string const& s(s0.size() < s1.size()? s0: s1);
      std::string const& l(s0.size() < s1.size()? s1: s0);
      auto p = std::mismatch(s.begin(), s.end(), l.begin(), pred);
      

      接着,p 是一对迭代器,指向不同的第一个字符(或结束迭代器)。要确定在您评估结果之前或之后的字符串排序。

      接口有点烦人,因为需要先用较短的序列:两端都应该有约束。

      【讨论】:

        【解决方案6】:

        (社区维基,请随意贡献。)

        您可以基于新的 char 类型定义新的字符串类型。以下编译并似乎运行,但可能有一些东西丢失或错误。目标是定义一个字符串类,其中连字符会自动转换为空格。

        #include<iostream>
        using namespace std;
        
        struct newchar {
                char c;
                bool operator <(const newchar &other) const {
                        return this->c < other.c;
                }
                newchar(char c_): c(c_) {
                        fixme();
                }
                newchar(): c('\0') {}
                newchar & operator = (const newchar &in) {
                        this->c = in.c;
                        fixme();
                        return *this;
                }
                void fixme() {
                        if(c=='-')
                                c = ' ';
                }
        };
        
        struct newstring : basic_string<newchar> {
                string toCharString() const {
                        std :: string s;
                        for(const_iterator i = this->begin(); i != this->end(); i++) {
                                char c = i->c;
                                s += c;
                        }
                        return s;
                }
        };
        ostream& operator<< (ostream & os, const newstring &ns) {
                os << ns.toCharString();
                return os;
        }
        
        int main() {
                newstring s;
                s.compare(s);
                s += 'k';
                cout << '<' << string() << '>' << endl;
                cout << '<' << s << '>' << endl;
        }
        

        【讨论】:

          猜你喜欢
          • 2012-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-20
          • 2013-05-06
          • 1970-01-01
          • 2017-11-23
          • 1970-01-01
          相关资源
          最近更新 更多