带有 %s 和 std::string 的 sprintf 给出乱码

sprintf with %s and std::string gives gibberish

在下面的代码中:

#include <string>
using namespace std;

int main(){
    char command[300];
    string stringz = "mystringy";
    sprintf(command,"echo \"something with a string %s\" ", stringz);
    system(command);
    return 0;
}

为什么是输出

something with a string 8�

而不是预期的

something with a string mystringy

一个愚蠢的问题,但我找不到答案。

sprintf 格式 %s 需要一个 C 字符串,这是一个以 0 结尾的 char 数组,而不是 std::string.

stringz.c_str() 并且由于 C++11 &stringz[0]stringz.data() 是获取 std::string.[=17= 持有的 C 字符串的几种方法]

printf 的 '%s' 修饰符采用 char*,而不是 std::string

你可以这样写:

sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());

其中给你一个const char*到一个std::string的内容。这显示了 sprintf 的主要弱点之一——没有类型检查!

要添加 Deduplicator 答案,请尝试输入

sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());

你应该设置好了。

您可以使用:

sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());

请注意 %s 使用 C 字符串而不是 std::string

最好还是用,iostreams:

string stringDemo("MYSTRING");
std::cout << stringDemo << "\n";

这是因为 sprintf 期望 char * 作为扩展 %s 标记的参数。它会像

sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());

将字符串的“char *”版本传递给 sprintf

之所以显示那些奇怪的字符是因为整个 std::string 对象被复制到sprintf 的栈帧中。然后,接受可变数量参数的 sprintf 查看它自己的堆栈 space 并假设它要找到的是 char *,但实际上是一些垃圾结果将字符串数据重新解释为 char *,并在取消引用时生成该序列。如果你运气不好,它也可能会出现段错误。

首先你不应该使用 sprintf。这是 C++,而不是 C。 std::string 以一种非常自然的方式支持连接,使用 + 运算符,就像在其他一些编程语言中一样:

#include <string>

int main(){
    std::string stringz = "mystringy";
    std::string command = "echo \"something with a string " + stringz + "\" ";
    system(command.c_str());
    return 0;
}

如果您坚持使用 char 数组函数,如 sprintf,请使用 stringz.c_str()。其实,这也是system所要求的。但请注意我的示例如何仅在最后可能的场合转换字符串。