Mis primeros 10 ejercicios en C

Dado que llevo dias sin presentar nada (por falta de tiempo), hoy dediqué un ratito para postear este post en bl4ck-p0rtal.org, y ya os lo dejo aquí también

Son mis primeros 10 ejercicios en C y sirven a modo de repaso por si en algún momento necesitara consultarlos

saludos
nax

1. Hi world


#include
#include

int main() {
printf("Hola mundo\n");
system("PAUSE");
return 0;
}

2. ClrScr

#include
#include

int main() {
system("cls");
printf("Hola\n");
system("pause");
}

3. Tipos: Int

#include
#include

int main() {
int x = 10, y = 20;
printf("El valor de x es %i!\nY el de y es %i\n", x, y);
system("pause");
}

4. Tipos: Char

#include
#include

int main() {
unsigned char letra = 'A'; //unsigned sirve para aumentar el rango de numeros positivos quitando los negativos
printf("El valor de ASCII de la letra %c es %i\n", letra, letra);
letra = letra + 1;
printf("Ahora el valor ASCII de la letra %c es %i\n", letra, letra);
system("pause");
}

5. Tipos: Float

#include
#include

int main() {
float var = 3.04;
printf("El numero %f se escribe de forma exponencial asi: %e\n", var, var);
system("pause");
}

6. sizeof()

#include
#include

int main() {
int var;
printf("El tipo int ocupa %i bytes\n", sizeof(var));
system("pause");
}

7. Scanf

#include
#include

int main() {
int num;
printf("Introduzca un numero: ");
scanf("%i", &num);
printf("El numero introducido es %i\n", num);
system("pause");
}

8.Getchar()

#include
#include

int main() {
char letra;
printf("Introduce una letra: ");
letra = getchar();
printf("Has introducido %c\n", letra);
system("pause");
return 0;
}

9. Bucles

#include
#include

int main() {
int i, j;

for(i=0, j=0; i<=20; i++, j+=2) { printf("En la linea %i J vale %i\n", i, j); } system("pause & cls"); while(i>0)
{
printf("Ahora i vale %i\n", i);
i--;
}

system("pause");


return 0;

}
10. Switch
Código: [Seleccionar]
#include
#include

int main() {
int opcion;

printf("Elije 1, 2 o 3: ");
scanf("%i", &opcion);

switch(opcion)
{
case 1:
printf("escojiste 1");
break;
case 2:
printf("escojiste 2");
break;
case 3:
printf("escojiste 3");
break;
default:
printf("Eres idiota");
break;
}
printf("\n");
system("pause");
return 0;
}

Bien eso es todo, espero el próximo code sea algo mas elaborado :GRI:

pd. por alguna razón se come los include... podes ver los códigos completos Aquí

Creando un bot IRC en PHP con Feed RSS

Creando un bot IRC en PHP con Feed RSS

$index[0][0] : Introducción


$index[0][1]. ¿Por qué esta guía?

Esta guía va destinada a un nivel bajo de PHP, explicando cada función y su funcionamiento, revisando el código línea por línea y ofreciendo soporte en www.bl4ckp0rtal.org/foro para cualquier tipo de problema o duda.
También viene originada por la poca documentación útil (se pueden encontrar entre 10 y 20 tutoriales de bots en PHP y ninguno de ellos funciona o está bien explicado) que se pueda encontrar en la red, sin ir más lejos mi primer bot se ha basado en un código PHP no funcional, en un código python y con la ayuda de mi amigo Frozzenfew en este lenguaje.

$index[0][2]. ¿Qué necesito saber?

Yo creo que no hay nada que no se pueda conseguir sin ganas y la motivación adecuada, pero te recomiendo que tengas una noción aceptable de PHP (sobretodo arrays y creación de funciones).
Todas las funciones que voy a explicar se pueden encontrar en php.net (Bendita página) y siempre que tengamos algún problema es sin duda al primer sitio donde debemos ir, de todos os iré dejado un link a su respectiva página en php.net.


$index[1][0] : Los primeros pasos de tu bot


$index[1][1]. Las Clases (Class) de PHP

Vamos a hacer uso de la OOP de PHP (más info: http://php.net/manual/en/language.oop5.php) para la programación de nuestro bot.
Lo básico que debemos saber:

Class ClassName //Declaramos la Class como si se tratase de una función
{
Var
variable = valor; //a estas variables accederemos así: $this->variable
Function __construct($variable) //el () funciona igual que en function
{ //esta función se llama cuando usamos new ClassName
//Aquí aremos las operaciones correspondientes al crear el nuevo objeto (bot)
}
}
$var = new ClassName($variable) //Llamamos a la clase (creándola) y le pasamos una variable para que trabaje con ella.
?>
$index[1][2]. Configuración del Bot

Ya que tenemos claro cómo será el esqueleto de nuestro bot, vamos a empezar por codear algunas configuraciones previas. (la parte anterior era solo un ejemplo, si hay alguna duda en el orden del code abajo dejaré el code completo)

set_time_limit(0)
ini_set(‘display_errors’, ‘on’)
$config = array(//Config del server:
'server' => 'server’,
'
port' => 6667,
'
nick' => nick,
'
pass' => pass,
'
name' => 'nombre',
'
owner' => 'tunick',
'
channel' => 'canal
);
?>

El time limit es el tiempo que un script tiene permitido ejecutarse, si el tiempo se supera el script se cierra, esto es bueno para evitar ciertos bucles pero en nuestro caso no queremos que se cierre por lo tanto quitamos la opción asignándole el valor 0.
Con ini_set habilitamos que se muestren los errores. No creo que haga falta documentar más ambas partes.

La variable $config la usaremos como array, es más simple así, de entre toda la configuración solo cabe resaltar:
Owner: es la persona que controlará el bot, aquellos más experimentados y que tengan la necesidad de asignar el Owner a varias personas siéntanse libres de crearse un array en owner.
Pass: Antes de poder usar esto hemos de registrar el Nick de nuestro bot, que quede claro para que luego no haya errores en el funcionamiento.

$index[1][3]. Función __Construct()

Para que no haya dudas el nombre de construct lleva 2 ‘_’.
Cuando declaramos una variable fuera de una función podemos usar GLOBAL para acceder a ella o pasarla por parámetro, este último método usaremos, así que la función __construct requerirá la variable $config.
Dejo los comentarios originales del code porque os pueden ayudar para entender una primera lectura del code.

class IRCBot
{
var $socket;//Definimos la conexión
var $ex = array();//Definimos el array de datos

function __construct($config)
{
$this->socket = fsockopen($config['server'], $config['port']); //conectamos...
if (!$this->socket) //comprobemos que conecta...
{ echo "Unable to connect to ".$config['server'];
} else {
$this->send('USER', $config['nick'].' bl4ckp0rtal.org '.$config['nick'].' :'.$config['name']); //Log User
$this->send('NICK', $config['nick']); //Change Nick
$this->main($config); //A jugar!
}
}
?>
Creamos la Class con el nombre IRCBot y le definimos 2 variables $socket para la conexión y $ex como un array para cuando separemos los datos (esto ya se verá mas adelante.
Analizemos __construct mas a fondo, primero que nada __construct requiere una variable como argumento que llamará $config.
Usamos la variable para abrir una conexión mediante el comando fsockopen(dirección,puerto) (info: http://es2.php.net/manual/en/function.fsockopen.php).
Una vez que hemos intentado conectar comprobaremos que se haya conectado, si es así con la función send(comando,mensaje) (esta función la explicaré más abajo al detalle, de momento quedaros con que envía datos al servidor.), cambiamos nuestro Nick y llamamos a la función main($config).


$index[1][4]. Función main()


En esta función también necesitamos trabajar con los datos de la configuración por eso requerirá que se le pase una variable por parámetro.

Pd. A partir de aquí hay muchísimas formas de plantear el funcionamiento. Así que espero que el lector se tome este manual como una simple orientación para comprender el cómo y luego pueda aplicar su propia lógica de programación. Esta en ningún momento se dice que sea la única ni la mejor manera de hacerlo, simplemente es la forma que a mí me gusta hacer.

function main($config)
{
$on = 1; // funciona asi que on es 1
while($on) //Aca vamos con el bucle, solo salimos si on es 0
{
$data = fgets($this->socket,1024); //recibimos datos
echo nl2br($data);
flush();
$this->ex = explode(' ',$data); //Separamos los datos
?>
Aquí no acaba el code pero vamos a ir por partes, la función main es la principal, el cerebro de la aplicación. Se encarga de recolectar los datos y de dar las respuestas correspondientes.
Primero de todo ponemos una variable llamada $on en 1 o true que nos servirá para controlar el bucle “infinito”. A continuación creamos ese espantoso bucle infinito que nos puede dar varios problemas. Si en algún momento vuestro bot falla y se desconecta sin razón aparente o intenta entrar a un canal ya conectado recomiendo ir al Administrador de tareas y matar el proceso httpd.exe pues con varios fallos podría llegar a sobrecargar nuestro pc.

Bien, primero vamos a capturar los datos que nos envían y guardarlo en la variable $data con fgets(conexión,tamaño de datos), hasta hoy tenía el tamaño a 128 pero recomiendo subirlo a 1024 para poder enviarle más datos, mostramos los datos por pantalla y usamos flush(); (http://es2.php.net/manual/en/function.flush.php).

Ahora viene la parte que mas confusiones crea, primero hemos de tener clara como será el formato de $data:

:nax!nax@bl4ckp0rtal.org PRIVMSG #bl4ckp0rtal :palabra1 palabar2 etc

Ese es el formato básico de un mensaje, podemos analizar 4 partes esenciales:
$this->Ex[0] :nax!nax@bl4ckp0rtal.org: en esta parte sacamos 3 partes más, el Nick, el user y el host.
$this->Ex[1] PRIVMSG: el comando.
$this->Ex[2] #bl4ckp0rtal : el canal en los mensajes privados saldrá el nombre de nuestro bot y no el canal…
$this->Ex[3,4,5,etc..] :palabra1 palabar2 etc: Las considero un conjunto pero en realidad en el explode las estamos separando.
Ese es el formato básico que tendrá un mensaje que nos envíen por medio de un canal. Aconsejo miremos el log frecuentemente para ver los cambios entre un mensaje un cambio de poderes (MODE) , una expulsión (KICK) un ban, etc.
Con esto nuestro bot ya es capaz de entrar a nuestro canal y registrar la conversación, pero aun tiene muchas carencias, la más importante es el PING.
El servidor nos enviará cada X tiempo un comando PING seguido de un código al cual deberemos responder PONG y el mismo código. Así que procederemos con nuestra obra:


if(strlen(strstr($data,'PING :'))>0) //Jugando al Ping Pong
{
$pong = str_replace('PING','PONG',$data);
$this->send($pong);
} else if (strlen(strstr($data,'for Open Proxies'))>0)
{//Si acabó de entrar a deepspace o nos echan del canal conectamos
$this->send('JOIN', $config['channel']);
$this->send('IDENTIFY', $config['pass']);
}

?>
Lo que hacemos es básicamente buscar la palabra PING, el strlen() es por el caso de que el resultado de 0 y así no evaluaría como FALSE no es para nada necesario en este caso pero me gusta tener buenas costumbres de programación, así que solo lo remplazamos por PONG y lo enviamos.
También agregué un else if con el último data que envía mi servidor para saber que ya terminó de recibir todo los data (me vi obligado a ello porque sinó no hacia el JOIN correctamente), así que solo hemos de entrar a nuestro servidor IRC con el bot y ver cuál es el ultimo data que envía.
En mi caso:
:opsb2!opsb2@stats.deepspace.org NOTICE botiboti :Your Host is being Scanned for Open Proxies
Entonces solo nos queda entrar al canal e identificar el nick.

$index[1][4]. Función send()


Ahora voy a hacer un pequeño salto a la función send() para que podamos entender más claramente el código que tenemos en las manos y sobretodo el código que nos queda.
El formato al enviar datos a send es: send($comando, [$mensaje]), donde el mensaje es un valor opcional.


function send($cmd, $msg=null) // Funcion para enviar comandos
{
if($msg == null)
{
fputs($this->socket, $cmd."\r\n");
echo ''.$cmd.'
'
;
} else {
fputs($this->socket, $cmd.' '.$msg."\r\n");
echo ''.$cmd.' '.$msg.'
';
}
}
?>

Usamos la función fputs($conexion, $mensaje a enviar) (info http://es2.php.net/manual/en/function.fputs.php). El \r y \n es para indicar a IRC que se acabó el comando (es como enviar un enter)
No hay mucho más que explicar, pero creo que ahora se hace más claro el código.


$index[2][0] Dándole un cerebro al bot


$index[2][1] Función main(), evaluando y tomando decisiones.

Quiero aclarar que esta parte del code (de la versión 1.1.5) está pendiente de ser reescrita, funciona perfectamente pero da una sensación abstracta y está poco organizada, pero se arreglará para la versión 1.2.0 y muy posiblemente editaré estos puntos para que el manual sea aún más claro y eficaz.

if(preg_match('/^:+'.$config['owner'].'/',$data)) //solo si es Owner
{
unset($arg);//si el comando tiene argumentos los metemos en $ar
for($i = 4; $i <= count($this->ex)-1; $i++) {$arg = $arg.' '.$this->ex[$i]; }

$command = str_replace(array(chr(10), chr(13)), '', $this->ex[3]);
$arg = str_replace(array(chr(10), chr(13)), '', $arg);

?>
Con el if simplemente nos aseguramos que el que nos envía los comandos es el Owner.
Borramos la variable argumentos y el for siguiente es un proceso lógico.
Lo que hace es a partir del 4to valor del array y mientras $i sea menor o igual que la totalidad de valores -1 (el -1 es porque el primer valor es 0 y no 1) agregue ese valor a la variable $arg, así podríamos enviar mensajes con el comando .say por ejemplo.
Asignamos el $this->ex[3] al command, si tenemos dudas con esto revisemos varias veces la cadena $data y no olvidemos que la primera parte es 0 y no 1
Ahora quitamos \r y \n a $command y $arg, dicen que es recomendable, no e probado que pasa si no se quitan, si tenéis curiosidad probad y comentadme…

$index[2][1] Primeras palabras del bot
A partir de aquí empiezan los comandos, voy a poner los más básicos, porque los demás es cuestión de probarlo y ver que formato tiene el $data y realizar las comprobaciones necesarias



$index[2][2] Primers palabras del bot

A partir de aquí empiezan los comandos, voy a poner los más básicos, porque los demás es cuestión de probarlo y ver que formato tiene el $data y realizar las comprobaciones necesarias


if($command == ':.q')
{
if($arg) { $this->send('QUIT', $arg); } else { $this->send('QUIT', 'Bye!'); } // QUIT
$on = 0;
}else if($command == ':.join' && isset($this->ex[4])) {
for($i = 4; $i <= count($this->ex)-1; $i++ ) { $this->send('JOIN', $this->ex[$i]); } // JOIN
}else if($command == ':.leave') { $this->send('PART', $this->ex[2]); // LEAVE
?>


La comprobación la hacemos con if y no switch por el simple hecho de poder agregar varias condiciones, los ‘:’ del principio es porque no merece la pena una línea para quitar los ‘:’, todos estos comandos se le indican al bot por el canal y no pro privado.
Como podemos ver todo se basa en el comando SEND y la sintaxis correcta del $data, para salir enviamos un QUIT, el argumento es un mensaje opcional que si no se pone se envía Bye!, el $on=0 es para salir del while indicando que se va a cerrar la conexión.
El Join conecta con todos los canales que le pasemos y el LEAVE sale del canal en el que mandamos la acción.
}else if($this->ex[2] == $config['nick'] && isset($this->ex[3])) {
$this->ex[3] = str_replace(':','',$this->ex[3]);
$this->send('PRIVMSG '.$this->ex[3], $arg); // SAY - ONLY PRIVATE
?>


Este comando es un tanto más especial y es la base para la versión 1.2.0, comprueba que en vez de enviarse a un canal se envíe a él (es decir un mensaje privado) y comprueba que se le haya dado valor a $this->ex[3] (que es donde indicaremos el canal), si estas condiciones se cumplen substituye los ‘:’ por nada y envía un PRIVMSG al canal con el texto que hemos asignado.

$index[2][3] Primeros brotes de autonomía.

}else if ($this->ex[1] == 'KICK' && $this->ex[3] == $config['nick']) { //Kick? I Rejoin!
$this->send('JOIN', $this->ex[2]);
}
?>
Esta parte se encarga de detectar que ha sido kickeado y en caso de ser así entrar otra vez al canal.
Esta parte se puede configurar para que solo lo haga en los canales de “confianza” (los de $config), en mi caso lo he dejado en todos.

$index[2][4] Feed RSS.

Ahora vamos a ver su función más importante hasta el momento, .rss
En el mismo if que venimos modificando hace rato agregamos

}else if($command == ':.rss') { $this->FeedRss($this->ex[2]); //Show feed
?>

Y vamos a crear la función

function FeedRss($chann)
{
$feedurl='http://feeds.feedburner.com/Bl4ckp0rtal?format=xml';
$raw = file_get_contents($feedurl);
$rawfeed = str_replace('feedburner:origLink','origlink',$raw);
$xml = new SimpleXMLElement($rawfeed);
foreach($xml->channel->item as $item)
{
$this->send('PRIVMSG '.$chann, $item->title.' '.$item->origlink);
}
}
?>


Como requerimiento tenemos el $chann, para saber el canal.
En $feedurl guardamos la url del feed.
En $raw descargamos el código del feed en xml
Substituimos feedburner:origLink por origlink (sino el php da problemas al trabajar con un ítem con : en el nombre.
Ahora solo resta mostrarlos, el raw nos devuelve 5 items así que no hará falta limitar el bucle. (no hagan spam ¬¬”)

Usamos la librería SimpleXMLElements (info: http://es2.php.net/manual/en/book.simplexml.php), a mi parecer está muy pobremente explicada, pero con algo de maña, estudiando el code y algo de tutos en internet, entendemos lo siguiente:
El xml es algo asi

Bl4ck-P0rtal
http://www.bl4ck-p0rtal.org/foro/index.php
…bla bla bla…
<ítem>rss1link rss (no el original)
…blab la bla…

<ítem...
pd: la estructura del feed puede variar según el servicio pero suele ser similar,esta es de feed burner

y así 5 veces
Las partes que nos interesa son title y link y son las que usamos precisamente en el code, y como vemos están dentro de <ítem>

$index[2][5] Cerrándolo todo

Para finalizar cerramos todos los if sueltos y ponemos esto

fclose($this->socket);
?>
La línea antes de cerrar el while para que cierre la conexión.

$index[2][6] todo el code


El código entero se puede encontrar aqui: http://www.bl4ck-p0rtal.org/foro/index.php?topic=8212.0

no lo publico porque vamos a crear un post demasiado largo...


$index[3][0] Final


$index[3][1] Puteadas:

- A Microsoft Office por pasarse por el forro el formato de mis codes
- A todos esos lamos que se creen lo que no son por hacer cosas que mi hermana de 12 años hace mejor y luego se ocultan tras una pared para que nadie lo sepa ;)

$index[3][2] Gr33ts:

- A todo los users y administración de Bl4ck-P0rtal.org que siempre me enseñan algo nuevo
- A aquellos de indetectables que se nos meten en el IRC a hablar a ratos ;)
- A Leesiem y Frozenfew por su interés en el code y a este ultimo por su ayuda en python (gracias bro ;) )


Nax



Multiplicación y división con decimales

Si bien ayer expuse un conversor de Hexadecimal a decimal, el objetivo final no es más que un conversor de Decimal a Hexadecimal.
Dicho objetivo no se nos plantea tan complicado usando cualquier lenguaje de programación, pero, como todos sabemos, Batch no es un lenguaje de programación y esto nos trae ciertos problemas, los más dignos de destacar creo que son la inexistencia de la función Len y la discapacidad de Batch frente a operaciones matemáticas con decimales.

Si señores, leen bien, batch es incapaz de sumar dos números decimales provocando el error tan conocido de: ' Falta Operador '.
Para solucionar esto, los programadores hemos creado códigos que se adaptan a la necesidad del proyecto final. E encontrado varios códigos en la red sobre Multiplicaciones y Divisiones con decimales en batch (que son operaciones necesarias para convertir números decimales a hexadecimales) pero como ninguno de ellos me acababa de convencer (o bien la lógica de programación era muy confusa, o simplemente no daba el resultado esperado, decidí crear mis dos propias funciones que pasaré a explicar a continuación:

Multiplicación con decimales



Se me pasó por la cabeza crear un code que cumpliera con la multiplicación con decimales en los 2 niveles (nivel 1: 2,12*2 nivel 2: 2,12*2,1) el caso es que tras pensar un rato no llegué a una conclusión lógica de como efectuar una operación de nivel 2 y como no era de vital necesidad para mi objetivo me decanté por multiplicaciones de nivel 1.

Teniendo como ejemplo: 2,20*6, el proceso empieza por separar las 2 partes de la variable con decimales a partir de la ',' (part1=2 part2=20. Esas dos partes se multiplican por el multiplicador (2*6 y 20*6).
A la segunda parte se le corre la coma según el número de decimales (en este caso 1,20), para ello hace falta separar la variable en dos partes mas (p1 y p2) donde la primera parte es la parte entera y la segunda la parte decimal.
Para finalizar se suma la parte 1 de la segunda separación (p1) a la parte 1 de la primera (parte1), dándonos como resultado 13,2.

División con Decimales



Para la división con decimales solo decir que el método me sorprendió y no es originalmente mío (lo encontré en la red no recuerdo donde...), simplemente intenté codearlo de una forma más clara y de acuerdo a mis necesidades.

El proceso es más sencillo y repetitivo, empezamos dividiendo el dividendo por el divisor y, como batch solo devuelve enteros, buscamos el resto. Con esta acción ya tenemos la parte entera, solo nos falta la decimal.

Para la parte decimal empezamos comprobando que el resto no sea 0, después de hacer eso solo nos encargamos de dividir el resto anterior (agregando un al final 0) para obtener el decimal y de buscar el MOD (resto) del resto anterior (agregando también un 0) para obtener el siguiente decimal, y así hasta que de 0.

Pueden hacer la comprobación con este mismo ejemplo: 1711*16 = 106,9375

Y para terminar por hoy (el convertidor decimal a hexadecimal otro día :p) dejo ambos códigos para análisis, recuerdo que pueden encontrarlos también en Bl4ck-P0rtal.org


Multiplicación.bat
@echo off
:: call :decimal_multi numero_decimal numero_entero
:: devuelve %multi%

:decimal_multi
setlocal
set num1=%1
set num2=%2

for /f "tokens=1,2 delims=." %%a in ("%num1%") do (
call :len %%b
set /a part1=%%a*%num2%
set /a part2=%%b*%num2%
)

call set p2=%%part2:~-%long%%%
set minus=%long%
call :len %part2%
set /a minus=%long%-%minus%
call set p1=%%part2:~0,%minus%%%

set /a suma=%p1%+%part1%
endlocal && set multi=%suma%.%p2% && goto :eof

:len
set len=%1
set long=0
:_loop
call set var=%%len:~%long%,1%%
if not defined var (goto :eof)
set /a long+=1
goto _loop


División.bat

@echo off
:: call :decimal_division dividendo divisor
:: devuelve: %division%

:decimal_division
setlocal
set dividendo=%1
set divisor=%2
set decimales=0

set /a "entero=%dividendo%/%divisor%"
set /a "resto0=%dividendo%%%%divisor%"

:div_decimal
if [!resto%decimales%!]==[0] goto div_fin
set /a sig=%decimales%+1
set /a decimal%decimales%=!resto%decimales%!0/%divisor%
set /a resto%sig%=!resto%decimales%!0%%%divisor%
set /a "decimales+=1"
goto div_decimal

:div_fin
for /l %%a in (0,1,%decimales%) do (set final=!final!!decimal%%a!)
endlocal && set division=%entero%.%final% && goto:eof

Hexadecimal To Decimal Converter

Como primer proyecto pensé en exponer algún que otro trabajo, pero como algunos me van a pegar si vuelvo a poner la v1 o la v2 del SNAKX, el juego en ActionScript o algún otro code que haya quedado en el olvido, prefiero presentar un sencillo trabajo en Batch.

La idea de realizar el code fue que se necesitaba un código para el S.C.O.T Team que consistiera en pasar valores decimales a Hexadecimales y como a mí me gusta ir al revés de la situación creé un code para pasar Hexadecimales a Decimales :P

Con el tiempo se van a ir dando cuenta que mi especialidad no es el diseño (es más, lo detesto y soy totalmente negado a ello...) así que mis programas consisten en una interfaz muy sencilla (o ninguna interfaz, como es el caso) y un código estructurado.



En este artículo voy a explicar el procedimiento que se sigue para pasar de un valor Hexadecimal a un valor Decimal.

Primeramente hace falta saber que un número Hexadecimal está en y un número Decimal en Base 10.

Entonces, primeramente necesitamos la longitud del texto, para ello llamamos a la función :Len, que nos retornará la longitud en la variable %long%.
A continuación separaremos cada digito para poder trabajar con él y lo guardaremos en una simulación de array que llamaremos digit_X (siendo X el valor numérico de la posición del array).
Aprovecharemos el mismo bucle para hacer la substitución de caracteres, siendo A=10 y F=16

Una vez finalizada la etapa de separación y substitución, nos introducimos en otro bucle (la razón de que no se haga todo en el mismo bucle es porque necesitamos todas las variables definidas para trabajar con ellas) en el cual aremos los cálculos apropiados.

La regla para convertir un valor hexadecimal a decimal dice que hemos de tomar los números de derecha a izquierda, multiplicarlos por su base elevada a n+1 y sumarlos.

Ejemplo con el valor '2A'

2(16^1)+A(16^0) = 2*16 + 10*1 = 32+10 = 42


Entonces hacemos exactamente eso en el último for, la única curiosidad es la función :Potencia que se encarga de multiplicar el número a su potencia

Syntaxis: call :potencia indice exponente


Finalmente mostramos el valor en hexadecimal y su conversión a decimal


A continuación os dejo el code para vuestra valoración:

@echo off
@title Hexadecimal To Decimal
SETLOCAL ENABLEDELAYEDEXPANSION
:ini
cls
set decimal=0
set /p "hexa=numero hexadecimal>>"
if not defined hexa goto ini
call :len %hexa%
set /a long+=1

for /l %%a in (1,1,%long%) do (
set digit_%%a=!hexa:~-%%a,1!
set cnt=9

for %%b in (A,B,C,D,E,F) do (
set /a cnt+=1
call set digit_%%a=!digit_%%a:%%b=%%cnt%%!)
)


for /l %%a in (1,1,%long%) do (
set /a exponente=%%a-1
call :potencia 16 !exponente!
set /a digit_%%a=!digit_%%a!*!potencia!
set /a decimal=!digit_%%a!+!decimal!
)

echo Hex: !hexa! -^> Dec: !decimal!
pause>nul
goto ini


:potencia
if %2==1 (set potencia=%1 & goto :eof)
if %2==0 (set potencia=1 & goto :eof)

set "potencia=%1"
for /l %%a in (2,1,%2) do (set /a potencia*=%1)
goto :eof



:len
set len=%1
set long=0
:_loop
call set var=%%len:~%long%,1%%
if not defined var (set /a long-=1 && goto :eof)
set /a long+=1
goto _loop

Apertura de puertas

Si bien no estaba seguro de que la creación de un blog me diera más que problemas, hoy e tenido un tiempo pos-estrés en el cual llegué a la conclusión de que un blog, si mas no, me ayudaría a centrarme y conseguir ciertos objetivos definidos en a lo que programación refiere.

El nombre del blog es "Syntax Error", supongo que a aquellos programadores con cierta experiencia encima no hace falta decirles el porqué, todos hemos sufrido antes o después, más o menos, aquellos fatídicos errores que tanto nos frustraron y al final resultaron ser un ';' o un paréntesis mal cerrado.

El blog en sí tiene como primer objetivo presentar mis progresos en los diferentes proyectos de programación, pero también proyectos a nivel de foro o equipos.

El aspecto de la web irá cambiando, así como los gadgets hasta que lo crea conveniente :p

mis salu2
nax