CString Trim

Quienes programamos en MFC Visual C++ algunas veces hemos tenido que eliminar los espacios en blanco de una cadena y sucede que la clase CString no tenia una sola funcion trim, sino las funciones TrimLeft y TrimRight.

Nose por que diablos demoraron tanto (o no se dieron cuenta) en agregar esa funcioncita.

Lo que se hacia normalmente es:

m_sCadena.TrimLeft();

m_sCadena.TrimRight();

Esto ahora ha causado un problema de compatibilidad con las versiones anteriores y no creo que sea la unica.

Leer datos MySQL desde C++ sobre Linux

Resulta que algunas veces es necesario acceder desde C/C++ a MySQL, razones hay muchas…. el asunto es como hacerlo.

Antes de hacer cualquier cosa debemos instalar las librerías de desarrollo de MySQL:

sudo apt-get install libmysqlclient-dev

Todos los archivos que necesitaremos van a estar ubicados en /usr/include/mysql y /usr/lib/mysql , los parámetros para compilar un archivo simple es como sigue:

gcc archivo.cpp \
           -o archivo \
           -I/usr/include/mysql -L/usr/lib/mysql \
           -lmysqlclient -lstdc++ -lz

Una breve descripción de los parámetros:

  • -o (output) indica el nombre que va a tener el archivo de resultado
  • -I le dice al compilador que incluya una ruta adicional para los archivos de inclusión
  • -L le dice al enlazador que incluya una ruta adicional para los archivos de librería dependientes
  • -l (ele minuscula) le dice al enlazador que incluya la librería especificada
  • \ es el caracter que usamos en la linea de comando para ejecutar varias lineas como una sola expresión.

Escribí para ustedes un código de ejemplo, no es gran cosa pero les va a dar luces para sus proyectos:

//conexion.cpp
#include 
#include 
#include 
 
using namespace std;
 
int main(int argc, char *argv[])
{
    MYSQL mysql;
 
    mysql_init(&mysql);
    if (!mysql_real_connect(&mysql
		,"localhost"
		,"root"
		,""
		,"ciudades",0,NULL,0))
    {
        cerr<<"Horror ! : "
	    <

El resultado de la ejecución es:

ivancp@ubuntu$ ./conexion
01 AMAZONAS
02 ANCASH
03 APURIMAC
04 AREQUIPA
05 AYACUCHO
06 CAJAMARCA
07 CALLAO
08 CUSCO
09 HUANCAVELICA
10 HUANUCO
11 ICA
12 JUNIN
13 LA LIBERTAD
14 LAMBAYEQUE
15 LIMA
16 LORETO
17 MADRE DE DIOS
18 MOQUEGUA
19 PASCO
20 PIURA
21 PUNO
22 SAN MARTIN
23 TACNA
24 TUMBES
25 UCAYALI

Espero les sirva mucho!

SIAF GL sobre Linux

Es conocido por todos los que alguna vez pasaron por el sector publico que el Sistema Integrado de Administración Financiera (SIAF) es un software al que no podemos pasar por alto, a pesar de que esta hecho en Visual Fox y se presentan errores en el funcionamiento periódicamente. Pero nos guste o no tenemos que utilizarlo, de todas maneras el SIAF es la norma hecha Software.

Desde hace algunos meses vengo trabajando en la Oficina de Informática de la Municipalidad Provincial de Puno, y definitivamente tener funcionando el SIAF sobre un Servidor de Archivos Windows es vivir en zozobra.

Los virus, colgadas inesperadas, y innumerables pantallas azules indicando Error numero 0xADFD21244 y mas bla bla bla; me hicieron desechar el sistema operativo Windows del servidor y pasarme a Linux Fedora Core 3 con Samba para que los usuarios del SIAF no se den cuenta del cambio.

Cuando los residentes del SIAF o los del staff de soporte técnico venían a actualizarlo no sabían que hacer con el servidor, incluso preguntaban “¿Que Windows es éste?”

Desde aquel historico día, los problemas solo fueron del mismo SIAF ya no del sistema operativo. Aunque no esta muy difundido esto del Linux en las Instituciones Publicas del Perú, deberían tomarlo en cuenta, por que además de que ademas de ahorrar miles de dólares en licencias también se ahorran las molestias que causa Windows frecuentemente.

A todo esto, en las instituciones publicas es muy difícil implantar el software libre en los equipos usuario, por que ya están mentalizados en utilizar Word para sus documentos, Excel para sus hojas de calculo, por solo citar dos ejemplos. El software libre vive normalmente en el entorno académico, depende de nosotros que esto cambie.

Si desean asistencia en la instalacion de SIAF sobre Linux pueden escribir a ivancp [AT] latindevelopers.com

Los MVP’s

MVP Logo
Microsoft Most Valuable Professional (MVP) es una especie de galardon de reconocimiento a quienes destacan en el desarrollo y/o uso de aplicaciones Microsoft. Generalemente se encuentra a los MVP’s en los foros y comunidades de desarrollo.

Pueden encontrar mas al respecto en http://www.mvps.org/

Los MVP’s que a mi me interesan son los de Visual C++. Hay MVP’s de casi todas las aplicacioes de Microsoft.

MVP’s Visual C++:

Girish Bharadwaj http://www.gbvsoft.com

Rodrigo Corral http://rcorral.mvps.org

James Curran http://www.NovelTheory.Com

Ricardo González http://www.devsynergy.net/

Richard Grimes http://www.grimes.demon.co.uk

Alok Gupta http://www.thatsalok.com

Doug Harrison http://www.eluent.com

David Lowndes http://www.jddesign.co.uk/

Randy Charles Morin http://www.kbcafe.com/

Katy Mulvey http://www.mulveyfamily.com/~katy

Thomas Wai Ho Phan http://www.entersys.com/Twhphan.aspx

Tomas Restrepo http://www.winterdom.com/

Bliss Sloan http://www.ertin.com/sloan.html

Thomas Woelfer http://www.woelfer.com/

Coding Standards

Al empezar con esto de la programacion uno adopta una forma de escribir el codigo. Este codigo no siempre es bien visto por quienes tiene experiencia (como si se tratara de caligrafia).

No habia nada dicho al respecto de los estandares de codigo fuente, pero muchos se animaron a establecer estandares de «caligrafia» para el C/C++.

En este enlace pueden encontrar reglas que pueden seguir sin miedo para escribir sus programas en C/C++:

Coding Standards
http://www.possibility.com/Cpp/CppCodingStandard.html

GNU tiene sus propios estandares que hay que seguir para escribir codigo para GNU Linux. Se podria decir que es lo mismo, pero en este caso estas reglas estan hechas no solo para escribir codigo limpio sino tambien para que otros programadores entiendan lo que uno ha programado.

GNU Coding Standards
http://www.gnu.org/prep/standards/standards.html

Por mi parte puedo contarles que no me agrada mucho escribir las funciones de esta manera:

void
funcion (var1,var2)
int var1,
int var2
{
  //...
}

Por otro lado es mejor tener los corchetes bien acomodados para entender los bloques.

Prefiero que se vea asi:

int main(int argc, char *argv[])
{
	char str[80];
	while(cin.getline(str,80))
	{
		int len = strlen(str);
		cout<<endl;
		for(int i = 0 ; i < len ; i++)
		{
			cout<<ind(str[i],0,44);
		}
	}
	return 0;
}

que asi:

int main(int argc, char *argv[]){
	char str[80];
	while(cin.getline(str,80)){
		int len = strlen(str);
		cout<<endl;
		for(int i = 0 ; i < len ; i++)
		 cout<<find(str[i],0,44);
	}
	return 0;
}

Nuevo Articulo: Same Game

En una de esas encontré el problema del SameGame en la ACM. [Ver : http://acm.uva.es/p/v7/758.html]

Despues de resolverlo me animé a programar el juego en Visual C++ 6.0. Ya que hace mucho tiempo no programaba juegos y cosas asi para poder desestresarme. Espero que les guste.

Para poder resolver este problema utilicé un algoritmo de búsqueda recursiva simple, hace un tiempo atras (varios años) programé el juego de Bubble Puzzle ,con listas de listas y listas doblemente enlazadas, toda una complicación para aprobar el curso de Estructuras de Datos en el cual se eliminaban las bolitas de igual forma.

SameGame


SameGame.exe

El codigo fuente del juego lo pueden descargar de SameGame – Visual C++. Le hacen falta muchas mejoras, como por ejemlo: implementar la animación de la eliminación de los elementos, almacenar el score de los jugadores, mejorar la animación al estilo SameGame para linux, implementar una versión para linux, etc, etc.

Si alguien se anima a mejorarlo o ha encontrado un bug, puede enviarme un mail con las mejoras y volverlo a publicar.

Update:

Ahora pueden descargarse el juego compilado. (si presenta errores al momento de ejecutar envienme un mail)

Minesweeper – Busca minas

Minesweeper es uno de los cientos de problemas de la ACM, la idea es basicamente elaborar un programa que resuelva o simule ej juego del buscaminas. Pueden ver los detalles del problema en esta pagina: http://acm.uva.es/p/v101/10189.html

El problema planteado solamente tiene una entrada simple, pero pueda que la solución que estén elaborando no contemple todas las posibilidades. Para ello implementé un programita en c++ para generar entradas de ejemplo para el programa que estén desarrollando del tamaño que se indique, puede serles de mucha utilidad para testear sus programas.

#include <iostream.h>
int main(int argc, char* argv[])
{
    if(argc < 3)
    {
       cout<<"\nUso:\t"<<argv[0]<<" [N] [M] ";
       return 1;
    }

    int n = atoi(argv[1]);
    int m = atoi(argv[2]);
    cout<<n<<" "<<m<<endl;
    for(int i = 0; i < n ;i++)
    {
       for(int j = 0; j < m ;j++)
       {
          if(rand()%14 == 0)
          {
             cout<<"*";
          }else
          {
             cout<<".";
          }
       }
       cout<<endl;
    }
   cout<<"0 0";
	return 0;
}

El programa produce la siguiente salida.

15 30
...............*.....*........
.*.....*......................
.................*.*...*......
...*.......*.*.....*..........
....................*.........
.............*...............*
........*.................*...
*.....*...*........*..........
..............*....*......*...
.*............................
.........*..........*.........
.......*.*....................
................*.............
..*.*....*....*..*.........*..
..............................
0 0

La salida de sus soluciones debería ser como sigue:

Field #1:
111000111000001*10001*10000000
1*10001*1000001121212121100000
11211011101121101*3*201*100000
001*1000001*2*10113*3111100000
00111000001132200012*100000011
0000000111001*100001110001111*
11000112*21111100011100001*111
*10001*212*10111002*2000022200
22100111011101*1002*200001*100
1*1000001110011100122100011100
111000113*2000000001*100000000
0000001*3*20000111011100000000
0112111132200112*2100000001110
01*2*1001*1001*22*100000001*10
011211001110011111100000001110

Si necesitas alguna ayuda adicional puedes consultarla en el foro de programación c++.

Descomprimir archivos de un rpm

Seguramente muchos de ustedes han necesitado de algun archivo que esta contenido en un RPM y no han encontrado la manera de extraerlo.

Existe un programita llamado rpm2cpio. Por ejemplo lo que yo quise hacer es extraer los archivos del manual de MySQL en formato HTML de MySQL-server-4.1.12-1.i386.rpm

El comando para hacer esto es ubicar el archivo RPM y ejecutar:

rpm2cpio MySQL-server-4.1.12-1.i386.rpm | cpio -icduv *.htm

Y listo!

Esto extraera los archivos indicados en la carpeta actual incluyendo directorios.

Los argumentos de cpio:

i : Extrae los archivos
c : Formato portable
d : Crear directorios completos
u : Incondicional (reemplaza los archivos si existieran)
v : Muestra los archivos descomprimidos en pantalla

Grafos

Los grafos son un tipo de estructuras de datos; no voy a explicar exactamente de que se tratan los grafos pero pueden encontrar mas información al respecto aqui.

Llegar a implementar en forma básica listas, árboles y grafos es una parte importante en los inicios de la carrera de un programador. Por lo que estoy preparando pequeño artículo sobre como implementar grafos.

Lo interesante de este articulo, que desarrollé hace algunos años, es que lo combiné con un algoritmo de ordenación grafica basada en distancias y para que el parpadeo no moleste lo implementé con double buffering.

Aquí un recorte de muestra del programa en ejecución.

Grafo Visual C++

Pueden descargarse un demo ejecutable, por lo pronto, en el siguiente enlace:

grafos.zip

Cuando lo tenga completamente listo voy a publicarlo documentado y podrán descargarlo con código fuente que podran compilar en diferentes sistemas operativos. Espero que luego les pueda servir como punto de inicio y llegar mas lejos con las estructuras de datos.

Update: Pueden descargar el artículo de la siguiente dirección:

Implementacion de Double Buffer en Visual C++:
http://www.latindevelopers.com/vcpp/bitmap/doble-buffer/

Detectar pais del visitante en PHP

PHP Logo Los webmasters nos preocupamos mucho por saber quienes son los que visitan nuestras páginas, para ello utilizamos herramientas muy útiles como contadores de visitas, analizadores de tráfico, etc., pero no siempre tenemos lo que queremos, no hay como hacer un script con tus propias manos.

Hace mucho tiempo encontré una base de datos (actualizada periódicamente) que contiene todos la mayoría de números IP que se pueden encontrar en la red. Estos están almacenados en forma de rangos y contiene el dato que nos interesa el País. Con esta base de datos es fácil determinar el país de procedencia del visitante a partir del numero  IP.

MaxMind es una empresa que provee este tipo de servicios y nos brinda un archivo libre (pero limitado) que podemos aprovechar.  http://www.maxmind.com/app/geolitecountry , solo tenemos que descargar el archivo e instalarlo en nuestra base de datos MySQL, sigan los pasos:

Paso 1: Descargar y Descomprimir la base de datos MaxMind (formato .csv):

wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
unzip GeoIPCountryCSV.zip  #contiene el archivo GeoIPCountryWhois.csv

Esta es una vista previa del archivo GeoIPCountryWhois.csv

...
"190.8.128.0","190.8.159.255","3188228096","3188236287","PE","Peru"
"190.8.160.0","190.8.163.255","3188236288","3188237311","PA","Panama"
"190.8.164.0","190.8.167.255","3188237312","3188238335","VE","Venezuela"
"190.8.176.0","190.8.179.255","3188240384","3188241407","CO","Colombia"
"190.8.180.0","190.8.183.255","3188241408","3188242431","EC","Ecuador"
"190.8.184.0","190.8.191.255","3188242432","3188244479","AR","Argentina"
"190.8.192.0","190.8.255.255","3188244480","3188260863","CO","Colombia"
"190.9.0.0","190.9.31.255","3188260864","3188269055","AR","Argentina"
"190.9.32.0","190.9.47.255","3188269056","3188273151","VE","Venezuela"
...

Luego debemos crear la tabla donde vamos a importar esos datos en formato csv:

CREATE TABLE ipdatabase
(
  str_ip_from varchar(15),
  str_ip_to varchar(15),
  ip_from int unsigned,
  ip_to int unsigned,
  country_code2 char(2),
  country_name varchar(50),
  KEY ip_from (ip_from),
  KEY ip_to (ip_to)
);

Es importante que los campos ip_from e ip_to sean int unsigned por que guardaremos números realmente grandes.

LOAD DATA LOCAL INFILE '/ruta_hacia/GeoIPCountryWhois.csv'
INTO TABLE ipdatabase
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';

Para poder mostrar las imágenes debemos tener las imágenes de las banderas de todos los países, pueden descargar un pack banderas en diferentes tamaños de: http://speckyboy.com/2010/08/04/top-10-country-flag-icon-sets/

Ahora todo esta listo para que podamos escribir el código PHP que determinara el registro al cual pertenece un determinado numero de IP:

$link = mysql_connect("localhost" , "ipdatabase", "pwd");
mysql_select_db("ipdatabase",$link);
$sql = "SELECT lcase(country_code2) as code,country_name as name ".
"FROM ipdatabase ".
"WHERE ip_from <= inet_aton('{$_SERVER['REMOTE_ADDR']}') ".        
"AND ip_to >= inet_aton('{$_SERVER['REMOTE_ADDR']}') ";
if($res = mysql_query($sql,$link)) 
{
if(mysql_affected_rows($link) > 0 && $row = mysql_fetch_array($res))
    $im = imagecreatefrompng("../images/flags/".$row['code'].".png");
else
    $im = imagecreatefrompng("../images/flags/-.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
mysql_free_result($res);
}
else
{
echo mysql_error($link);
}
mysql_close($link);

El resultado del script anterior es el siguiente:

Usted nos esta visitando desde :

Ustedes pueden personalizar el código PHP para publicarlo en sus paginas web.

Espero les sirva.