кодирование чисел с плавающей точкой и целых чисел в строке

0

Я пишу программу C++, которая требует кодирования некоторых значений в строке (она должна быть строкой). Я решил сделать это, используя sprintf, чтобы сохранить данные (один неподписанный int и два удвоения) в массиве char. Дело в том, что у меня проблемы с пониманием поведения этой функции. Вот код, который я использую

    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 char (байт), я ожидаю ошибку сегментации. Однако я удивительно (для меня, конечно), получая вывод

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);

Конечно, ничего не работает, не могли бы вы мне помочь? Я прочитал документацию по используемой функции, но я не мог понять, почему это не работает. Спасибо! Andrea

EDIT: Я запускаю некоторые тесты, если я создаю строку со следующим кодом:

    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

не так ли?

Еще раз спасибо!

  • 1
    Вы не можете «ожидать ошибки сегментации». Там нет ничего, что позволяет вам ожидать, что сломанная программа делает.
  • 0
    Я не понимаю Почему вы только даете vel 1 байты? Вам нужно как минимум 11 байтов для хранения 4-байтового значения без знака в виде строки. Рассмотрим значение 4294967295 (максимальное значение). Это 10 символов + 1, необходимых для завершающего нулевого символа.
Показать ещё 7 комментариев
Теги:

2 ответа

0
Лучший ответ

Причина, по которой вывод вашего 1-го кода:

packet sending: 30
packet dim: 4

это потому, что sprintf успешно создал строку, хотя vel - только 1 байт. Ваш код создает переполнение буфера на 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.
  • 0
    Это действительно решило мою проблему, спасибо!
  • 0
    'Рад помочь. :)
Показать ещё 3 комментария
0

Если вы хотите использовать sprintf вам необходимо предоставить буфер, достаточно большой для хранения всех символов. Массив, заданный в вашей программе, является небольшим, поэтому функция перезаписывает следующий блок памяти, добавляет NULL в конец и затем правильно печатает его в stdout. После вызова переменной sprintf n, вероятно, не равно 30. Безопасной версией этой функции является snprintf. http://www.cplusplus.com/reference/cstdio/snprintf/ http://www.cplusplus.com/reference/cstdio/sprintf/

  • 0
    Спасибо! Однако, если я пишу стек достаточно большой и пытаюсь получить значения, это не работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню