/* MANIPULACION DE BITS DE ENTERO DE DOS BYTES
El siguiente programa, contiene funciones para manipulaci¢n de los bits de
un entero de dos bytes sin signo. Debe tener bien claro, antes de leerlo,
tanto los números binarios como los hexadecimales y los diferentes operadores
sobre bits.  */
																																																																			 //BitEscrib.CPP
#include <IOManip.H>
#include <ConIO.H>
#include <Math.H>

const Bits=16;

//---------------------------------------------------------------------------
void EscribirBitsDeEntero(unsigned int Decimal){
	unsigned int Aux; // Son Bits bits sin signo
	int Veces=Bits-1;//simule siguiente error: coloque esta variable unsigned

	while(Veces >= 0){
		Aux = Decimal;
		Aux = Aux >> Veces;
		Aux = Aux & 0x1;
		cout << Aux;
		Veces--;
	}
	cout << endl;
}
//---------------------------------------------------------------------------
unsigned int ObtenerNBitsDesdePos(unsigned int Valor, int N, int Pos){
	unsigned int Mascara = 0;
	int i=0;

	while(i < N-1){
		Mascara = Mascara | 0x1; //Se inserta un uno cada vez
		Mascara = Mascara << 1; //Se corre hacia la izquierda cada vez
		i++;
	}
	Mascara = Mascara | 0x1;//inserta un uno en bit 1. El menos significativo

	Mascara = Mascara << (Pos-N); //Se coloca M scara en posici¢n adecuada
	Valor = Valor & Mascara; //Se efect£a extracci¢n de los bits pedidos
	Valor = Valor >> (Pos-N);//se ajustan los bits pedidos a la derecha
	return Valor;
}
//---------------------------------------------------------------------------
unsigned int RotarUnBitHaciaLaIzq(unsigned int Valor){
/*Al desplazar los bits hacia las izquierda, con << se perder  el bit más
significativo, por esto hay que previamente almacenarlo en otra variable y,
luego asignarlo a la derecha de Valor. De esta forma quedan rotados, una vez
todos los bits*/
	unsigned int Aux;

	Aux = (Valor >> 15);//Aux toma bit más a la izquierda. Más significativo
	Valor = Valor << 1; //Se corren todos los bits a la izquierda.
				//Se pierde el que est  más la izquierda, y
				//a la derecha se completa con un cero
	Valor = Valor | Aux;//El bit que inicialmente era el más significativo,
				//se coloca ahora a la derecha.
	return Valor;
}
//---------------------------------------------------------------------------
unsigned int RotarUnBitHaciaLaDer(unsigned int Valor){
/*Al desplazar los bits hacia la derecha, con >> se perder  el bit menos
significativo, por esto hay que previamente almacenarlo en otra variable y,
luego asignarlo a la izquierda de Valor. De esta forma quedan rotados, una vez
todos los bits*/
	unsigned int Aux;

	Aux = Valor & 0x1;//Aux toma el bit más a la derecha. Menos significativo
	Aux = Aux << 15; //se dezplaza este bit de la derecha, a la izquierda.
	Valor = Valor >> 1; //Se corren todos los bits a la derecha.
				//Se pierde el que est  más la derecha, y
				//a la izquierda se completa con un cero
	Valor = Valor | Aux;//El bit que inicialmente era el memos significativo,
				//se coloca ahora a la izquierda.
	return Valor;
}
//---------------------------------------------------------------------------
unsigned int RotarBits(unsigned int Valor, int N){
	unsigned int i=0;

	if(N>0)
		while(i < N){
			Valor = RotarUnBitHaciaLaIzq(Valor);
			i++;
		}
	else
		if(N < 0){
			N = -N;
			while(i < N){
				Valor = RotarUnBitHaciaLaDer(Valor);
				i++;
			}
		}

	return Valor;
}
//---------------------------------------------------------------------------
unsigned int InvertirBits(unsigned int Valor){
	unsigned int Vector[16], Bit=0, Mascara=0x1,	PotenciaDeDos = 1;

	while(Bit < 16){
		Vector[Bit] = Valor & Mascara;
		Vector[Bit] =	Vector[Bit] >> Bit;
		Bit++;
		Mascara = Mascara << 1;
	}

	Bit = 16;	Valor = 0;
	while(Bit > 0){
		Bit--;
		Valor = Valor + Vector[Bit]*PotenciaDeDos;
		//cuando la variable Vector se coloca de tipo int, el resultado
		//no da, debido a que la multiplicación anterior, la efectúa solo
		//sobre dos bytes con signo.
		PotenciaDeDos = PotenciaDeDos << 1;//Queda multiplicado por dos
	}
	return Valor;
}
//---------------------------------------------------------------------------
unsigned int ByteMenosSignificativo(unsigned int DosBytes){
	unsigned int aux=DosBytes;

	aux = aux<<8;//SE DESPLAZA 8 BITS A LA IZQUIERDA
	aux = aux>>8;//SE DESPLAZA 8 BITS A LA DERECHA

	return aux;
}
//---------------------------------------------------------------------------
unsigned int IntercambiarBytesIzquierdoyDerecho(unsigned int DosBytes){

	return (ByteMenosSignificativo(DosBytes)<<8) | ByteMasSignificativo(DosBytes) ;
}
//---------------------------------------------------------------------------
int LongitudCadena(char *c){
	int l=0;

	while (*c){
		l++;
		c++;
	}

	return l;
}

int LeerEnBinarioValor(){
	int longitud;
	unsigned int suma=0;
	char CadenaBinaria[20];

	cout << "Digite un numero en Binario (maximo 16 Digitos).";
	cout << "\nA continuaci¢n se mostrara su representaci¢n como Entero: ";
	cin >> CadenaBinaria;

	longitud = LongitudCadena(CadenaBinaria);

	for (int i=0;i<=longitud-1;i++){
		suma = suma + (CadenaBinaria[i]-'0') * pow(2, longitud- ( i + 1) );
	}
	cout << "Como entero = " << suma;
	return suma;
}
//---------------------------------------------------------------------------
unsigned int ByteMasSignificativo(unsigned int DosBytes){
	unsigned int aux=DosBytes;

	aux=aux>>8;//SE DESPLAZA 8 BITS A LA DERECHA

	return aux;
}
//---------------------------------------------------------------------------
void main(){
	unsigned int Decimal, N; // Son 16 bits sin signo
	char opcion;

	for(;;){
		clrscr();
		cout << "1. Digite decimal\n";
		cout << "2. Digite binario\n";
		cout << "3. Extraer N bits de los 16, desde una posici¢n\n";
		cout << "4. Rotar a izquierda y derecha\n";
		cout << "5. Se invierten todos los bits:\n";
		cout << "6. Bytes menos y m s significativo:\n";
		cout << "Cualquier otro caracter para terminar";

		opcion=getch();
		clrscr();
		switch(opcion){
		//---------------------------------------------------------------------------
			case '1':
				cout << "Digite un n£mero entero en base decimal(0 al 65536): ";
				cin >> Decimal;
				EscribirBitsDeEntero(Decimal);
				break;
		//---------------------------------------------------------------------------
		 case '2':
				Decimal = LeerEnBinarioValor();
				break;
		//---------------------------------------------------------------------------
			case '3':
				EscribirBitsDeEntero(Decimal);
				cout <<"\nSe extraer n N bits de los 16, desde una posici¢n: ";
				cout <<"\nDigite el n£mero de bits a extraer N(1 a 16): ";
				cin >> N;
				cout <<"\nDigite desde que posici¢n de bit quiere extraer("
						 << N << " a 16): ";
				int Pos; cin >> Pos;

				EscribirBitsDeEntero(	ObtenerNBitsDesdePos(Decimal, N, Pos));
				break;
		//---------------------------------------------------------------------------
			case '4':
				EscribirBitsDeEntero(Decimal);
				cout <<"\nSe rota un bit hacia la izquierda:\n";
				EscribirBitsDeEntero( RotarUnBitHaciaLaIzq(Decimal));
				cout <<"\nSe rota un bit hacia la Derecha:\n";
				EscribirBitsDeEntero( RotarUnBitHaciaLaDer(Decimal));

				cout <<"\nDigite el n£mero de veces que quiere rotar los bits. ";
				cout <<"\nNegativo para la derecha y positivo para la izquierda:";
				cin >> N;

				EscribirBitsDeEntero( RotarBits(Decimal, N));
				break;
	//---------------------------------------------------------------------------
			case '5':
				EscribirBitsDeEntero(Decimal);
				cout <<"\nSe invierten todos los bits:\n";
				EscribirBitsDeEntero( InvertirBits(Decimal) );
				break;
	//---------------------------------------------------------------------------
			case '6':
				EscribirBitsDeEntero(Decimal);
				cout <<"\nByte m s significativo  : ";
				EscribirBitsDeEntero(ByteMasSignificativo(Decimal) );
				cout <<"\nByte menos significativo: ";
				EscribirBitsDeEntero(ByteMenosSignificativo(Decimal));
				cout <<"\nIntercambio de bytes    : ";
				EscribirBitsDeEntero( IntercambiarBytesIzquierdoyDerecho(Decimal) );
				break;
		}
		if(opcion>='1' && opcion <= '6')
			getch();
		else
			return;
	}
}



