【问题标题】:Unable to concat strings in C++?无法在 C++ 中连接字符串?
【发布时间】:2018-03-02 14:00:09
【问题描述】:

我有一种使用以下定义记录的方法:

void log(std::string s) {
    std::string tag = "main";
    std::cout << tag << " :" << s << std::endl;
}

我正在尝试这样调用此方法:

log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));

directioncount 是整数。

我收到以下错误,&lt;&lt; 带有红色下划线:

没有运算符

我的标题中有#include&lt;string&gt;,以确保我的字符串正常工作。

我试过std::string("direction"),问题还是一样。

C++ 初学者。帮助将不胜感激。

【问题讨论】:

  • std::string("direction") + std::to_string(direction) ...您要连接的是一个字符数组和一个字符串;不是 2 个字符串
  • 这不是必需的:"direction" + std::to_string(direction) 工作。

标签: c++ string function operators concat


【解决方案1】:

operator&lt;&lt; 不用于任意字符串连接 - 它被称为 “输出流运算符”,它仅在 std::ostream 的上下文中使用。

当你说...

std::cout << tag << " :" << s << std::endl;

...您实际上编写的代码大致相当于:

std::cout.operator<<(tag).operator<<(" :").operator<<(s).operator<<(std::endl);

如您所见,operator&lt;&lt; 知道如何使用 std::coutstd::string,但不能在字符串之间使用。


为了连接std::string 实例,您可以简单地使用operator+

log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));

请注意,这种连接技术并不是最有效的:您可能需要查看std::stringstream 或直接使用std::string::reserve 以避免不必要的内存分配。

【讨论】:

  • 好的。但我只是将&lt;&lt; 更改为+,我再也看不到那个错误了。还需要转换吗?
  • @FaizuddinMohammed:是的,抱歉,您实际上不需要将"direction" 显式转换为std::string,因为operator+ 是为(const char*, const std::string&amp;) 定义的。
【解决方案2】:

在处理字符串而不是流时,将 &lt;&lt; 替换为 + 运算符:

log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));

【讨论】:

    【解决方案3】:

    如果您决定使用operator&lt;&lt; 表示法,您需要一个能够理解它的对象。

    这是这样一个对象(我没有声称这是个好主意):

    #include <string>
    #include <sstream>
    #include <iostream>
    
    void log(std::string s) {
        std::string tag = "main";
        std::cout << tag << " :" << s << std::endl;
    }
    
    struct string_accumulator
    {
        std::ostringstream ss;
    
        template<class T>
        friend string_accumulator& operator<<(string_accumulator& sa, T const& value)
        {
            sa.ss << value;
            return sa;
        }
    
        template<class T>
        friend string_accumulator& operator<<(string_accumulator&& sa, T const& value)
        {
            return operator<<(sa, value);
        }
    
        operator std::string () { return ss.str(); }
    };
    
    inline auto collect() -> string_accumulator
    {
        return string_accumulator();
    }
    
    int main()
    {
        int direction = 1;
        int count = 1;
        log(collect() << "direction" << std::to_string(direction) << ", count: " << std::to_string(count));
    }
    

    【讨论】:

    • std::ostringstream就是这样一个对象,是标准的
    • 如果你不想使用这样的对象,你也可以写一个std::string operator &lt;&lt; (std::string, std::string)...我不是建议这样做,但你可以
    • @BasileStarynkevitch 这就是我使用它的原因:)
    • @UKMonkey 除了整个“全局命名空间中的令人惊讶的行为”论点之外,你在 io 操纵器方面会遇到困难。这就是我代理 ostringstream 的原因。它现在也默认理解 . 中的所有内容
    • @RichardHodges 哦,我一点也不建议有人实现该运算符,但这只是使用该语法的另一种方式:) 即使您在回答中说“我没有声称这是一个好主意”,所以我在同一标题下提出了另一个建议
    【解决方案4】:

    你的函数原型是void log(std::string s);。它正在等待std::string。所以你需要传递一个字符串给它,而不是一个流!

    所以,改变这个:

    log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
    

    到这里:

    log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
    

    我只将&lt;&lt; 运算符更改为+ 运算符。现在它将括号内的所有内容连接到单个std::string


    您的尝试意味着您想将std::ostream 作为参数传递。也许您想阅读C++ Passing ostream as parameter。但是,如果我是你,我只会超载&lt;&lt;

    【讨论】:

    • 哦。这绝对有帮助。那么,如果我使用std::ostream 会起作用吗?让我测试一下。
    【解决方案5】:

    你为什么不使用: // 只包含这个using namespace std;

    【讨论】:

    猜你喜欢
    • 2018-10-14
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多