Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - ~

#11
Programar el puerto paralelo en Windows

Descargar lpthandler.tar

Solo necesitamos conectar un LED entre el pin 9 y el 22 del paralelo.

O como muestra el esquema, entre cualquiera de los pines anaranjados (los pines de datos) y cualquiera de los pines grises (pines de polo a Tierra, GND). Tenemos un total de 16 de esos pines, 2 pines por bit de datos para poder conectar las 2 patas de un LED u otro dispositivo.

Asegurarse de poner el LED en la polaridad correcta, o darle vuelta, o simplemente no va a dejar pasar la electricidad y no va a encender.


Uso de este programa para encender todos los 8 LEDS:
lpthandler.exe 3bc 11111111

  o sino el puerto 378
lpthandler.exe 378 11111111

  o sino el puerto 278
lpthandler.exe 278 11111111


Uso de este programa para apagar todos los 8 LEDS:
lpthandler.exe 3bc 00000000

  o sino el puerto 378
lpthandler.exe 378 00000000

  o sino el puerto 278
lpthandler.exe 278 00000000


Cada uno de los 8 bits a escribir debe ser un 1 o 0.
Un 0 apaga y un 1 enciende.



/*
En resumen solo necesitamos:

 Out32(Direccion_Base_Puerto_Paralelo+2, 0);          //Resetear Puerto de Control
 Out32(Direccion_Base_Puerto_Paralelo,   0xFF-0x00);  //Escribir el Puerto de Datos
*/



//Aquí, la Direccion_Base_Puerto_Paralelo
//puede ser:
//          0x3BC -- LPT1
//          0x378 -- LPT1
//          0x278 -- LPT2
///

//Necesitamos resetear el Puerto de Control escribiéndole un 0
//para configurar sus opciones, controladas por cada uno de
//sus bits:
///
 Out32(Direccion_Base_Puerto_Paralelo+2, 0);

//Enviamos un valor entre 0 y 255 al puerto de Datos:
///
 Out32(Direccion_Base_Puerto_Paralelo,   0xFF-0x00);


Por si no se entiende el código, se puede ver cómo se escribió en tiempo real, carácter por carácter como en la programación original:

>> Ver Tutorial Animado de Código de lpthandler.c <<





Cita de: ~ en  7 Abril 2016, 17:35 PMLo primero son los binarios y el código fuente del driver de acceso general a bajo nivel:

inpout32_source_and_bins.zip [Mirror 1]

inpout32_source_and_bins.zip [Mirror 2]


Después necesitamos saber qué direcciones de I/O tiene el puerto paralelo. Los puertos de I/O son como direcciones de memoria que van desde 0 hasta 65535. Cada una de esas posiciones podemos enviar 1, 2 o 4 bytes, o nosotros podemos recibir 1, 2 o 4 bytes. Por ahora solo vamos a enviar 1 byte a la vez.



El LPT1 está en el puerto (0x378, 378h)(888 decimal) o (0x3BC, 3BCh)(956 decimal).

El LPT2 está en el puerto (0x278, 278h)(632 decimal).

El LPT3 está en el puerto (0x3BC, 3BCh)(956 decimal).

El puerto paralelo es un periférico de 8 bits, así que usa 8 pines de datos para representar los 8 bits de cada byte (ya que usa datos y señales en paralelo, simultáneos), y esos son los pines que manipulamos con encendido o apagado cada vez que escribimos, por ejemplo, al puerto 0x378 (Los Pines Anaranjados, del 2 al 9):





Conector Hembra, en la Tarjeta Madre:





Ahora necesitamos usar void _stdcall Out32(short PortAddress, short data), que viene del driver inpout32.dll y hwinterface.sys.

Algo como esto:
Out32(378h, 255-0);





El código completo es el siguiente:
//NOTE: Compile with GCC under MinGW.
//
// gcc lpthandler.c -o lpthandler.exe
//
//Usage:
// lpthandler.exe LPT_Port Byte_Bit_Data
//
// LPT_Port:
//  - can be 3bc, 378 or 278
//
// Byte_Bit_Data:
//  - can range from 00000000 to 11111111 (written like that, in binary).
//    Every bit controls one of 8 LEDs.
//
// LEDs are connected between DATA and GROUND lines.
// DATA to GROUND lines are connected like this, for pins:
//
// DATA is + and GROUND is -
//
//  2-18
//  3-19
//  4-20
//  5-21
//  6-22
//  7-23
//  8-24
//  9-25
//
// Remember to set the parallel ports as Standard/Normal in the BIOS
// to ensure proper working of the basics with this program.
///

#include <stdio.h>
#include <windows.h>

typedef short _stdcall (*_Out32)(short portaddr, short value);
typedef short _stdcall (*_Inp32)(short portaddr);

int main(int argc, char *argv[])
{
HINSTANCE INPOUT32_DLL_Handle;
_Inp32 Inp32;
_Out32 Out32;


//Load the inpout32.dll library. It's also associated
//with hwinterface.sys, but it should open it by itself:
///
 INPOUT32_DLL_Handle=LoadLibrary("inpout32.dll");
 if(INPOUT32_DLL_Handle == NULL)
 {
  printf("LoadLibrary failed for inpout32.dll...\n\n");
  return -1;
 }


//Get access to the Out32/Inp32 functions from inpout32.dll:
///
 Out32 = (_Out32)GetProcAddress(INPOUT32_DLL_Handle, "Out32");
 Inp32 = (_Inp32)GetProcAddress(INPOUT32_DLL_Handle, "Inp32");

//NOTE: The following two lines are the actual logic of the program
//      and are at the top of importance and the program's key logic.
//      Everything else could be considered API noise:

//Configure the CONTROL Port with a 0 to sanitize the port state:
///
 Out32(strtol(argv[1],NULL,16)+2, 0);  //Bit 0: Strobe
                                       //Bit 1: Auto Line Feed
                                       //Bit 2: Initialize Printer
                                       //Bit 3: Select Printer
                                       //Bit 4: Enable IRQ Via Ack Line
                                       //Bit 5: Enable Bi-Directional Port
                                       //Bit 6: Unused
                                       //Bit 7: Unused



//Write the Data port with the desired 8-bit value:
///
 Out32(strtol(argv[1],NULL,16), strtol(argv[2],NULL,2));


//Unload our inpout32.dll library:
///
 FreeLibrary(INPOUT32_DLL_Handle);

return 0;
}

#12
filesopen Espera_aleatoria_minima Espera_aleatoria_maxima Nombre_base_de_datos Numero_de_fila_de_configuracion

Aquí tengo un programa de consola que escribí, que abre automáticamente y al azar archivos locales o URLs tomadas de una base de datos SQLite3 la cual maneja por sí misma usando la librería de Amalgamación de SQLite3.

Está completamente escrita en C y funciona bajo Windows (aunque tal vez pueda funcionar bajo Wine).

Aquí está el binario compilado:
FILESOPEN.EXE

Aquí se puede ver y aprender a escribir un programa en C básico para manejar una base de datos SQLite3:
>> Grabación de Texto para el Visor Aleatorio de Archivos y URLs <<

La estructura documentada y el uso de la base de datos está contenido en dicha grabación de la escritura del código.

Se puede hacer una prueba del funcionamiento con la siguiente base de datos que contiene más de 2 millones de nombres de dominio provenientes de la lista diaria de 1 millón de sitios más importantes de Alexa:
domains_alexaranks.db

Para correr el programa, solo se necesita el siguiente comando:

filesopen 1 1 domains_alexaranks.db 1




Aquí está el código principal (compilado bajo MinGW):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "SQLite3-Amalgamation-3.12.0/sqlite3.h"
#include "SQLite3-Amalgamation-3.12.0/sqlite3.c"
#include "SQLite3-Amalgamation-3.12.0/sqlite3ext.h"
#include <windows.h>

const char sqlite3_version[] = SQLITE_VERSION;

//Set default values for the number of table rows and for the current column
//this last one will be selected at random:
///
int SQLite3_Row_Ctr=1;
int SQLite3_Current_Row=1;

sqlite3      *SQLite3_DB_Obj;
sqlite3_stmt *SQLite3_State;
int           SQLite3_DB_Res_Handle;
char         *SQL_String;
char         *SQLite3_ErrorMsg=NULL;
char         *SQLite3_zTail_String;



//These are the default minimum and maximum number of minutes to wait
//before trying to open other file/directory entry:
///
int minwait=1;
int maxwait=1;


long minmax_rand(long min, long max)
{
return rand()%((max+1) - min) + min;
}


char *config_tablename;
char *config_datarowname;
char *config_idrowname;
char *config_fileprotocol;

static int SQLite3_Callback_config(void *NotUsed, int argc, char **argv, char **azColName)
{
config_tablename=malloc(512);
config_datarowname=malloc(512);
config_idrowname=malloc(512);
config_fileprotocol=malloc(512);

sprintf(config_tablename,"%s",argv[0]);
sprintf(config_datarowname,"%s",argv[1]);
sprintf(config_idrowname,"%s",argv[2]);
sprintf(config_fileprotocol,"%s",argv[3]);


printf("Getting database configuration...\n");
printf("tablename=%s\ndatarowname=%s\nidrowname=%s\nfileprotocol=%s\n\n", config_tablename, config_datarowname, config_idrowname, config_fileprotocol);


return 0;
}


static int SQLite3_Callback(void *NotUsed, int argc, char **argv, char **azColName)
{
int x=0;
int requiredSize=0;
int   openstrlen=0; char *cmd=NULL;
char *cmd2=NULL;
char *openstr="open";
char *openstrW;
char *explorerstr="C:\\WINDOWS\\explorer.exe";
char *explorerstrW;

int   execres=0;

openstrW=malloc(131072);
explorerstrW=malloc(131072);
cmd=malloc(131072);
cmd2=malloc(131072);

MultiByteToWideChar(
                     (UINT)CP_UTF8,
                     (DWORD)0,
                     (LPCSTR)explorerstr,
                     (int)-1,
                     (LPWSTR)explorerstrW,
                     (int)131072
                    );

MultiByteToWideChar(
                     (UINT)CP_UTF8,
                     (DWORD)0,
                     (LPCSTR)openstr,
                     (int)-1,
                     (LPWSTR)openstrW,
                     (int)131072
                    );




for(x=0; x<argc; x++)
{
  snprintf(cmd,131072,"\"%s%s\"",config_fileprotocol,argv[x]);

/*
int MultiByteToWideChar(
  _In_      UINT   CodePage,
  _In_      DWORD  dwFlags,
  _In_      LPCSTR lpMultiByteStr,
  _In_      int    cbMultiByte,
  _Out_opt_ LPWSTR lpWideCharStr,
  _In_      int    cchWideChar
);
*/
  MultiByteToWideChar(
                      (UINT)CP_UTF8,
                      (DWORD)0,
                      (LPCSTR)cmd,
                      (int)-1,
                      (LPWSTR)cmd2,
                      (int)131072
                     );

  printf("%ld: %s\n\n", SQLite3_Current_Row, cmd);

/*
HINSTANCE ShellExecute(
  _In_opt_ HWND    hwnd,
  _In_opt_ LPCTSTR lpOperation,
  _In_     LPCTSTR lpFile,
  _In_opt_ LPCTSTR lpParameters,
  _In_opt_ LPCTSTR lpDirectory,
  _In_     INT     nShowCmd
);

*/

  execres=(int)ShellExecuteW(
                (HWND)0,
                (LPCWSTR)openstrW,
                (LPCWSTR)explorerstrW,
                (LPCWSTR)cmd2,
                (LPCWSTR)NULL,
                (INT)SW_SHOWNORMAL
               );


  switch(execres)
  {
   case 0:
   printf("exec: 0");
   break;

   case ERROR_BAD_FORMAT:
    printf("exec: ERROR_BAD_FORMAT");
   break;

   case SE_ERR_ACCESSDENIED:
    printf("exec: SE_ERR_ACCESSDENIED");
   break;

   case SE_ERR_ASSOCINCOMPLETE:
    printf("exec: SE_ERR_ASSOCINCOMPLETE");
   break;

   case SE_ERR_DDEBUSY:
    printf("exec: SE_ERR_DDEBUSY");
   break;

   case SE_ERR_DDEFAIL:
    printf("exec: SE_ERR_DDEFAIL");
   break;

   case SE_ERR_DDETIMEOUT:
    printf("exec: SE_ERR_DDETIMEOUT");
   break;

   case SE_ERR_DLLNOTFOUND:
    printf("exec: SE_ERR_DLLNOTFOUND");
   break;

   case SE_ERR_FNF:
    printf("exec: SE_ERR_FNF");
   break;

   case SE_ERR_NOASSOC:
    printf("exec: SE_ERR_NOASSOC");
   break;

   case SE_ERR_OOM:
    printf("exec: SE_ERR_OOM");
   break;

   case SE_ERR_SHARE:
    printf("exec: SE_ERR_SHARE");
   break;
  }


  sleep(60*(int)minmax_rand(minwait,maxwait));
}

free(cmd);
free(cmd2);
free(openstrW);
free(explorerstrW);


return 0;
}


static int SQLite3_Callback2(void *NotUsed, int argc, char **argv, char **azColName)
{
SQLite3_Row_Ctr=atol(argv[0]);
return SQLite3_Row_Ctr;
}



void clear_state()
{
//NOTE: This is for the good practice of not leaving
//      freeing of resources or other default operations
//      at their default state but accelerate and ensure
//      the global sanity of the environment and the program
//      by specifying every operation exactly as we want it:
///
sqlite3_finalize(SQLite3_State);
sqlite3_close(SQLite3_DB_Obj);
free(SQL_String);

}






int main(int argc, char *argv[])
{
atexit(clear_state);
SQL_String=malloc(4096);



if(argc>=5)
{
  if(!(minwait=atoi(argv[1])))minwait=1;
  if(!(maxwait=atoi(argv[2])))maxwait=1;
}
  else
  {
   printf("Usage: filesopen min_minutes max_minutes SQLITE3_Database_Path Database_Config_ID\n\n");
   return -2;
  }


//Open the database and see if it was successful. If not, just exit the program:
///
  SQLite3_DB_Res_Handle=sqlite3_open(argv[3], &SQLite3_DB_Obj);

  if(SQLite3_DB_Res_Handle!=SQLITE_OK)
  {
   printf("Error opening database\n\n");
   return -1;
  }


  //Get the configuration of the database to use the proper table and field names,
  //as well as basic formatting for the data:
  ///
   snprintf(SQL_String, 4096, "SELECT tablename,datarowname,idrowname,fileprotocol FROM config WHERE configid=%s LIMIT 1", argv[4]);
   SQLite3_DB_Res_Handle=sqlite3_exec(
                                      SQLite3_DB_Obj,
                                      SQL_String,
                                      SQLite3_Callback_config,
                                      SQLite3_zTail_String,
                                      &SQLite3_ErrorMsg
                                     );







//Get all columns for the first time to count them.
//Its callback will return the count in SQLite3_Row_Ctr:
///
  snprintf(SQL_String, 4096, "SELECT COALESCE(MAX(%s)+1, 0) FROM %s", config_idrowname, config_tablename);
  SQLite3_DB_Res_Handle=sqlite3_exec(
                                     SQLite3_DB_Obj,
                                     SQL_String,
                                     SQLite3_Callback2,
                                     SQLite3_zTail_String,
                                     &SQLite3_ErrorMsg
                                    );

printf("Cycling through %ld files...\n", SQLite3_Row_Ctr);


while(1)
{
  //Go to next row (selected randomly):
  ///
   SQLite3_Current_Row=minmax_rand(1, SQLite3_Row_Ctr);


  //Get random files to open:
  ///
   snprintf(SQL_String, 4096, "SELECT %s FROM %s WHERE %s=%ld LIMIT 1", config_datarowname, config_tablename, config_idrowname, SQLite3_Current_Row);
   SQLite3_DB_Res_Handle=sqlite3_exec(
                                      SQLite3_DB_Obj,
                                      SQL_String,
                                      SQLite3_Callback,
                                      SQLite3_zTail_String,
                                      &SQLite3_ErrorMsg
                                     );


  //If there was a database error or fault, just end:
  ///
   if(SQLite3_ErrorMsg)return 0;
}


return 0;
}


#13
Criptografía / Re: Proteger par de claves RSA
29 Marzo 2016, 17:32 PM
Aplicar SHA3-512 a la contraseña y recalcularla cada vez que se desencripte para comparar. No almacenar ese hash ni la contrasea.
#14
Este es el libro "El Habla de Mi Tierra", que trata sobre el estudio del idioma Español en gran detalle y en todos sus aspectos.

Contiene 459 imágenes con resolución de 1,700px × 2,338px.

Citar El Habla de Mi Tierra.zip (401 MB)
MD5:345334d526b20da63c4607b231998673




En caso de que el link haya expirado, esta es la URL en la que mantengo actualizado y vigente los links de descarga en un momento dado:

Descargar El Habla de Mi Tierra; Rodolfo María Ragucci (Actualizado el 14 de Noviembre del 2014)







Dado lo raro que es encontrar ahora literatura de esta calidad y que necesitaba preservar mi ejemplar ya desgastado por el uso y por el tiempo (incluso antes de tenerlo yo, allá por los años 70/80).

Originalmente lo publiqué como imágenes JPG sueltas para poder ser vistas fácilmente sin descargar todo el paquete y sin consumir demasiados recursos del cliente y del servidor, y ahora he subido el ZIP con todas las imágenes en link anterior.
#15
Hace un par de meses comencé a descargar el torrent de Geocities (de 641 Gigabytes), a una velocidad máxima de 400 Kilobytes por segundo, después de varios intentos parciales anteriores por buscar sitios antiguos de Internet de los 90's y principios del 2000, especialmente sitios técnicos con información interesante, como los sitios de Geocities en SiliconValley.

Necesité 3 Terabytes (1 disco de 1 Terabyte para descargar el torrent y otro disco de 2 Terabytes para descomprimir y finalmente guardar los contenidos, con un tamaño de clúster de 512 bytes y compresión NTFS activada, para ahorrar el máximo espacio posible), y usando también una laptop Dual Core a 2.4 GHz y 2 GB de memoria. Este es realmente un ejercicio muy interesante para aprender a manipular, copiar, detectar errores de CR5/MD5/SHA, administrar una enorme cantidad de datos arbitrarios del mundo real, y cosas que realmente no son tan críticas como la necesidad de reducir el tamaño del archivo MFT en una partición NTFS (con algo como Clean Disk Security), entre otras cosas a descubrir con más tiempo de tener que manejar tantos datos.



Este es el link del torrent:
Código (magnet) [Seleccionar]
magnet:?xt=urn:btih:2DC18F47AFEE0307E138DAB3015EE7E5154766F6&dn=geocities.archiveteam.torrent&tr=udp%3a%2f%2ftracker.openbittorrent.com%3a80&tr=udp%3a%2f%2ftracker.publicbt.com%3a80&tr=udp%3a%2f%2ftracker.istole.it%3a80%2fannounce&tr=udp%3a%2f%2fopen.demonii.com%3a1337


Este es el link que he puesto para visualizar cómodamente el contenido:
http://geocities.archefire.org/

Y el historial de intentos y del procedimiento para ponerlo finalmente en disco:

Agregado el dominio geocities.archefire.org (¿Qué Tiene De Nuevo para Ofrecer?)

Descargando el Torrent de Geocities


Resulta que hay mucho contenido que se ve mal si se trata de acceder localmente porque usa muchas URLs absolutas, y otros casos en los que el contenido puede existir pero estar disperso entre los diferentes directorios del torrent, y son tan enormes que lo mejor es buscar y redirigir automáticamente con PHP.

Así que puse todo el contenido, archivo por archivo, con el extra de que se puede ver el contenido de cada directorio existente sin que index.html estorbe, que es algo que no es posible hacer con otros mirrors como Reocities u OOcities, y en consecuencia no es posible saber de la existencia de mucho contenido ocultado por index.html, pero que está superado en este mirror que creé para mi conveniencia de visualización, y también para alguien más que quisiera poder ver el respaldo de Geocities en su totalidad, con absolutamente todo lo que eso implica.

Es posible que  este mirror esté ocasionalmente offline porque está en un disco USB de 3.5", y si necesito reconfigurar algo (o ahorrar electricidad, o por otras razones), sería mejor usar un disco interno o uno externo pero de 2.5".
#16
http://www.iana.org/assignments/media-types/

La recomendación general para tipos de archivo no estándar y sin MIME Type, es simplemente analizar el formato en cuestión de dicho archivo, y asignarle el MIME Type que más se le acerque. En este caso, ese tipo sería simplemente text/plain, porque no contiene más que texto simple, independientemente de que sean datos del registro de Windows, un archivo de código de C/C++/Ensamblador, etc. Si el formato no se puede determinar o si se desea un manejo especial de una extensión, podemos usar simplemente application/octet-stream.

______________________________________________
______________________________________________
______________________________________________
______________________________________________
El MIME Type (Multipurpose Internet Mail Extensions), como su nombre lo dice, sirve principalmente para que sea manejado de formas específicas por una aplicación de Internet, como un navegador Web.

Por lo menos la instalación de Apache por defecto trata a los archivos .reg, y aparentemente por defecto también a archivos como .bat, .com y otros poco estandarizados o desconocidos, como de tipo text/plain.

Si definiéramos (en Apache) el MIME Type de los archivos .reg como text/plain, este se mostrará como texto plano Unicode o de otro tipo en el navegador mismo, ya que eso es exactamente lo que es. Pero si lo definiéramos como application/octet-stream o mejor aún, como application/force-download, el comportamiento normal es que el navegador muestre un diálogo de descarga para el archivo.

En realidad, lo que cuenta es el formato de archivo en sí, como en el caso de las imágenes, para las que el MIME Type puede hacer que se muestren como texto, como imagen, o que forcen su descarga, pero eso depende más de la aplicación en sí.


#17
Cita de: @drvymonkey en 15 Octubre 2013, 21:44 PM
Pues mira.. es uno de los mas ricos del planeta y Microsoft predomina el mercado de los PC's personales.. parece ser que funciona.. si tienes la habilidad de convencer a cualquier persona.. te haces rico :P
Me refiero a que no sirve de nada decir "¿para qué escribir código?".

El resto, todos son ricos en esa industria cuando pertenecen a esta. Bill Gates es de los más ricos simplemente porque aparte de tener habilidad indiscutible para los negocios, alguien tenía que empezar a darle relevancia a la PC, porque es de los primeros y el primero en popularizar GUIs consistentes, y creó productos del uso más masivo, y fáciles de usar.

Ahora el juego es muy diferente tomando en cuenta los recursos que se necesitan para suplir las expectativas de los usuarios, y de cuántos secretos industriales dependemos, que no es posible de dominar para un pequeño grupo ajeno a la industria misma (como nosotros) en menos de por lo menos 1 generación. Pero todavía se puede hacer mucho por el lado de la programación y la educación en base a aplicaciones graydes e importantes; aunque volverse rico no es tan fácil, tomando en cuenta que ahora existen programas tanto piratas como open source para virtualmente todas las tareas imaginables.
#18
Cita de: topomanuel en 15 Octubre 2013, 21:15 PM
Para que escribir códigos, si Gates es un genio pero de las finanzas y las inversiones... ese wey siendo solo un párvulo, fue capaz de enamorar a la gente de IBM y venderles un SO para sus maquinas que ni siquiera era de el en ese momento... jajajajaaaa... códigos...


Me encanta el sarcasmo... por eso admiro al Dr. House...
¿Y qué utilidad práctica tiene esto, que tampoco es exacto (sin código no hay dinero ni industria)?

Esto no resuelve ningún problema, ni es práctico.
#19
Cita de: topomanuel en 15 Octubre 2013, 20:38 PM
Ya saldrán los linuceros a decir que esa partida de monos deberían estar dirigidos por un gurú bien peludo como el mentado "Stallman"... jajajaaaaa...
Debería ser así para los proyectos en los que ha trabajado y que todos usamos, que son relevantes, aunque rara vez o prácticamente nunca explican las cosas desde un nivel principiante.

Aunque eso tampoco lo hacen los citados en este artículo, y nunca vamos a verlos enseñando las tecnologías cerradas de sus productos desde el código y todos sus trucos.

Cada vez hay más opciones y simplemente hay que tomar lo mejor, lo que más se aplica a nivel profesional en el mundo real.

La mejor opción para llegar ahí, después de estudiar y trabajar con gente de ese nivel, también open source, es buscar mentores para trabajar en agregar características en programas de código abierto. Pero esto requiere que uno sea experto en C, C++ y otros lenguajes compilables clásicos, que es en lo que están escritos la mayoría de programas, incluyendo los navegadores web.

Esa opción (buscar mentores no solo para saber qué cosas modificar de un proyecto grande para agregar características, sino para aprender trucos de alto nivel desde los fundamentos, y gratis, en Internet, sin tener que ir a universidades extremadamente caras y fuera del alcance del 99% de la población mundial) es casi imposible de encontarr de manera fácil hasta el día de hoy.

Y lo que se habla en este artículo es una ayuda más, pero no diferente a los muchos cursos genéricos que hay, que por más alto nivel que tengan, siguen siendo demasiado genéricos, demasiado desconectados de la enseñanza y la comprensión basada en los programas importantes del mundo real ya existentes (por ejemplo aprender a programar y aprender de tecnología web entendiendo el código de Mozilla Firefox mediante clases).

Irse por cursos con problemas inventados en lugar de problemas de comprensión y de desarrollo en programas es desperdicio de esfuerzo que se podría usar en lograr desarrollar los programas ya existentes y enseñar a los nuevos programadores (creando versiones/branches especiales de dichos programas para el aprendizaje, tal vez menos eficientes, pero no menos complejas y utilizables en el mundo real).
#20
Cita de: El Benjo en  4 Octubre 2013, 02:04 AM
jajajajajajajajajajajajajaja Es que no debemos perder el tiempo, Frodo. XD

Bueno, aprovecho para comentar un mito que según sé es falso, pero quisiera saber si alguno de ustedes ha escuchado de él. Se dice que en las aplicaciones de VB.net cuando uno coloca un if de la forma:

Código (vbnet) [Seleccionar]

If A = True And B = True Then

End If


Aunque la primera evaluación sea falsa se hace la segunda evaluación y por ello es mejor realizar un if anidado.

Yo sigo creyendo que es un mito, pero qué dicen ustedes?

No es cierto. Un código compilado que ejecutara todo el IF aunque este ya no cumpla una condición requerida sería extremadamente ineficiente. De hecho no es tan difícil programar a mano este tipo de optimización, y es más breve y hasta claro.

Por ejemplo para el código anterior sería más eficiente compilarlo así:
1. comparar A==TRUE
2. si es FALSE, terminar el IF en 6 (y no se ejecuta la siguiente condición)
3. comparar B==TRUE
4. si es FALSE, terminar el IF en 6

5. { Código dentro del IF }

6. terminar el IF



Que compilarlo así:
1. comparar A==TRUE
2. si es TRUE, seguir comparando en 3 (un salto inmediato poco inteligente)
3. comparar B==TRUE
4. si es TRUE, entrar en el IF en 6
5. ir a terminar el IF en 7

6 { Código dentro del IF }

7. terminar el IF



Son más comprobaciones ejecutadas sin razón cuando se sabe que si se usa AND y no se cumple no hay caso de seguir ejecutando, y requiere un salto incondicional como terminador del IF (en el segundo caso, que es más ineficiente). Y si el IF fuera mucho más complejo, la ejecución sería menos que óptima, y eso no sería aceptable en aplicaciones de grado industrial que tienen elementos mucho más complejos que esto.



Cita de: ivancea96 en  4 Octubre 2013, 17:04 PM
Hablando de C++:

En un IF con varias condiciones unidas por un AND (Ejemplo: "if(1 && 0);"), se leen en orden, y en el momento en que una sea falsa, acaba con el IF. Esto lo podemos ver fácilmente (¬¬ vagos) con un código como este:

Código (cpp) [Seleccionar]
#include <iostream>
bool asd(){
std::cout << "Hola";
return false;
}
int main () {
if(2==0 && asd());
system("pause>nul");
}


Compilado con MinGW*

Haced la prueba en VB, y los lenguajes que uséis, y así tenemos este hilo para saber que lenguajes leen todas las condiciones xD

Respecto a la pregunta original, Ikillnukes, el compilador lo que hace es compilar, no averiguar si las condiciones (excepto las del tipo "#if") son o no son verdaderas.
Eso depende de la comprobación y de la forma en la que se optimiza el código. Si por ejemplo hay valores constantes que siempre van a evaluar a verdadero o a falso, el compilador haría bien en eliminarlos, entre otras optimizaciones más complejas. Tener que comprobar todas las condiciones determinables en tiempo de compilación debería ser una optimización básica. También es necesario realizar otras comprobaciones para las demás optimizaciones y para eso se necesita algún nivel de evaluación del IF (el simple hecho de tener que compilarlo requiere eso).