J'ai besoin d'aide pour une mission de laboratoire de programmation que je n'arrive pas à comprendre.

La question est :

Permettez à l'utilisateur de saisir 4 valeurs entières toutes comprises entre 0 et 15 inclus. Stockez ces 4 valeurs dans un seul entier de 32 bits nommé "packit". Permettez à l'utilisateur de choisir lequel des 4 entiers il souhaite récupérer à partir de "packit". Une entrée de "1" récupérera la première entrée de valeur, un "2" la seconde, un "3" la troisième, etc. N'utilisez que des manipulations de bits pour stocker et récupérer les valeurs.

Voici ce que j'ai jusqu'à présent:

#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;
}

Je me suis arrêté à output1 juste pour le tester, et ça ne marche pas. Cependant, c'est ce à quoi je suis arrivé après avoir essayé pendant des heures. Je ne suis pas sûr de ce que je fais de mal. Je suis les notes que j'ai copiées sur le tableau en classe. Toute aide serait appréciée.

1
n00b programmer 3 mai 2017 à 23:41

3 réponses

Meilleure réponse

Vous ne manipulez pas correctement les bits.

Les valeurs 0-15 nécessitent 4 bits maximum, mais vous ne déplacez les bits que de 2 places, vous avez donc de la place pour gérer les valeurs 0-3 uniquement.

Décomposons votre code, en utilisant 15 (1111 en binaire) comme exemple.

Ce code:

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

Prend les données existantes (32, qui sont 00100000 en binaire), les décale de 2 places vers la gauche, devient 10000000.

Alors ce code:

data = data | input1;

Ajoute l'entrée (que vous ne restreignez en aucune façon, par l'affectation) dans les bits inférieurs, devenant 10001111.

Ce code:

output1 = data >> 2;

Décale le nombre total de bits de 2 places vers la droite, devenant 00100011, qui, comme vous pouvez le voir, perd les deux bits inférieurs de la valeur d'entrée précédente qui a été stockée.

Alors ce code:

cout << output1;

Sort les bits restants tels quels, qui se compose de bits de deux valeurs différentes fusionnées ensemble, produisant 35 comme sortie.

Donc, vous devez décaler les bits dans les deux sens de 4 bits (le minimum nécessaire pour gérer les valeurs 0-15, prenant 16 bits au total) ou de 8 bits (le maximum autorisé à adapter 4 valeurs sur 32 bits). Et dans le cas du décalage vers la droite, vous devez masquer les bits dont vous ne voulez pas dans la sortie.

Essayez plutôt quelque chose de plus comme ceci:

Utilisation du stockage 4 bits (le minimum nécessaire pour gérer les valeurs 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;
}

Utilisation du stockage 8 bits (le maximum autorisé, ce qui permettrait en fait de gérer des valeurs de 0 à 255 maximum):

#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;
}
4
Remy Lebeau 3 mai 2017 à 21:17

Vous pouvez accomplir cela par manipulation de bits ou avec une union. L'union a tendance à être l'approche la plus lisible.

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

Remarque: la punition de type via une union n'est valide qu'en C.

Pour utiliser les opérations sur les bits, vous devez effectuer à la fois un décalage et une opération and ou or pour récupérer et définir correctement les bits.

unsigned long packit = 0;

// Set data0
packit |= data0;

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

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

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

La lecture est l'opposé du réglage. Vous devez effacer toutes les valeurs à l'exception de ce que vous voulez lire et la décaler dans la bonne position.

unsigned char data0 = (packit & 0x000000FF);
unsigned char data1 = (packit & 0x0000FF00) >> 8;
unsigned char data2 = (packit & 0x00FF0000) >> 16;
unsigned char data3 = (packit & 0xFF000000) >> 24;
6
lcs 3 mai 2017 à 21:00

Vous devez penser en vous-même, Combien de bits faut-il pour représenter le nombre 15?

15 = 1111

Cela prend exactement 4 bits.

Vous devez maintenant stocker 4 de ces nombres ... vous aurez donc besoin de 16 bits. Ce qui signifie que vous pouvez même stocker tous ces numéros dans un int, short ou 2 chars. Utilisons les ints comme on vous a dit de le faire.

Ok, revenons à ton code,

#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;
}

D'abord ceci, unsigned int data = 32; // makes room for the 4 integers.

Cela ne laisse pas de place pour 4 entiers comme vous le supposez. Le nombre 32 est 10000 en binaire.

Ce que vous voulez en fait faire pour faire de la place pour 4 entiers, c'est que chaque fois que vous voulez stocker l'un des nombres, vous décalez les bits de l'entier vers la gauche de 4, puis stockez le nombre en utilisant le bit ou ({{ X0}}) pas =

C'est donc plus ce dont vous avez besoin pour commencer:

unsigned int data = 0;

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

Maintenant, pour récupérer, disons input1, nous faisons ceci:

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

Pourquoi?

En effet, input1 est suivi de 8 bits appartenant à input2 et input3, donc nous les éliminons, puis pour obtenir la valeur là-bas, nous faisons le bit par bit et & de 15 (1111), ce qui est simplement fait parce que la largeur du nombre stocké n'est pas supérieure à 15, et parce que 15 est le plus petit nombre le plus proche de ces nombres et se compose de tous les 1.

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

input3 == (data)&((1 << 4)-1)

J'espère que cela pourra aider

2
smac89 3 mai 2017 à 21:25