Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 06.04.05 15:02
Оценка:
У меня имелось несколько int и float переменных, которые я записывал в символьный массив примерно так:
char Msg[256];
sprintf(Msg, "%d %d %f %f",
m_nTemp1, m_nTemp2, m_fTemp3, m_fTemp4);
Теперь мне надо эти и еще несколько переменных и массивов запихнуть в структуру.
ВОПРОС: как полученную структуру перевести в символьный массив char Msg[256]?
Re: Как перевести структуру в строковый буфер
От: ZeusSon  
Дата: 06.04.05 15:59
Оценка:
Здравствуйте, Вов и К, Вы писали:

ВИК>У меня имелось несколько int и float переменных, которые я записывал в символьный массив примерно так:

ВИК> char Msg[256];
ВИК> sprintf(Msg, "%d %d %f %f",
ВИК> m_nTemp1, m_nTemp2, m_fTemp3, m_fTemp4);
ВИК>Теперь мне надо эти и еще несколько переменных и массивов запихнуть в структуру.
ВИК>ВОПРОС: как полученную структуру перевести в символьный массив char Msg[256]?

Ответы:
1. Если необходимо выводить в строку значения используй такой же финт и для каждого из полей структуры. Тут других вариантов нету.
2. Если необходимо просто хранить структуру в строке (как области памяти), то просто заполняешь структуру, а потом: struct _Struct {int a;} _s;
_s.a = 10;
...
char* _str = &_s;

Опиши более подробно твою ситуацию — может помогу.
Re: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 06.04.05 16:18
Оценка: 1 (1)
Здравствуйте, Вов и К, Вы писали:

ВИК>У меня имелось несколько int и float переменных, которые я записывал в символьный массив примерно так:

ВИК> char Msg[256];
ВИК> sprintf(Msg, "%d %d %f %f",
ВИК> m_nTemp1, m_nTemp2, m_fTemp3, m_fTemp4);
ВИК>Теперь мне надо эти и еще несколько переменных и массивов запихнуть в структуру.
ВИК>ВОПРОС: как полученную структуру перевести в символьный массив char Msg[256]?

В С++ для этих целей пользуются

(1) перегрузкой функций...

Например, для вывода в любой текстовый поток общепринято завести семейство операторов <<
std::ostream& operator<< (std::ostream& ostr, const YourType& t);

тогда вывод структуры можно рекурсивно определить через вывод её полей
struct Foo
{
  int x;
  double y;
  Bar z; // ещё какая-то структура
  Buz t[10]; // и даже массив
};

inline std::ostream& operator<< (std::ostream& ostr, const Foo& foo)
{
  ostr << "{ ";
  ostr << x << " " << y << " " << z << " "; // предполагаем, что такой оператор есть и для Bar
  std::copy(t,t+10, std::ostream_iterator<Buz>(ostr, " ")); // маленькая хитрость - копирование массива в поток
    // превращается внутри в ostr << t[0] << " " << t[1] << " " ...
  ostr << "}";
  return ostr;
}


(2) и полиморфными объектами
Если ты решился делать всё через потоки (благо, для них уже много чего имеется в STL), обрати внимание: всё семейство operator<< принимает слева ostream. Это базовый класс, наследники которого — файловые и консольные потоки, но не только. Один из них — ostringstream — всё выводимое коллекционирует в строку.
Foo foo;
std::ostringstream oss;
oss << foo;
std::string s = oss.str();
Перекуём баги на фичи!
Re[2]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 14.04.05 12:53
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Вов и К, Вы писали:


К>(2) и полиморфными объектами

К>Если ты решился делать всё через потоки (благо, для них уже много чего имеется в STL), обрати внимание: всё семейство operator<< принимает слева ostream. Это базовый класс, наследники которого — файловые и консольные потоки, но не только. Один из них — ostringstream — всё выводимое коллекционирует в строку.
К>
К>Foo foo;
К>std::ostringstream oss;
К>oss << foo;
К>std::string s = oss.str();
К>


Это бы мне подошло конечно.

Но кмпилятор ругается при написании следующего кода:

struct Foo
{
int x;
double y;
char t[10]; // массив
};

Foo foo;
foo.x = 11;
foo.y = 22;

std::ostringstream oss;
oss << foo;
std::string s = oss.str();


d:\work\Debug\test\test.cpp(70) : error C2079: 'oss' uses undefined class 'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>,
            _Alloc=std::allocator<char>
        ]
        d:\work\Debug\test\test.cpp(70) : see reference to class template instantiation 'std::basic_ostringstream<_Elem,_Traits,_Alloc>' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>,
            _Alloc=std::allocator<char>
        ]
        d:\work\Debug\test\test.cpp(70) : see reference to class template instantiation 'std::basic_ostringstream<_Elem,_Traits,_Alloc>' being compiled
        with
        [
            _Elem=char,
            _Traits=std::char_traits<char>,
            _Alloc=std::allocator<char>
        ]
d:\work\Debug\test\test.cpp(71) : error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'int' (or there is no acceptable conversion)
d:\work\Debug\test\test.cpp(72) : error C2228: left of '.str' must have class/struct/union type
        type is 'int'




Что я не так делаю?
Заранее прошу извинения за глупые вопросы. Я только начинаю вникать в С++ и STL
Re[3]: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 14.04.05 13:06
Оценка:
Здравствуйте, Вов и К, Вы писали:

ВИК>Что я не так делаю?

#include <sstream>

Сделал?
Перекуём баги на фичи!
Re[4]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 14.04.05 13:17
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Вов и К, Вы писали:


ВИК>>Что я не так делаю?

К>
К>#include <sstream>
К>

К>Сделал?

Тут я немоного лопухнулся. Вместо этого у меня стояло (пробовал другие варианты):
#include <strstream>


После замены вывалилось:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'main::Foo' (or there is no acceptable conversion)
Re[2]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 14.04.05 13:29
Оценка:
Здравствуйте, ZeusSon, Вы писали:

ZS>Здравствуйте, Вов и К, Вы писали:


ВИК>>У меня имелось несколько int и float переменных, которые я записывал в символьный массив примерно так:

ВИК>> char Msg[256];
ВИК>> sprintf(Msg, "%d %d %f %f",
ВИК>> m_nTemp1, m_nTemp2, m_fTemp3, m_fTemp4);
ВИК>>Теперь мне надо эти и еще несколько переменных и массивов запихнуть в структуру.
ВИК>>ВОПРОС: как полученную структуру перевести в символьный массив char Msg[256]?

ZS>Ответы:

ZS>1. Если необходимо выводить в строку значения используй такой же финт и для каждого из полей структуры. Тут других вариантов нету.
ZS>2. Если необходимо просто хранить структуру в строке (как области памяти), то просто заполняешь структуру, а потом: struct _Struct {int a;} _s;
ZS>_s.a = 10;
ZS>...
ZS>char* _str = &_s;

ZS>Опиши более подробно твою ситуацию — может помогу.


ОК. Попытаюсь объяснить поподробнее.

Два хоста соединены по Ethernet. С одного на другой надо передать набор данных.
Было реализовано примерно так.

 
char Msg[256];  
sprintf(Msg, "%d %d %f %f", Temp1, Temp2, Temp3, Temp4);


Это накладывает определенные ограничения на порядок чтения. Т.е. sscanf(...) на приемнике надо выполнять в том же порядке. А параметров в функции у меня сейчас скопилось довольно много. Вот и хотелось бы сделать структуру примерно такую:

struct foo
{
int Temp1;
int Temp2;
double Temp3;
double Temp4;
char Temp5[10];
...
}

Потом присвоить элементам какие-то значения и вывести всю область памяти, занимаемую структурой в строковый поток.
Далее на приемном хосте произвести обратную операцию извлечения из строкового потока в структуру и работать дальше с принятыми данными.

(Проблема передачи по сети не рассматривается. Главное требование буфер для приема-передачи должен быть char)

Как я понимаю, у меня проблема именно в конвертации структуры в строковый поток и последующей правильной обратной операцией на приемном хосте.
Re[5]: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 14.04.05 13:34
Оценка:
Здравствуйте, Вов и К, Вы писали:

ВИК>После замены вывалилось:

ВИК>
ВИК>error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'main::Foo' (or there is no acceptable conversion)
ВИК>


Так ты определил ostream& operator<<(ostream& ost, const Foo& foo) или нет?
Перекуём баги на фичи!
Re[6]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 14.04.05 13:54
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Вов и К, Вы писали:


ВИК>>После замены вывалилось:

ВИК>>
ВИК>>error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'main::Foo' (or there is no acceptable conversion)
ВИК>>


К>Так ты определил ostream& operator<<(ostream& ost, const Foo& foo) или нет?


А надо? Я подумал, что это только для варианта 1.
Что, все-таки надо расписывать вывод каждого поля структуры, как в варианте 1?
Re[7]: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 14.04.05 14:09
Оценка:
Здравствуйте, Вов и К, Вы писали:

К>>Так ты определил ostream& operator<<(ostream& ost, const Foo& foo) или нет?


ВИК>А надо? Я подумал, что это только для варианта 1.

ВИК>Что, все-таки надо расписывать вывод каждого поля структуры, как в варианте 1?

Конечно. "перегрузка функций и полиморфизм".
Это было как бы объяснение, что стоит за оператором <<.
Перекуём баги на фичи!
Re[8]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 15.04.05 11:24
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Вов и К, Вы писали:


К>>>Так ты определил ostream& operator<<(ostream& ost, const Foo& foo) или нет?


ВИК>>А надо? Я подумал, что это только для варианта 1.

ВИК>>Что, все-таки надо расписывать вывод каждого поля структуры, как в варианте 1?

К>Конечно. "перегрузка функций и полиморфизм".

К>Это было как бы объяснение, что стоит за оператором <<.


Тогда чем это все лучше, чем если я напишу что-то типа:

 char evenMsg[256]; 
         std::strstream msg(evenMsg,sizeof evenMsg);          

            msg << m_Temp1 << " ";
         msg << m_Temp1 << " ";            
        msg << m_Temp1 << " ";
         msg << m_Temp1 << " ";      
...


Опять же надо перечислять все переменные в определенном порядке.
Кстати не понятно, как потом их считывать.

А я бы хотел, если это возможно в принципе, сконвертить область памяти занимаемую ВСЕЙ структурой в char* или CString например, прицепить затем к этому делу хидер, а на обратном конце проделать обратную операцию — отделить хидер и переконвертить принятый кусок в структутру.
Если это в принципе невозможно, тогда прижется использовать последовательное занесение параметров. тогда мне структура вообще не нужна.
Re[9]: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 15.04.05 11:44
Оценка:
Здравствуйте, Вов и К, Вы писали:

ВИК>Тогда чем это все лучше, чем если я напишу что-то типа:


Лучше лишь тем, что тебе не придётся копипастить этот код, если вдруг такое потребуется ещё где-то.

ВИК>Опять же надо перечислять все переменные в определенном порядке.

ВИК>Кстати не понятно, как потом их считывать.

ВИК>А я бы хотел, если это возможно в принципе, сконвертить область памяти занимаемую ВСЕЙ структурой в char* или CString например, прицепить затем к этому делу хидер, а на обратном конце проделать обратную операцию — отделить хидер и переконвертить принятый кусок в структутру.

ВИК>Если это в принципе невозможно, тогда прижется использовать последовательное занесение параметров. тогда мне структура вообще не нужна.

А вот эта штука называется "сериализация". И она не сводится к простому распечатыванию в строку и последующему вычитыванию.
Вообще, вывод в текстовое представление для чтения человеком, и в последовательное (необязательно текстовое) представление для последующего восстановления (десериализации) — совершенно разные задачи.

Поищи по форуму (да и по гуглу тоже).
Перекуём баги на фичи!
Re[10]: Как перевести структуру в строковый буфер
От: Cyberax Марс  
Дата: 15.04.05 13:19
Оценка:
Кодт wrote:

> Вообще, вывод в текстовое представление для чтения человеком, и в

> последовательное (необязательно текстовое) представление для
> последующего восстановления (десериализации) — совершенно разные задачи.
> Поищи по форуму (да и по гуглу тоже).

Могу сразу отправить на:
http://boost.org/libs/serialization/doc/index.html ИМХО, лучшая
реализация сериализации для С++.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[2]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 19.04.05 11:18
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Вов и К, Вы писали:


ВИК>>У меня имелось несколько int и float переменных, которые я записывал в символьный массив примерно так:

ВИК>> char Msg[256];
ВИК>> sprintf(Msg, "%d %d %f %f",
ВИК>> m_nTemp1, m_nTemp2, m_fTemp3, m_fTemp4);
ВИК>>Теперь мне надо эти и еще несколько переменных и массивов запихнуть в структуру.
ВИК>>ВОПРОС: как полученную структуру перевести в символьный массив char Msg[256]?

К>В С++ для этих целей пользуются


К>(1) перегрузкой функций...


К>Например, для вывода в любой текстовый поток общепринято завести семейство операторов <<

К>
К>std::ostream& operator<< (std::ostream& ostr, const YourType& t);
К>

К>тогда вывод структуры можно рекурсивно определить через вывод её полей
К>
К>struct Foo
К>{
К>  int x;
К>  double y;
К>  Bar z; // ещё какая-то структура
К>  Buz t[10]; // и даже массив
К>};

К>inline std::ostream& operator<< (std::ostream& ostr, const Foo& foo)
К>{
К>  ostr << "{ ";
К>  ostr << x << " " << y << " " << z << " "; // предполагаем, что такой оператор есть и для Bar
К>  std::copy(t,t+10, std::ostream_iterator<Buz>(ostr, " ")); // маленькая хитрость - копирование массива в поток
К>    // превращается внутри в ostr << t[0] << " " << t[1] << " " ...
К>  ostr << "}";
К>  return ostr;
К>}
К>


К>(2) и полиморфными объектами

К>Если ты решился делать всё через потоки (благо, для них уже много чего имеется в STL), обрати внимание: всё семейство operator<< принимает слева ostream. Это базовый класс, наследники которого — файловые и консольные потоки, но не только. Один из них — ostringstream — всё выводимое коллекционирует в строку.
К>
К>Foo foo;
К>std::ostringstream oss;
К>oss << foo;
К>std::string s = oss.str();
К>


прошу прощения за навязчивость. С вышеизложенным я разобрался. А как сделать обратную операцию из строкового потока в структуру. Куда считывать пробелв между элементами?
Re[3]: Как перевести структуру в строковый буфер
От: Кодт Россия  
Дата: 19.04.05 12:00
Оценка:
Здравствуйте, Вов и К, Вы писали:

(оверквотинг покусан)

ВИК>прошу прощения за навязчивость. С вышеизложенным я разобрался. А как сделать обратную операцию из строкового потока в структуру. Куда считывать пробелв между элементами?


А никуда. Определяешь istream& operator>>(istream& ist, YourType& var)
и все числа будут считаны через пробелы, а вот со строками уже сложности.
Дело в том, что ost<<str пишет строку str как есть, а ist>>str читает до разделителя (пробела или перевода каретки).
Если str содержала разделители, получаем неприятность.
Чтобы избежать этого, можно, например, закодировать строку. Примерно так:
string percent_encode(string s)
{
  // заменить все спецсимволы (0x01-0x20) на читаемые последовательности
  string dst;
  for(int i=0; i<s.size(); ++i)
  {
    char c = s[i];
    char buf[4];
    if(c=='%' || isspace(c) || iscntrl(c)) { sprintf(buf, "%%%02X", (unsigned char)c); dst += buf; }
    else { dst += c; }
  }
  return dst;
}

string percent_decode(string s)
{
  // восстановить спецсимволы из %XX
  string dst;
  for(int i=0; i<s.size(); )
  {
    char c = s[i];
    if(isspace(c) || iscntrl(c)) { ++i; } // игнорируем пробельные символы, их просто не должно быть
    else if(c != '%') { dst += c; ++i; }
    else { char buf[] = { '0', 'x', s[i+1], s[i+2], 0 }; c = atoi(buf); dst += c; i += 3; }
  }
  return dst;
}

(конечно, алгоритм неоптимальный. перепиши его на свой вкус).

Теперь осталось переписать сериализацию:
ostream& operator << (ostream& ost, YourType const& data)
{
  ost << percent_encode(data.s1) << ' ' << percent_encode(data.s2) << data.n3;
  return ost;
}

istream& operator >> (istream& ist, YourType& data)
{
  string tmp;
  ist >> tmp; data.s1 = percent_decode(tmp);
  ist >> tmp; data.s2 = percent_decode(tmp);
  ist >> data.n3;
  return ist;
}
Перекуём баги на фичи!
Re[4]: Как перевести структуру в строковый буфер
От: Вов и К  
Дата: 19.04.05 13:32
Оценка:
Спаисбо.
Настолько я понимаю, реализация функций должна быть:

struct Foo
{
  int x;
  double y;
  ...
};  

  Foo foo;
  std::istringstream iss;
  iss >> foo;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.