Manipolazione di bit

di il
6 risposte

Manipolazione di bit

Salve a tutti. Non riesco ad uscire fuori da questo programma. La traccia è presa dal Deitel "Tecniche avanzate di prog. in c++":

L'operatore shift a sinistra può essere usato per comprimere i valori di due caratteri, in una variabile intera senza segno di due byte. Scrivete un programma che accetta in input due caratteri dalla tastiera e li passa alla funzione packCharacters. Per comprimere due caratteri in una variabile intera unsigned, assegnate il primo carattere alla variabile unsigned, fate scorrere a sinistra, per 8 posizioni la variabile unsigned, e combinate la variabile unsigned con il secondo carattere, usando l'operatore a livello di bit OR inclusivo. Il programma dovrà visualizzare i caratteri nel loro formato a bit, prima e dopo essere stati compressi nell'intero unsigned , per provare che i caratteri sono di fatto correttamente compressi nella variabile unsigned.

Da quello che ho capito siccome parla di compressione significa che nella variabile unsigned di 2 byte (16 bit) 8 bit rappresentano un carattere e gli altri 8 un altro carattere. Il codice ASCII della lettera a ad esempio su 16 bit è 01100001 00000000 in quanto ho fatto lo shift di 8 posizioni come dice la traccia. La lettera b il codice è: 00000000 01100010. Facendo la OR di questi due codici ottengo effettivamente 01100001 01100010 di cui i primi 8 bit rappresentano effettivamente la a e i secondi 8 la b. Io ho scritto il codice che mi calcola a e b ma non riesco a fare la OR dato che mi escono tutti 1. Ovviamente le lettere a e b sono un esempio potevo considerare c d o qualsiasi altra lettera..Date un'occhiata:

#include <iostream>
#include <cstdlib>
#include <iomanip>

using namespace std;

void packCharacters( char a, char b ); // prototipo

int main()
{
   char a, b; // integral value to print in binary

   cout << "Inserisci un primo carattere: ";
   cin >> a;
   cout << "Inserisci un secondo carattere: ";
   cin >> b;
   packCharacters( a, b );
   
   system("pause");
   return 0;
}

void packCharacters( char a, char b )
{
     const unsigned MASK = 1 << 15;
     unsigned value = a;
     value <<= 8;
     unsigned value1 = b;
   // display bits
   for ( unsigned i = 1; i <= 16; i++ ) 
   {
      cout << ( value & MASK ? '1' : '0' ); 
      
      value <<= 1;

      if ( i % 8 == 0 ) 
         cout << ' ';
   }
   cout << endl;
   for ( unsigned i = 1; i <= 16; i++ ) 
   {
      cout << ( value1 & MASK ? '1' : '0' ); 
      
      value1 <<= 1;

      if ( i % 8 == 0 ) 
         cout << ' ';
   }
   cout << endl;
   for ( unsigned i = 1; i <= 16; i++ ) 
   {
      cout << ( value1 | value ? '1' : '0' ); 
      
      
      value <<= 1; 

      if ( i % 8 == 0 ) // mette uno spazio dopo 8 bit
         cout << ' ';
   }

   cout << endl;
}

6 Risposte

  • Re: Manipolazione di bit

    Scusa ma cosa c'è di complicato nel fare ciò
    
    unsigned val = a;
    val <<= 8;
    
    val |= b;
    
    per estrarre i dati puoi usare
    
    a = val >> 8;
    b = val & 0xFF;
    
    siccome vuoi i primi 8 bit questi si ricavano usando come maschera un numero con i 8 bit meno siginificativi a 1 e questo numero è il 255 (00000000 11111111) che in hex è FF.
  • Re: Manipolazione di bit

    M'è riuscito finalmente però la mia soluzione non la vedo molto elegante soprattutto perchè devo riscrivere le tre istruzioni iniziali sennò mi escono risultati sballati però è sostanzialmente corretta nei risultati.. Dacci un'occhiata se puoi skynet:
    
    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    void packCharacters( char a, char b );
    
    int main()
    {
         char a, b;
    
         cout << "Inserisci un primo carattere: ";
         cin >> a;
         cout << "Inserisci un secondo carattere: ";
         cin >> b;
         cout << endl;
         packCharacters( a, b );
         
         cout << endl;
       
         system("pause");
         return 0;
    }
    
    void packCharacters( char a, char b )
    {
         const unsigned MASK = 1 << 15;
         unsigned value = a;
         value <<= 8;
         value |= b;
          
         cout << a << " = ";
         for ( unsigned i = 1; i <= 8; i++ ) 
         {
             cout << ( value & MASK ? '1' : '0' );
             value <<= 1;
         }
         
         cout << "\n" << b << " = ";
         for ( unsigned i = 9; i <= 16; i++ ) 
         {
             cout << ( value & MASK ? '1' : '0' );
             value <<= 1;
                 
         }
         
         cout << endl;
         unsigned value1 = a;
         value1 <<= 8;
         value1 |= b;
         cout << "Caratteri " << a << " e " << b << " compressi: ";
         for ( unsigned i = 1; i <= 16; i++ ) 
         {
             cout << ( value1 & MASK ? '1' : '0' );
             value1 <<= 1;
             if ( i % 8 == 0 ) // mette uno spazio dopo 8 bit
             cout << ' ';
         }
       
       cout << endl;
    }
    
  • Re: Manipolazione di bit

    Ti è permesso usare <bitset> ?
    
        void packCharacters( char a, char b )
        {
             unsigned value = a;
             value <<= 8;
             value |= b;
             
    		 std::bitset<8> aVal(value >> 8);
    		 std::bitset<8> bVal(value & 0xFF);
    
    		 cout << aVal.to_string() << " " << bVal.to_string();
        }
    
  • Re: Manipolazione di bit

    Skynet non sapevo della classe bitset buono a sapersi. Soltanto che non riesco a capire la logica che è molto importante. Allora iniziamo col dire che sul computer che uso il char occupa 1 byte (8 bit) mentre il tipo unsigned 4 byte (32 bit). Supponiamo che io inserisca le lettere a e b:
    a = 97 (decimale ASCII) = 01100001 (binario)
    Ora seguiamo la funzione; a viene assegnato a value, ma value essendo un unsigned memorizzerà il numero:
    value = 00000000 00000000 00000000 01100001
    Shifto a sinistra value di 8:
    value = 00000000 00000000 01100001 00000000
    b = 00000000 00000000 00000000 01100010
    La OR tra value e b vale:
    value|b = 00000000 00000000 01100001 01100010
    Poi definisco l'oggetto aVal di 8 bit inizializzandolo allo shift a destra di value di 8 posizioni. Ma lo shift di 8 posizioni di value è:
    01100010 00000000 00000000 01100001
    Ed ecco la mia domanda. L'oggetto bitset prende gli ultimi 8 bit cioè quelli meno significativi non i primi 8? Perchè se è così allora mi trovo. E mi trovo pure con bVal. Grazie..
  • Re: Manipolazione di bit

    NO. Lo shift a destra non è rotatorio. Lo shift non viene applicato alla stessa variabile ma il risultato viene copiato in aVal. E' come se tu scrivessi
    
    unsigned valoreRitorno = value >> 8;
    
    questa equivale a 
    
    unsigned valoreRitorno = value / (2^8); 
    ovvero
    unsigned valoreRitorno = value / (256); 
    
    quindi il risultato dello shift è
    00000000 00000000 00000000 01100001.

    il bitset prende i x numeri meno significativi si, ma anche se li predesse tutti l'operazione
    value >> 8 da un nuovo numero che non viene assegnato a value (quindi nessuna rotazione)
  • Re: Manipolazione di bit

    Ok
Devi accedere o registrarti per scrivere nel forum
6 risposte