C++位流解码函数返回较差的值(指针问题?)

发布于 2024-12-08 13:39:15 字数 6335 浏览 0 评论 0原文

我的函数 READ() 似乎工作正常,但当我转储输入时,我得到的内容超出了我的要求。既不是 0 也不是 1 的奇怪字符。我敢打赌这是由于我的指针使用(取消引用运算符)造成的,但我似乎无法弄清楚正在做什么。任何使其输出正确数据的帮助都会有所帮助。另外,还解释了为什么它的用法是错误的,以及一些关于如何不再这样做的好提示。谢谢你们,你们是最棒的。

在MSVC++ 2010 Express下编译:

#include <iostream> 
using namespace std;

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[6];    // Always 6 bits
    unsigned char hasid[1];     // Always 1 bit
    unsigned char cid[4];       // always 4 bits
};

// Turns our Bytes Into Bits
// Credit: Ben Voigt(http://stackoverflow.com)
void BIT(const char *bytes, size_t len, char *bitStr)
{
    while (len--) {
        bitStr[0] = (*bytes & 0x80) ? '1': '0';
        bitStr[1] = (*bytes & 0x40) ? '1': '0';
        bitStr[2] = (*bytes & 0x20) ? '1': '0';
        bitStr[3] = (*bytes & 0x10) ? '1': '0';
        bitStr[4] = (*bytes & 0x08) ? '1': '0';
        bitStr[5] = (*bytes & 0x04) ? '1': '0';
        bitStr[6] = (*bytes & 0x02) ? '1': '0';
        bitStr[7] = (*bytes & 0x01) ? '1': '0';
        bitStr += 8;
        bytes++;
    }

    *bitStr = 0;
}

// This function is not working correctly
void READ( unsigned char *BITS, unsigned char *PACKET_ID, unsigned char *HAS_CHANNEL_ID, unsigned char *CHANNEL_ID, unsigned char *PACKET)
{
//=====================================================
// The Below Header Info Is Always The Same
//=====================================================
// Packet ID ALWAYS 6 BITS
    PACKET_ID[0] = BITS[2];
    PACKET_ID[1] = BITS[3];
    PACKET_ID[2] = BITS[4];
    PACKET_ID[3] = BITS[5];
    PACKET_ID[4] = BITS[6];
    PACKET_ID[5] = BITS[7];

// Packet Has Channel ID (1==true) ALWAYS 1 BIT
    HAS_CHANNEL_ID[0] = BITS[1];

// Channel ID ALWAYS 4 BIT
    CHANNEL_ID[0] = BITS[0];
    CHANNEL_ID[1] = BITS[15];
    CHANNEL_ID[2] = BITS[14];
    CHANNEL_ID[3] = BITS[13];
//=====================================================
// The above Header Info Is Always The Same
//=====================================================
//Variables For Looping
int P = 16; // This is the start of all data, always
int B = 24; // Every 24 bits, the loop goes into an IF_STATMENT and reads backwards into the array, then continues normally
int A = 1;  // This Increases every 24 bits
int Z = 0;  // This holds how many times we loop.  Used for IF_STATMENT formula
int I = 0;  // This gets zeroed out every IF_STATMENT and keeps our loop int i in sync
        PACKET[0] = BITS[12];
        PACKET[1] = BITS[11];
        PACKET[2] = BITS[10];
        PACKET[3] = BITS[9];
        PACKET[4] = BITS[8];

// Starts our main loop...
for(int i=5 ; i < sizeof(BITS) ; i++, P++, Z++)
{
    PACKET[i] = BITS[P];

    if( (A * B) == Z)   // A==1 B==24 Z==FOR_LOOP
    {
        I = 0;      // ZERO THIS OUT.  THIS IS USED FOR P COUNTER
        A++;        // Increase by one for IF_STATMENT formula
        if( (P+7) <= sizeof(BITS))  // if P+7 is less then or equal to BITS then its okay todo the following
        {                           // which is needed because maybe P+7 is bigger then BITS, so this wouldnt be good ...
            PACKET[i] = BITS[P+7];
            I++;
        }
        if( (P+6) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+1] = BITS[P+6];
            I++;
        }
        if( (P+5) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+2] = BITS[P+5];
            I++;
        }
        if( (P+4) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+3] = BITS[P+4];
            I++;
        }
        if( (P+3) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+4] = BITS[P+3];
            I++;
        }
        if( (P+2) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+5] = BITS[i+2];
            I++;
        }
        if( (P+1) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+6] = BITS[P+1];
            I++;
        }
        if( P <= sizeof(BITS))      // Explained Above
        {
            PACKET[i+7] = BITS[P];
            I++;
        }
        P += I;                 // We have been increasing I each time we do one of the statments to keep track of how many loops
        if(I != 0)              // we need to add to P to keep it on track ...  + I-1 to keep i on track
            i += I-1;
    }
}
}

    int main() 
    {

    const char p40[] =
    {
        0x81, 0x11, 0xb6, 0x1e, 0xc9, 0x67, 0x0e, 0x52, 0x0b, 0xec, 0xff, 0x3b, 0xa8, 0xfa, 0x2a, 0x62, 
        0x41, 0x79, 0xd2, 0x75, 0x7b, 0x93, 0xaf, 0xb4, 0xcf, 0x10, 0x3a, 0x12, 0x4d, 0x4b, 0x60, 0x64, 
        0xcc, 0x78, 0x01, 0xd1, 0x83, 0xbc, 0x27
    };

        Holder k;                               // Call our struct for holding stuff
        unsigned char bitbit[sizeof(p40)*8];    // bitbit is an array that is p40 * 8 to get the amount of bits being made using BIT function

        BIT(p40,sizeof(p40),(char*)bitbit);     // BIT takes p40, and turns it into bits and stores them in bitbit
        k.bits = bitbit;                        // now k.bits is equal to bitbit

    cout << k.bits;                             // dumps k.bits to screen
    cout << "\n";                               // space to see ...

        unsigned char r[sizeof(k.bits-11)];     // r is k.bits - 11 because 11 bits are used for something else

        READ(k.bits, k.header,k.hasid, k.cid,r);    //This puts k.bits into READ function.  Itll store the info into the struct

    cout << "\nPACKET_HEADER:\n";
    cout << k.header;                           // This dump seems to be displaying more then what its suppose too...

    cout << "\nHAS_CANNEL:\n";
    cout << k.hasid;                            // This dump seems to be displaying more then what its suppose too...

    cout << "\nCHANNEL_ID:\n";
    cout << k.cid;                              // This dump seems to be displaying more then what its suppose too...

    cout << "\nPACKET_BITS:\n";
    cout << r;                                  // The last dump (r) is displaying all inputs into the function READ + r.

      int a;                                    // Used to hang program ...
      cin >> a;
      return 0;
    }

My function READ(), seems to be working correctly, except when I dump the inputs I am getting more than what I asked for. Weird chars that are not 0s nor 1s. I bet it is due to my pointer usage (dereference operators), but I just cant seem to figure out what is doing it. Any help on making it output the correct data would be helpful. Also, some explanation why its wrong usage, and some good tips on how to never do it again. Thanks, you guys are the best.

Compiling under MSVC++ 2010 Express:

#include <iostream> 
using namespace std;

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[6];    // Always 6 bits
    unsigned char hasid[1];     // Always 1 bit
    unsigned char cid[4];       // always 4 bits
};

// Turns our Bytes Into Bits
// Credit: Ben Voigt(http://stackoverflow.com)
void BIT(const char *bytes, size_t len, char *bitStr)
{
    while (len--) {
        bitStr[0] = (*bytes & 0x80) ? '1': '0';
        bitStr[1] = (*bytes & 0x40) ? '1': '0';
        bitStr[2] = (*bytes & 0x20) ? '1': '0';
        bitStr[3] = (*bytes & 0x10) ? '1': '0';
        bitStr[4] = (*bytes & 0x08) ? '1': '0';
        bitStr[5] = (*bytes & 0x04) ? '1': '0';
        bitStr[6] = (*bytes & 0x02) ? '1': '0';
        bitStr[7] = (*bytes & 0x01) ? '1': '0';
        bitStr += 8;
        bytes++;
    }

    *bitStr = 0;
}

// This function is not working correctly
void READ( unsigned char *BITS, unsigned char *PACKET_ID, unsigned char *HAS_CHANNEL_ID, unsigned char *CHANNEL_ID, unsigned char *PACKET)
{
//=====================================================
// The Below Header Info Is Always The Same
//=====================================================
// Packet ID ALWAYS 6 BITS
    PACKET_ID[0] = BITS[2];
    PACKET_ID[1] = BITS[3];
    PACKET_ID[2] = BITS[4];
    PACKET_ID[3] = BITS[5];
    PACKET_ID[4] = BITS[6];
    PACKET_ID[5] = BITS[7];

// Packet Has Channel ID (1==true) ALWAYS 1 BIT
    HAS_CHANNEL_ID[0] = BITS[1];

// Channel ID ALWAYS 4 BIT
    CHANNEL_ID[0] = BITS[0];
    CHANNEL_ID[1] = BITS[15];
    CHANNEL_ID[2] = BITS[14];
    CHANNEL_ID[3] = BITS[13];
//=====================================================
// The above Header Info Is Always The Same
//=====================================================
//Variables For Looping
int P = 16; // This is the start of all data, always
int B = 24; // Every 24 bits, the loop goes into an IF_STATMENT and reads backwards into the array, then continues normally
int A = 1;  // This Increases every 24 bits
int Z = 0;  // This holds how many times we loop.  Used for IF_STATMENT formula
int I = 0;  // This gets zeroed out every IF_STATMENT and keeps our loop int i in sync
        PACKET[0] = BITS[12];
        PACKET[1] = BITS[11];
        PACKET[2] = BITS[10];
        PACKET[3] = BITS[9];
        PACKET[4] = BITS[8];

// Starts our main loop...
for(int i=5 ; i < sizeof(BITS) ; i++, P++, Z++)
{
    PACKET[i] = BITS[P];

    if( (A * B) == Z)   // A==1 B==24 Z==FOR_LOOP
    {
        I = 0;      // ZERO THIS OUT.  THIS IS USED FOR P COUNTER
        A++;        // Increase by one for IF_STATMENT formula
        if( (P+7) <= sizeof(BITS))  // if P+7 is less then or equal to BITS then its okay todo the following
        {                           // which is needed because maybe P+7 is bigger then BITS, so this wouldnt be good ...
            PACKET[i] = BITS[P+7];
            I++;
        }
        if( (P+6) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+1] = BITS[P+6];
            I++;
        }
        if( (P+5) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+2] = BITS[P+5];
            I++;
        }
        if( (P+4) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+3] = BITS[P+4];
            I++;
        }
        if( (P+3) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+4] = BITS[P+3];
            I++;
        }
        if( (P+2) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+5] = BITS[i+2];
            I++;
        }
        if( (P+1) <= sizeof(BITS))  // Explained Above
        {
            PACKET[i+6] = BITS[P+1];
            I++;
        }
        if( P <= sizeof(BITS))      // Explained Above
        {
            PACKET[i+7] = BITS[P];
            I++;
        }
        P += I;                 // We have been increasing I each time we do one of the statments to keep track of how many loops
        if(I != 0)              // we need to add to P to keep it on track ...  + I-1 to keep i on track
            i += I-1;
    }
}
}

    int main() 
    {

    const char p40[] =
    {
        0x81, 0x11, 0xb6, 0x1e, 0xc9, 0x67, 0x0e, 0x52, 0x0b, 0xec, 0xff, 0x3b, 0xa8, 0xfa, 0x2a, 0x62, 
        0x41, 0x79, 0xd2, 0x75, 0x7b, 0x93, 0xaf, 0xb4, 0xcf, 0x10, 0x3a, 0x12, 0x4d, 0x4b, 0x60, 0x64, 
        0xcc, 0x78, 0x01, 0xd1, 0x83, 0xbc, 0x27
    };

        Holder k;                               // Call our struct for holding stuff
        unsigned char bitbit[sizeof(p40)*8];    // bitbit is an array that is p40 * 8 to get the amount of bits being made using BIT function

        BIT(p40,sizeof(p40),(char*)bitbit);     // BIT takes p40, and turns it into bits and stores them in bitbit
        k.bits = bitbit;                        // now k.bits is equal to bitbit

    cout << k.bits;                             // dumps k.bits to screen
    cout << "\n";                               // space to see ...

        unsigned char r[sizeof(k.bits-11)];     // r is k.bits - 11 because 11 bits are used for something else

        READ(k.bits, k.header,k.hasid, k.cid,r);    //This puts k.bits into READ function.  Itll store the info into the struct

    cout << "\nPACKET_HEADER:\n";
    cout << k.header;                           // This dump seems to be displaying more then what its suppose too...

    cout << "\nHAS_CANNEL:\n";
    cout << k.hasid;                            // This dump seems to be displaying more then what its suppose too...

    cout << "\nCHANNEL_ID:\n";
    cout << k.cid;                              // This dump seems to be displaying more then what its suppose too...

    cout << "\nPACKET_BITS:\n";
    cout << r;                                  // The last dump (r) is displaying all inputs into the function READ + r.

      int a;                                    // Used to hang program ...
      cin >> a;
      return 0;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

为人所爱 2024-12-15 13:39:15

您将数据保存在 char 数组中,因此当您将它们传递给 std::cout 时,运算符假定以 null 结尾的 C 字符串。除非你的标头保证以空终止,否则 std::cout 将会超出数组的末尾并打印比你想要的更多的内容。

解决此问题的一种巧妙方法是:

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[6];    // Always 6 bits
    unsigned char header_term = '\0' // null terminator
    unsigned char hasid[1];     // Always 1 bit
    unsigned char hasid_term = '\0' // null terminator
    unsigned char cid[4];       // always 4 bits
    unsigned char cid_term = '\0' // null terminator
};

假设您的编译器没有对 Holder 中的字段重新排序,这应该会导致 std::cout 仅打印您期望的字节数。

这仅回答了您问题的一部分。我现在正在发帖,如果我弄清楚其余部分,我将进行编辑。

ETA:查看 READ,您的问题似乎又是缺少空终止。数组中需要一个额外的字符来保存空字符('\0',几乎普遍等于 NULL,本身几乎总是 0),这将告诉 std::cout C 字符串正在结束。另外,这是一种为 Holder 提供空终止的更简洁的方法:

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[7]={0,0,0,0,0,0,'\0'};    // Always 6 bits
    unsigned char hasid[2]={0,'\0'};     // Always 1 bit
    unsigned char cid[5]={0,0,0,0,'\0'};       // always 4 bits
};

我保留了上面原始的、丑陋的修复,因为它说明了导致代码打印额外垃圾的规则。

You are holding your data in char arrays, and so when you pass them to std::cout the operator assumes null-terminated C strings. Unless your headers are guaranteed to be null-terminated, std::cout is going to run off the end of the arrays and print more than you want them to.

A kind of hacky way to fix this:

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[6];    // Always 6 bits
    unsigned char header_term = '\0' // null terminator
    unsigned char hasid[1];     // Always 1 bit
    unsigned char hasid_term = '\0' // null terminator
    unsigned char cid[4];       // always 4 bits
    unsigned char cid_term = '\0' // null terminator
};

Assuming your compiler doesn't re-order the fields in Holder, this should cause std::cout to print only the number of bytes you expect.

This answers only part of your problem. I'm posting for now and will edit if I figure out the rest.

ETA: Looking over READ, it appears your problem is again an absence of null-termination. You need one extra char in the array to hold the null character ('\0', near universally equal to NULL, itself almost always 0) which will tell std::cout that the C string is ending. Also, this is a cleaner way to provide null-termination to Holder:

struct Holder
{
    unsigned char *bits;        // holds our bits
    unsigned char header[7]={0,0,0,0,0,0,'\0'};    // Always 6 bits
    unsigned char hasid[2]={0,'\0'};     // Always 1 bit
    unsigned char cid[5]={0,0,0,0,'\0'};       // always 4 bits
};

I'm keeping the original, ugly fix above because it illustrates the rules that cause your code to print extra garbage.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文