从字符串或字符串流设置和获取数据

问题描述 投票:-1回答:1

我正在尝试编写一个可重用的消息对象,该对象将使用其属性,将它们转换为定界字符串(使用0x1d组分隔符),将其放入char缓冲区中,并且还可以进行反向操作(从char回到对象)。

之所以必须这样做,是因为我完全受操作系统功能的限制,只能发送类型为char和固定大小的消息,因此这是我的包装。

这是我到目前为止所拥有的。易于包装..现在,我该如何写一个明智的包装方法。如果这个班的每个孩子都必须手动解压缩这些数据,我可以,但是我不知道如何。我尝试过getline,但随后我得到一个字符串,将不得不编写许多转换函数。必须有一种更简单的方法。

注意我在C ++ 98中。

#include <iostream>
#include <sstream>
#include <string.h>

class Msg {
    public:
        Msg(){
            delim = 0x1d;
        }
        int8_t ia;
        int16_t ib;
        int32_t ic;
        int64_t id;
        uint8_t ua;
        uint16_t ub;
        uint32_t uc;
        uint64_t ud;
        std::string str = "aaa bbb ccc dddd";
        char sz[64];
        char delim;

        // convert to a char buffer
        void ToBuffer(unsigned char* b, int s){
            std::stringstream ss;
            ss << ia << delim
               << ib << delim
               << ic << delim
               << id << delim
               << ua << delim
               << ub << delim
               << uc << delim
               << ud << delim
               << str << delim 
               << sz << delim;

            strncpy((char*)b, ss.str().c_str(), s);
            b[s-1] = '\0';
        }

        // convert from a char buffer
        void FromBuffer(unsigned char* b, int s){
            // what on earth to do here..
            // could use getline which returns a string after
            // each delimiter, then convert each string to the
            // value in a known order.. but at that point I may
            // as well have written this all in C... !
        }

        void Print(){
            std::cout 
                << " ia " << ia
                << " ib " << ib
                << " ic " << ic
                << " id " << id
                << " ua " << ua
                << " ub " << ub
                << " uc " << uc
                << " ud " << ud
                << " str " << str 
                << " sz "  << sz;
        }
};

int main()
{
    Msg msg;
    msg.ia = 0xFE;
    msg.ib = 0xFEFE;
    msg.ic = 0xFEFEFEFE;
    msg.id = 0xFEFEFEFEFEFEFEFE;
    msg.ua = 0xEE;
    msg.ub = 0xDEAD;
    msg.uc = 0xDEADBEEF;
    msg.ud = 0xDEADBEEFDEADBEEF;
    snprintf(msg.sz, 64, "this is a test");
    msg.Print();

    int s = 128;
    unsigned char b[s];
    msg.ToBuffer(b, s);

    Msg msg2;
    msg2.FromBuffer(b, s);
    //msg2.Print();


    return 0;
}
c++ c++98
1个回答
0
投票

好,所以它可以工作,但是将缓冲区放入字符串流中只是一个丑陋的事情,所以您可以使用带有分隔符的std :: getline提取位,然后使用另一个字符串流或std :: stoi和朋友进行转换正确类型的项目:

https://repl.it/repls/GainsboroInsecureEvents

    void FromBuffer(unsigned char* b, int s){
        std::string item;
        std::stringstream ss((char *)b);
        // You don't NEED to use std::stringstream to convert
        // the item to the primitive types - you could use
        // std::stoi, std::stol, std::stoll, etc but using a
        // std::stringstream makes it so you don't need to
        // know which primitive type the variable is
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ia;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ib;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ic;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> id;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ua;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ub;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> uc;
        std::getline(ss,item,'\x1d'); std::stringstream(item) >> ud;
        // Until you get to here.  Then >> stops on a space
        // and all the sudden you can't use >> to get the data
        std::getline(ss,str,'\x1d');
        // And a C string is even worse because you need to
        // respect the length of the buffer by using strncpy
        std::getline(ss,item,'\x1d'); strncpy(sz,item.c_str(),64); sz[63] = '\0';
    }

因此,我认为更好的方法是创建一个使用新定界符的新ctype构面,并在字符串流中注入新构面,就像在此处changing the delimiter for cin (c++)所做的那样

这样我们就可以直接提取哪个更好:

https://repl.it/repls/GraveDraftyAdministrators

    void FromBuffer(unsigned char* b, int s){
        struct delimiter : std::ctype<char> {
          delimiter() : std::ctype<char>(get_table()) {}
          static mask const* get_table()
          {
            static mask rc[table_size];
            rc[0x1d] = std::ctype_base::space;
            return &rc[0];
          }
        };
        std::stringstream ss((char *)b);
        ss.imbue(std::locale(ss.getloc(), new delimiter));
        ss >> ia
           >> ib
           >> ic
           >> id
           >> ua
           >> ub
           >> uc
           >> ud
           >> str
           >> sz;
    }
© www.soinside.com 2019 - 2024. All rights reserved.