位操作将多个值存储在一个int C ++中

时间:2017-05-03 20:41:07

标签: c++ bit-manipulation

我需要帮助完成我似乎无法解决的编程实验室任务。

问题是:

  

允许用户输入0到15之间的4个整数值。将这4个值存储到一个名为" packit"的32位整数中。允许用户选择他们希望从" packit"中恢复的4个整数中的哪一个。输入" 1"将恢复第一个值输入," 2"第二,a" 3"第三种,等等。只使用位操作来存储和恢复值。

这是我到目前为止所做的:

#include <iostream>

using namespace std;

int getInput(){
    int in;
    cout << "Input a number: ";
    cin >> in;
    return in;
}

int main(){
    int input1, input2, input3, input4;
    int output1, output2, output3, output4;
    unsigned int data = 32; // makes room for the 4 integers
    input1 = getInput();
    input2 = getInput();
    input3 = getInput();
    input4 = getInput();

    data = data << 2; //makes room for the input
    data = data | input1;
    output1 = data >> 2;
    cout << output1;


    return 0;
}

我在output1停留只是为了测试它,它不起作用。然而,这是我在尝试了几个小时之后来到的。我不确定我做错了什么。我跟着我在课堂上复制的笔记。 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:6)

您可以通过位操作或联合来完成此操作。联盟往往是更具可读性的方法。

union
{
  unsigned char[4] data;
  unsigned long packed;
} packit;

data[0] = 1;
data[1] = 1;
data[2] = 1;
data[3] = 1;

std::cout << "packit = " << packit.packed;
// packit = 16843009
// 00000001 00000001 00000001 00000001

注意:通过联合键入双关语仅在C中有效。

要使用位操作,您需要执行移位以及andor操作以正确检索和设置位。

unsigned long packit = 0;

// Set data0
packit |= data0;

// Set data1
packit |= (data1 << 8)

// Set data2
packit |= (data2 << 16)

// Set data3
packit |= (data3 << 24)

阅读与设置相反。除了想要阅读的内容之外,您需要清除任何值并将其移动到正确的位置。

unsigned char data0 = (packit & 0x000000FF);
unsigned char data1 = (packit & 0x0000FF00) >> 8;
unsigned char data2 = (packit & 0x00FF0000) >> 16;
unsigned char data3 = (packit & 0xFF000000) >> 24;

答案 1 :(得分:3)

您没有正确操作这些位。

值0-15最多需要4位,但是您只将位移2位,因此您只有处理值0-3的空间。

让我们分析您的代码,使用15(二进制1111)作为示例。

此代码:

data = data << 2; //makes room for the input

采用现有数据(32,二进制为00100000),将其向左移2位,变为10000000

然后这段代码:

data = data | input1;

在较低位中添加输入(您没有以任何方式限制,根据分配),变为10001111

此代码:

output1 = data >> 2;

将总位数向右移动2位,变为00100011,正如您所见,它会丢失已存储的上一个输入值的低两位。

然后这段代码:

cout << output1;

按原样输出剩余的比特,它由两个不同值合并在一起的比特组成,产生35作为输出。

因此,您需要在两个方向上按位移位4位(处理值0-15所需的最小值,总共占16位)或8位(允许最大值为4位的32位) 。在右移的情况下,您需要屏蔽输出中不需要的位。

尝试更像这样的东西:

使用4位存储(处理值0-15所需的最小值):

#include <iostream>
#include <limits> 

using namespace std;

unsigned int getInput()
{
    unsigned int in;
    do
    {
        cout << "Input a number between 0-15 inclusive: ";
        if (cin >> in)
        {
            if ((in >= 0) && (in <= 15))
                break;
        }

        cin.clear();
        cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
    }
    while (true);

    return in;
}

int main()
{
    unsigned int input1, input2, input3, input4;
    unsigned int packit, output;
    int which;

    input1 = getInput();
    input2 = getInput();
    input3 = getInput();
    input4 = getInput();

    packit = (input4 << 12) | (input3 << 8) | (input2 << 4) | input1;

    do
    {
        cout << "Which number to retrieve (1-4, or 0 to exit): ";
        if (cin >> which)
        {
            if (which == 0)
                break;

            if ((which >= 1) && (which <= 4))
            {
                output = ((packit >> (4*(which-1))) & 0x0F);
                cout << output << endl;
                continue;
            }
        }

        cin.clear();
        cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
    }
    while (true);

    return 0;
}

使用8位存储(允许的最大值,实际上允许处理最大值0-255):

#include <iostream>
#include <limits> 

using namespace std;

unsigned int getInput()
{
    unsigned int in;
    do
    {
        cout << "Input a number between 0-15 inclusive: "; // or 255
        if (cin >> in)
        {
            if ((in >= 0) && (in <= 15)) // or 255
                break;
        }

        cin.clear();
        cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
    }
    while (true);

    return in;
}

int main()
{
    unsigned int input1, input2, input3, input4;
    unsigned int packit, output;
    int which;

    input1 = getInput();
    input2 = getInput();
    input3 = getInput();
    input4 = getInput();

    packit = (input4 << 24) | (input3 << 16) | (input2 << 8) | input1;

    do
    {
        cout << "Which number to retrieve (1-4, or 0 to exit): ";
        if (cin >> which)
        {
            if (which == 0)
                break;

            if ((which >= 1) && (which <= 4))
            {
                output = ((packit >> (8*(which-1))) & 0xFF);
                cout << output << endl;
                continue;
            }
        }

        cin.clear();
        cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
    }
    while (true);

    return 0;
}

答案 2 :(得分:1)

你必须自己想一想,表示数字15需要多少位?

15 = 1111

它只需要4位。

现在你需要存储4个这样的数字...所以你需要16位。这意味着您甚至可以将所有这些数字存储在intshort2 chars中。按照你的要求,让我们使用整数。

好的,回到你的代码,

#include <iostream>

using namespace std;

int getInput(){
    int in;
    cout << "Input a number: ";
    cin >> in;
    return in;
}

int main(){
    int input1, input2, input3, input4;
    int output1, output2, output3, output4;
    unsigned int data = 32; // makes room for the 4 integers
    input1 = getInput();
    input2 = getInput();
    input3 = getInput();
    input4 = getInput();

    data = data << 2; //makes room for the input
    data = data | input1;
    output1 = data >> 2;
    cout << output1;


    return 0;
}

首先,unsigned int data = 32; // makes room for the 4 integers

这不会为您假设4个整数腾出空间。数字是32 二进制10000

为4个整数腾出空间,你真正想做的是,无论何时你想存储任何数字,你都要将整数中的位向左移4,然后使用按位或者按位存储数字。 (|)不是=

所以这更像是你需要开始的东西:

unsigned int data = 0;

data = (data << 4)|input1;
data = (data << 4)|input2;
data = (data << 4)|input3;

现在要检索说input1,我们这样做:

(data >> 8)&((1 << 4)-1)

<强>为什么吗

这是因为input1之后是属于input2input3的8位,所以我们将其删除,然后实际获取值,我们按位进行{{1} 1}}的15(1111),这是因为存储的数字的宽度不大于15,因为15是最接近这些数字的最小数字,并且由所有1&#39组成。

&

input2 == (data >> 2)&((1 << 4)-1)

希望有所帮助