我正在编写一个C ++程序,需要对字符串中的某些值进行编码(它必须是一个字符串)。我决定使用sprintf来保存char数组中的数据(一个unsigned int和两个double)。问题是我在理解这个函数的行为时遇到了问题。这是我正在使用的代码
char vel[1];
unsigned int n = 30;
std::sprintf(vel, "%u", n);
std::cout<< "packet sending: " << vel << std::endl;
std::cout<< "packet dim: " << sizeof(vel)<< std::endl;
这是初步测试。因为unsigned int是4个字节而我分配的数组只有1个字符(字节)我期待分段错误但是我很惊讶(当然,对我来说)得到输出
packet sending: 30
packet dim: 4
其实我不明白为什么。此外,目标是存储三个值并使用scanf检索它们。如果可能的话,这就是我想做的事情
char vel[1];
unsigned int n = 30;
std::sprintf(vel, "%u%f%f", n, 5.0,6.0);
std::cout<< "packet sending: " << vel << std::endl;
std::cout<< "packet dim: " << sizeof(vel)<< std::endl;
在我发送字符串
后的另一个函数中std::string s = vel.str();
我做
unsigned int i;
float g,h;
std::sscanf(s.c_str(), "%u%f%f",&i,&g,&h);
当然没有什么工作,你能帮我吗?我阅读了使用过的函数的文档,但我无法理解为什么这不起作用。 谢谢! 安德烈
编辑: 如果我使用以下代码生成一个字符串,我会运行一些测试:
char vel[13];
unsigned int n = 30;
std::sprintf(vel, "%u%f", n, 5.0);
std::stringstream packet;
packet << vel;
std_msgs::String outMsg;
outMsg.data = packet.str();
我尝试以这种方式检索信息:
packet = msg->data.c_str();
unsigned int i;
float f;
std::sscanf(packet, "%u%f", &i, &f);
std::cout << "received packet: "<< i << "\tdata: "<< f << std::endl;
生成的印刷品是
received packet: 305 data: 0
应该是
received packet: 30 data: 5
不应该吗?
再次感谢!
答案 0 :(得分:0)
如果要使用sprintf
,则必须提供足够大的缓冲区来存储所有字符。程序中给出的数组很小,因此函数会覆盖以下内存块,在末尾附加NULL
,然后将其正确打印到stdout。调用sprintf
变量n
后可能不等于30.此函数的更安全版本为snprintf
。
http://www.cplusplus.com/reference/cstdio/snprintf/
http://www.cplusplus.com/reference/cstdio/sprintf/
答案 1 :(得分:0)
第一个代码输出的原因是:
packet sending: 30
packet dim: 4
这是因为sprintf
成功创建了一个字符串,即使vel
只是1个字节的char数组。您的代码在vel
内的sprintf
上产生缓冲区溢出。并且可能通过此溢出修改变量n
(不知道)。如果您打印n
的值,我想它不再是30
。
我猜这是你想在第一段代码上完成的事情:
char vel[42]; //42 = 11 + 1 + 14 + 1 + 14 + 1
unsigned int n = 30;
std::sprintf(vel, "%u %.5f %.5f", n, 5.0,6.0);
std::cout<< "packet sending: " << vel << std::endl;
std::cout<< "packet dim: " << strlen(vel)<< std::endl;
//Changes:
// - add spaces in your format string
// change "%u%f%f" to "%u %f %f" so sscanf() will know
// when to stop parsing a specific data.
// - replace sizeof(vel) with strlen(vel) because
// your sending a string that changes size.
// sizeof() is for getting the size of DATA TYPES only.
在接收器代码中,尝试更改sscanf()中的格式字符串:
std::sscanf(packet, "%u %f", &i, &f); //add space in the middle.