¡Nuevo!  por fin disponible la versión 5 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


9.4  Manejo de bits


  Obtener el patrón de bits de un número entero sin signo:  se acepta una entrada numérica por el teclado hasta que se pulsa Intro (0x0D). El programa proporciona la imagen del patrón de bits correspondiente al número introducido.

#include <iostream.h>

int main() {        // ==========

  unsigned long m, res;
  int iter =0;

  std::cout << "Introduzca un numero positivo (Intro para terminar):" << std::endl;
  cin >> m;
  if (m < 0) std::cout << "Numero NO valido." << endl;
  else if (m <= 255)   iter = 8;
  else if (m <= 65535) iter = 16;
  else if (m <= 4294967295) iter = 32;
  for (int i = iter; i > 0; i--) {
    res = m & static_cast <unsigned long> (pow(2, i-1));
    cout << (res == 0? "-0": "-1");

  }
  cout << endl;
  return 0;
}

Resultados obtenidos con diversos valores:

m = 128       ->  -1-0-0-0-0-0-0-0

m = 3250     ->  -0-0-0-0-1-1-0-0-1-0-1-1-0-0-1-0

m = 112448  ->  -0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-1-1-0-1-1-0-1-1-1-0-1-0-0-0-0-0-0


   A continuación se incluye una versión perfeccionada del anterior.  El programa acepta igualmente un entero sin signo; a continuación puede seleccionarse la longitud del patrón de bits correspondiente:  "C" para carácter (8 bits);  "S" para unsigned short (16 bits) y "L" para unsigned log (32 bits). 

#include <iostream>
#include <conio.h>
using namespace std;

void mapC(unsigned char);    // Prototipos de las funciones que
void mapS(unsigned short);   // mostrarán el patrón de bits del
void mapL(unsigned long);    // número introducido

int main() {                 // ====================
   int val;                  // variables auxiliares
   bool ok = false;
   double uDouble = 0;
   while (true) {            // bucle principal
      cout << "\r\nIntroduzca un numero (Intro para terminar):" << endl;

      cin >> uDouble;
      cout << "\r\nValor seleccionado: " << uDouble << endl;
      ok = false;
      while ( true ) {
         cout << "\r\nSeleccione longitud: C=8 bits, S=16 bits, L=32 bits (ESC = salir)";
         val = getch();
         if (val == '\x1B') break;    // Escape
         else if (val==67 || val==99 || val==83 || val==115 || val==76 || val==108) {
            ok = true;
            break;
         } else {
            cout << "\r\nEl caracter NO es valido" << endl;
         }
      }
      if (! ok) break; // terminar ejecucion
      if (uDouble < 0 ) {
         cout << "\r\nEl numero NO es correcto (solo valores positivos)" << endl;
         continue;
      }
      switch (val) {
         case 67: case 99:        // unsigned char (8 bits)
            if (uDouble > UCHAR_MAX) {
               cout << "\r\nValor demasiado grande para 8 bits" << endl;
               break;
            }
            mapC((unsigned char) uDouble);    // observe el "casting"
            break;
         case 83: case 115: // unsigned short (16 bits)
            if (uDouble > USHRT_MAX) {
               cout << "\r\nValor demasiado grande para 16 bits" << endl;
               break;
            }
            mapS((unsigned short) uDouble);
            break;
         case 76: case 108: // unsigned long (32 bits)
            if (uDouble > ULONG_MAX) {
               cout << "\r\nValor demasiado grande para 16 bits" << endl;
               break;
            }
            mapL((unsigned long) uDouble);
            break;
      }
   }
   return EXIT_SUCCESS;
}

void mapC (unsigned char value) {     // patrón de 8 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 7; i >= 0; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << "\r\n";
}

void mapS (unsigned short value) {    // patrón de 16 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 15; i >= 8; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << " ";
   for(int j = 7; j >= 0; j--) cout << ((value & (1 << j)) ? "1" : "0");
   cout << "\r\n";
}

void mapL (unsigned long value) {     // patrón de 32 bits
   cout << "\r\n\nMapa de bits = ";
   for(int i = 31; i >= 24; i--) cout << ((value & (1 << i)) ? "1" : "0");
   cout << " ";
   for(int j = 23; j >= 16; j--) cout << ((value & (1 << j)) ? "1" : "0");
   cout << "-";
   for(int k = 15; k >= 8; k--) cout << ((value & (1 << k)) ? "1" : "0");
   cout << " ";
   for(int l = 7; l >= 0; l--) cout << ((value & (1 << l)) ? "1" : "0");
   cout << "\r\n";
}

Resultados para diversos valores de entrada:

128 y "C" -->  Mapa de bits = 10000000

128 y "S" -->  Mapa de bits = 00000000 10000000

255 y "S" --> Mapa de bits = 00000000 11111111

256 y "S" --> Mapa de bits = 00000001 00000000

4,294,967,040 y "L" -->  Mapa de bits = 11111111 11111111-11111111 00000000

Comentario:

Se ha dispuesto un control para verificar que la cantidad numérica está dentro del rango permitido a la longitud del patrón escogido. Este control se realiza mediante las constantes manifiestas UCHAR_MAX, USHRT_MAX y ULONG_MAX ( 2.2.4).

La cantidad introducida se asocia inicialmente a un número suficientemente grande (un double de 64 bitrs) para albergar cualquier entero.  Posteriormente se realiza un casting adecuado a la longitud elegida; a continuación se invoca la función que muestra el patrón de bits según la longitud seleccionada.  Observe que se supone una distribución "Big-endian" ( 2.2.6a), el octeto más significativo se muestra a la izquierda.

El programa puede ser útil para comprobar el resultado de los "experimentos" y ejercicios relativos a los operadores de manejo de bits ( 4.9.3).