小编典典

printf 与 std::string?

all

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

#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 个字符的字符串,例如上面的输出。


阅读 98

收藏
2022-07-14

共1个答案

小编典典

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

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

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

如果出于某种原因,您需要提取 C 风格的字符串,您可以使用 的c_str()方法std::string来获取一个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。如果您对类型或数字撒谎,该函数没有标准的获知方式,尽管一些编译器能够在您撒谎时检查并发出警告。

2022-07-14