在字符串中编码浮点数和整数

时间:2014-04-02 23:35:54

标签: c++

我正在编写一个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

不应该吗?

再次感谢!

2 个答案:

答案 0 :(得分:0)

如果要使用sprintf,则必须提供足够大的缓冲区来存储所有字符。程序中给出的数组很小,因此函数会覆盖以下内存块,在末尾附加NULL,然后将其正确打印到stdout。调用sprintf变量n后可能不等于30.此函数的更安全版本为snprintfhttp://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.