printf 与 std::string?

新手上路,请多包涵

我的理解是 stringstd 命名空间的成员,那么为什么会出现以下情况呢?

 #include <iostream>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString);
    cin.get();

    return 0;
}

在此处输入图像描述

每次程序运行时, myString 打印一个看似随机的 3 个字符的字符串,例如上面的输出。

原文由 Chunky Chunk 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

它正在编译,因为 printf 不是类型安全的,因为它使用 C 意义上的变量参数1 。 printf 没有 std::string 的选项,只有 C 风格的字符串。使用其他东西代替它所期望的绝对不会给你想要的结果。这实际上是未定义的行为,所以任何事情都可能发生。

由于您使用的是 C++,因此最简单的解决方法是使用 std::cout 正常打印它,因为 std::string 通过运算符重载支持它:

 std::cout << "Follow this command: " << myString;

如果由于某种原因需要提取 C 风格的字符串,可以使用 — 的 std::string c_str() 方法得到一个 const char * 即 null-终止。使用您的示例:

 #include <iostream>
#include <string>
#include <stdio.h>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString.c_str()); //note the use of c_str
    cin.get();

    return 0;
}

如果您想要一个类似于 printf 的函数,但类型安全,请查看可变参数模板(C++11,自 MSVC12 起在所有主要编译器上都支持)。你可以 在这里 找到一个例子。我知道在标准库中没有类似的实现,但在 Boost 中可能有,特别是 boost::format


[1]:这意味着您可以传递任意数量的参数,但函数依赖于您告诉它这些参数的数量和类型。在 printf 的情况下,这意味着具有编码类型信息的字符串,如 %d 表示 int 。如果您对类型或数字撒谎,该函数没有标准的获知方式,尽管一些编译器能够在您撒谎时检查并发出警告。

原文由 chris 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以使用 snprinft 来确定所需的字符数并分配正确大小的缓冲区。

 int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;

这是对 cppreference.com 上 示例 的小改编

原文由 shuhalo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题