带有 %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
所要求的。但请注意我的示例如何仅在最后可能的场合转换字符串。
在下面的代码中:
#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
所要求的。但请注意我的示例如何仅在最后可能的场合转换字符串。