提问者:小点点

用std::string printf?


我的理解是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个字符的字符串,如上面的输出。


共3个答案

匿名用户

之所以进行编译,是因为printf不是类型安全的,因为它使用了C语言意义上的变量参数1printf没有std::string选项,只有C样式字符串。 用别的东西代替它所期望的东西肯定不会给你想要的结果。 这实际上是一种未定义的行为,所以任何事情都可能发生。

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

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

如果出于某种原因需要提取C样式字符串,可以使用std::stringc_str()方法来获取以空结尾的const char*。 使用您的示例:

#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但类型安全的函数,请查看variadic模板(C++11,从MSVC12开始所有主要编译器都支持)。 你可以在这里找到一个例子。 我不知道在标准库中有什么类似的实现,但是在Boost中可能有,特别是Boost::format

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

匿名用户

请不要使用printf(“%s”,your_string.c_str());

使用cout<<<; 改为Your_String;。 简短,简单和类型安全。 实际上,当您编写C++时,通常希望完全避免printf--它是C语言中的一个剩余部分,在C++中很少需要或有用。

至于为什么要使用cout而不是printf,原因不胜枚举。 下面是几个最明显的例子:

>

  • 如问题所示,printf不是类型安全的。 如果您传递的类型与转换说明符中给出的类型不同,printf将尝试使用它在堆栈上找到的任何东西,就像它是指定的类型一样,从而给出未定义的行为。 有些编译器可以在某些情况下对此发出警告,但有些编译器根本不能/不愿意发出警告,而且没有一个编译器可以在所有情况下发出警告。
  • printf不可扩展。 您只能向它传递基元类型。 它所理解的转换说明符集在它的实现中是硬编码的,您没有办法添加更多/其他。 大多数编写良好的C++应该主要使用这些类型来实现面向所解决问题的类型。
  • 它使适当的格式设置更加困难。 举个明显的例子,当您打印数字供人们阅读时,您通常希望每隔几个数字插入几千个分隔符。 作为分隔符使用的数字和字符的确切数目各不相同,但cout也涵盖了这一点。 例如:

    std::locale loc("");
    std::cout.imbue(loc);
    
    std::cout << 123456.78;
    

    无名区域设置(“”)根据用户的配置选择区域设置。 因此,在我的机器上(配置为美式英语),这将打印为123,456.78。 对于为德国配置计算机的人来说,它会打印出类似123.456,78的内容。 对于为印度配置了它的人来说,它将输出为1,23,456.78(当然还有很多其他的)。 使用printf,我正好得到一个结果:123456.78。 这是始终如一的,但对任何地方的每个人来说都是始终如一的错误。 基本上,解决它的唯一方法是单独进行格式化,然后将结果作为字符串传递给printf,因为printf本身并不能正确地完成这项工作。

  • 匿名用户

    如果希望类似C的字符串(const char*)与printf一起使用,请使用mystring.c_str()

    谢谢