【问题标题】:sprintf and array of char vs std::stringsprintf 和 char 数组 vs std::string
【发布时间】:2018-05-02 04:11:36
【问题描述】:

我想知道为什么给出以下内容:

int main()
{
    char buf[50];
    //char str1[] = "ahoy";
    //char str2[] = "matey";
    std::string str1 = "ahoy";
    std::string str2 = "matey";

    sprintf(buf, "%s %s\n", str1, str2);

    std::cout << buf;
    return 0;
}

当 str1、str2 是字符数组时,我得到 ahoy matey 的预期输出。但是当 str1、str2 是 std::string 时,我会得到乱码输出。这是否与 char 数组实际上就是这样的事实有关,而 std::string 可能在实际 char 数组之前有一些元数据?

【问题讨论】:

  • 编译警告是什么?
  • 在 C++ 中,通常你会为这种类型的操作使用字符串流而不是 sprintf。

标签: c++


【解决方案1】:

你几乎是对的。 std::string 包含字符串本身以外的额外信息,例如字符串的长度。事实上,这些字符实际上并没有存储在字符串对象中。相反,字符串对象存储了字符的内存地址,这些地址位于其他位置。

如果您需要使用接受 char 数组的函数,请使用 c_str member function。但是你不能修改这个函数返回的内容,如果字符串对象发生变化,结果可能会失效。

C 输入/输出函数对 C++ 字符串一无所知,并尝试将数据解释为 char 数组,这就是您得到垃圾的原因。如果您打开编译器警告(您确实应该这样做),编译器会警告您。

您应该只使用 C++ 字符串和输入/输出。 std::string 提供了一个方便的 overload for the + operator 连接字符串。如果您不立即输出结果,请使用此选项。

newString = str1 + ' ' + str2;

您也可以只使用多个&lt;&lt;s,这样可以防止在您使用+ 时发生额外复制等问题。

std::cout << str1 << ' ' << str2 << '\n';

【讨论】:

    【解决方案2】:

    应该是: sprintf(buf, "%s %s\n", str1.c_str(), str2.c_str()); 否则你会得到原始的类数据——显然不是你想要的。但是,不要像那样混合 C 和 C++。一直使用std::string。 IOW,请考虑使用 stringstream 代替您的追加。

    【讨论】:

      【解决方案3】:

      当你说,

      sprintf(buf, "%s %s\n", str1, str2);
      

      %s 格式说明符需要一个指向字符数组初始元素的指针,而 str1str2std::string

      The warning tells it all

      【讨论】:

        【解决方案4】:

        代码会给出警告:

        prog.cc:15:18: warning: format '%s' expects argument of type 'char*',
        but argument 3 has type 'std::__cxx11::string' {aka
        'std::__cxx11::basic_string<char>'} [-Wformat=]
        
         sprintf(buf, "%s %s\n", str1, str2);
                      ^~~~~~~~~
        

        sprintf:

        int sprintf( char* buffer, const char* format, ... );
        

        期待char* args

        因此,如果您真的想使用std::string,请先将其转换为c-string

        sprintf(buf, "%s %s\n", str1.c_str(), str2.c_str());
        

        C++-ish

        其他方式是使用stringstream:

        #include <sstream>
        
        std::stringstream ss;
        ss << str1 << " " << str2;
        std::cout << ss.str(); // ahoy matey
        

        【讨论】:

          猜你喜欢
          • 2015-08-27
          • 1970-01-01
          • 2011-10-26
          • 1970-01-01
          • 1970-01-01
          • 2012-03-03
          • 1970-01-01
          • 2016-08-22
          • 1970-01-01
          相关资源
          最近更新 更多