Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

jueves, 8 de agosto de 2013

Cómo ignorar los acentos al hacer una búsqueda en una base de datos en MS Access (mdb) con C#

Tengo el siguiente código:

string nombre = nombreABuscarenlaBD;

string query = String.Concat("Select * from Tabla1 where campoNombre like '", nombre, "'");

Este query funciona mientras no se desee buscar un nombre que incluya acentos como "María" ingresando "Maria" . Lo peor: puede que el usuario ni siquiera sepa si en la base de datos los nombres están guardados con acentos o no.

Para que la búsqueda devuelva todas las coincidencias con y sin acentos, se debe hacer el siguiente cambio a la variable tipo string que contiene el criterio de búsqueda (la idea es sacada de este foro):

nombre = nombre.Replace("a", "[aá]").Replace("e", "[eé]").Replace("i", "[ií]").Replace("o", "[oó]").Replace("u", "[uú]").Trim();

Si se desea ignorar también las diéresis, será:

nombre = nombre.Replace("a", "[aäá]").Replace("e", "[eëé]").Replace("i", "[iïí]").Replace("o", "[oöó]").Replace("u", "[uüú]").Trim();

miércoles, 24 de julio de 2013

Tutorial: Script en Python para montar particiones en Ubuntu 12.04

Sólo lo he podido probar con particiones NTFS, y sin espacios en blanco en el nombre de la carpeta dentro de /media/ donde se monta la partición.

Tengo mi disco duro particionado en dos particiones: C: y D:, ambas NTFS. Al instalar el Ubuntu 12.04 desde Windows XP usando Wubi se crea un doble booteo: Windows y Ubuntu. Todo bien hasta aquí, el Ubuntu inicia y reinicia de lo mejor, al igual que el Windows. El Ubuntu coloca mi partición D: en la carpeta /host/:

Mi partición D: como la ve Ubuntu

Pero por ningún lado veía mi partición C:. El problema estaba en que debía montarla. Las instrucciones para hacerlo las saqué de esta web.

Luego de montar y desmontar la partición C: algunas veces, siguiendo las instrucciones de ubuntu-guia y restaurando el archivo /etc/fstab original, pensé que todos esos pasos podían automatizarse, y entonces recordé que Ubuntu ya viene con un intérprete de Python, el cual justamente se utiliza para automatizar ciertas tareas.

En este caso, la tarea consistía en:

  • Ingresar con privilegios de root (en todo momento sudo me pidió la contraseña de root para tener privilegios suficientes, especialmente al copiar y pegar el archivo fstab mediante el comando "gksudo nautilus /etc/").

  • Ejecutar comandos de sudo.

  • Crear una carpeta en un directorio de sistema (/media/).

  • Modificar un archivo de sistema (/etc/fstab).

  • Reiniciar el sistema (esto lo dejé a que lo hiciera el usuario).

Para acceder a las funciones y características del sistema operativo usando Python, se deben importar dos librerías "os" y "sys". El código para que el script ingrese con privilegios de root pidiendo la contraseña lo saqué de este enlace.

Una vez que ya podía ingresar como root, necesitaba una función de Python que me permitiera ejecutar comandos de sudo y almacenar en una variable los resultados. El primer comando de sudo que debía ejecutar mi script es "fdisk -l":


La función que necesito es os.popen() el cual me devuelve en una lista las particiones halladas y sus características, pero como cadenas de caracteres. Con la función print() puedo mostrar en la terminal el resultado y mostrar las particiones halladas. En mi caso la lista (almacenada en una variabble llamada "rem") tiene tres elementos, el script muestra esta lista y pide al usuario que ingrese la partición a montar con la función raw_input(). Se debe ingresar la partición tal y como se muestra en la terminal, en mi caso es "/dev/sde1" (sin las comillas). Luego el script evalúa si la partición existe, cuyo nombre está almacenado en una variable llamada "part", utilizando la función filter(). Si no existe, el script finaliza. Este chequeo es necesario pues el usuario puede ingresar cualquier otra cosa, desde equivocarse al escribir hasta intentar sabotear el sistema operativo. (la función raw_input() interpreta lo ingresado como caracteres, pero la función input() interpreta lo ingresado como comandos de Python; ambas funciones pertenecen a este lenguaje, mucho cuidado con confundirlas!).

La función filter() es el equivalente en Python de las funciones de C# Linq.Where().

La línea:

n = filter(lambda x: x.find(part, 0, len(x)) > -1, rem) 

en C# 3.0 sería:

var n = rem.Where(c => c.IndexOf(part) != -1);

En Python, si lalongitud de "n" es cero, es que no se ha hallado la partición ingresada.

Luego debo ejecutar el comando de sudo "blkid particion_elegida":


El resultado, guardado en la variable "rem", es una lista con un solo elemento tipo cadena de caracteres, el cual contiene el ID y el tipo de partición. Extraigo ambos con la función filter() y con el código que encontré en este enlace, el cual usa expresiones regulares para extraer la cadena de caracteres que se necesita, por este motivo debo importar también la librería "re".

Una vez que tengo todos los datos que necesito (partición, ID y tipo) le pido al usuario que escriba el nombre de la carpeta dentro de /media/ donde el script montará la partición. Si la carpeta no existe, el script la creará automáticamente. La línea que evalúa si la carpeta existe es:

os.path.isdir("media/carpeta_ingresada")

La variable con la ruta completa es "t2". Para crear la carpeta, si ésta no existe, utilizo el comando "mkdir" de sudo.

Python no posee un "switch" o un "Select Case" como otros lenguajes de programación, pero esto se resuelve con algunos if... else. En este caso, es para evaluar el tipo de partición y "armar" la línea que se añadirá al archivo /etc/fstab.

El código completo es:

#! /usr/bin/env python

import os;

import re;

import sys; 

# http://stackoverflow.com/questions/5222333/authentication-in-python-script-to-run-as-root

euid = os.geteuid()

if euid != 0:

    print "Iniciando sudo para ingresar como root..."

    args = ['sudo', sys.executable] + sys.argv + [os.environ]

    # the next line replaces the currently-running process with the sudo

    os.execlpe('sudo', *args) 

if euid == 0:

    print 'Corriendo, su euid es: ', euid

else:

    print 'No se pudo iniciar como root. Cerrando script'

    sys.exit()

 

# http://mail.python.org/pipermail/python-es/2007-December/019270.html

rem = os.popen("sudo fdisk -l").readlines() # obtengo las particiones 

for i in rem:

    print

# http://www.daniweb.com/software-development/python/threads/12326/how-to-do-input-in-python

# "input" interpreta lo ingresado como comando, se debe usar raw_input 

part = raw_input("Escriba la particion a montar: ")

n = filter(lambda x: x.find(part, 0, len(x)) > -1, rem) 

if len(n) == 0:

    print ("La particion no existe")

else:

    t = ("sudo blkid ", part) # obtengo el UUID

    sudo1 = ''

    sudo1 = sudo1.join(t)

    rem = os.popen(sudo1).readlines() 

    if len(rem) == 0:

        print("Particion no valida")

    else:

        partInfo = rem[0].split()

        IdPart = filter(lambda x: x.upper().find('UUID', 0, len(x)) > -1, partInfo)

        tipoPart = filter(lambda x: x.upper().find('TYPE', 0, len(x)) > -1, partInfo)       

        # http://stackoverflow.com/questions/4666973/how-to-extract-a-substring-from-inside-a-string-in-python

        uuID = re.search('"(.+?)"', IdPart[0]).group(1)

        tipoParticion = re.search('"(.+?)"', tipoPart[0]).group(1)

        print tipoParticion 

        carpeta = raw_input('ingrese el nombre de la carpeta dentro de /media/ donde montar la particion. ')

        t = ('/media/', carpeta)       

        t2 = ''

        t2 = t2.join(t) 

        if not os.path.isdir(t2):

              t = ('sudo mkdir /media/', carpeta)

              sudo1 = ''

              sudo1 = sudo1.join(t)

              rem = os.popen(sudo1).readlines()

        # http://snipplr.com/view/6630/

        # http://www.tutorialspoint.com/python/python_files_io.htm       

        if tipoParticion.upper() == 'NTFS':

            t = ('UUID=', uuID, '      /media/', carpeta, '     ntfs-3g default       0      0')

        elif tipoParticion.upper() == 'FAT':

            t = ('UUID=', uuID, '      /media/', carpeta, '     vfat rw,uid=1000,gid=1000      0      0')

        elif tipoParticion.upper() == 'EXT4':

            t = ('UUID=', uuID, '      /media/', carpeta, '     ext4 errors=remount-ro 0      1')

        else:

            t = ''

           

        if len(t) > 0:

            linea = ''

            linea = linea.join(t)           

            with open('/etc/fstab', 'a') as fstab_file:

                fstab_file.writelines(linea)

                fstab_file.close()

            print 'Se ha montado la particion, reinicie el sistema'

        else:

            print('particion desconocida')


 

Este script sólo ha sido probado montando particiones NTFS en Ubuntu 12.04 y en carpetas dentro de /media/ cuyos nombres no contengan espacios. La partición no debe estar listada en /host/ o el sistema Ubuntu botará error al iniciar. 

martes, 16 de julio de 2013

Seleccionar registros entre dos fechas en SQL Server 2005

Para seleccionar registros que se encuentren entre dos fechas almacenadas en un campo específico tipo DateTime, se debe crear un script de la siguiente forma:

Select * from tabla1 where campoFecha > Convert(char(19), '11/01/2010', 113) and campoFecha < Convert(char(19), '11/08/2010', 113)

La fecha debe estar en el formato dd/MM/yyyy HH:mm:ss (formato de fecha y 24 horas. Suele arrojar error si la hora está en el formato am/pm).
En C# la conversión de una fecha almacenada en una variable tipo DateTime al formato de 24 horas se realiza con la siguiente instrucción sacada de la web de MSDN:

DateTime date1 = alguna fecha;
string sDate = date1.ToString("dd/MM/yyyy HH:mm:ss", System.Threading.Thread.CurrentThread.CurrentCulture);

Para armar el script simplemente se concatena utilizando la variable sDate.

Para eliminar, el script tendrá la forma:
Delete from tabla1 where campoFecha = Convert(char(19), '11/08/2010 15:00:00', 113)

En ambos casos, la hora es opcional.
Más información acerca de la función Convert de Transact-sql en este enlace.
La función Convert de transact-sql que utilizo es sacada de Onglasses.
Una lista completa del uso de la función Convert de transact-sql en este enlace.

martes, 11 de junio de 2013

Cómo mantener la misma fila seleccionada de un DataGridView sin importar si cambia su índice (Index)

Tengo un DatagridView llamado dGridView como el siguiente:



El DataGridView tiene su propiedad SelectMode igual a FullRowSelect.
Las filas no contienen datos únicos y, en otra parte del programa, cambio su propiedad Multiselect de true a false y viceversa.
Al cambiar el valor de la propiedad Multiselect, la fila o filas seleccionadas se deseleccionan (se pierde la selección), además el usuario puede hacer click en las cabeceras de las columnas lo cual cambia el orden y los índices de las filas (hacer click en las cabeceras de las columnas no deselecciona ninguna fila).
Lo que deseo hacer es que la última fila seleccionada por el usuario siempre se mantenga seleccionada a pesar de que se haga click en las cabeceras de las columnas, la filas ya no estén en el mismo orden, y se cambie el valor de MultiSelect (u otra propiedad que haga que se pierda la selección).

Para lograr esto hay que considerar tres eventos del DataGridView: CellMouseDown, CellMouseUp y SelectionChanged.
El código es:

        int selectedIndex;

        private void dGridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (d
GridView.Rows.Count > 0 && dGridView.SelectedRows.Count >= 1)
                selectedIndex = d
GridView.SelectedRows[0].Index;
        }

        private void d
GridView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (d
GridView.Rows.Count > 0 && dGridView.SelectedRows.Count >= 1)
                selectedIndex = d
GridView.SelectedRows[0].Index;
        }


        private void dGridView_SelectionChanged(object sender, EventArgs e)
        {
            if (d
GridView.Rows.Count > 0 && dGridView.SelectedRows.Count >= 1)
                selectedIndex = d
GridView.SelectedRows[0].Index;
        }

Para restablecer la fila seleccionada se debe poner el siguiente código en donde se cambia la propiedad Multiselect de dGridView, ó después de cualquier código que haga que se pierda la selección:
        dGridView.Rows[selectedIndex].Selected = true;

jueves, 18 de abril de 2013

Calcular los n primeros elementos del Conjunto de Wirth

Me encontré con este problema revisando la página de PuntoPeek. Aquí copio la definición del Conjunto de Wirth:
"El conjunto de Wirth es un subconjunto de los enteros positivos que cumple con la siguiente regla: el 1 pertenece al conjunto y si un numero k pertenece al conjunto entonces los numeros 2*k+1 y 3*k+1 pertenecen al conjunto."

En un primer vistazo parecía un problema que podría resolverse con un bucle, pero en realidad es bastante más complicado:
Empiezo con 1 y calculo los siguientes dos números: 2*1+1=3 y 3*1+1=4.
Mi conjunto por ahora es: [1, 3, 4]
Los siguientes dos números son: 3*2+1=7 y 3*3+1=10
Los otros dos siguientes son: 4*2+1=9 y 4*3+1=13
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13]
Calculo los dos siguientes: 7*2+1=15 y 7*3+1=22
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22]
Calculo los dos siguientes: 10*2+1=21 y 10*3+1=31
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22, 21, 31]
Calculo los dos siguientes: 9*2+1=19 y 9*3+1=28
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22, 21, 31, 19, 28]

Se puede notar que los números del conjunto de Wirth no se generan de modo ascendente, si no que el conjunto se va "rellenando" a medida que se hacen más y más cálculos. Un simple bucle que calcule los 5 primeros números del conjunto de Wirth nos dará [1, 3, 4, 7, 10] cuando la respuesta correcta es [1, 3, 4, 7, 9]. El error se hace más grande con cantidades mayores.
Otro problema es que se generan números repetidos, por ejemplo en el caso de 10*3+1 y 15*2+1.
Considerando esto, se puede comprobar que varias de la respuestas dadas en esta web son erróneas.

Para evitar el caso de números faltantes, mi algoritmo calcula el doble de los números requeridos, además de comprobar que no estén repetidos, ordena el array resultante y sólo muestra la cantidad de números solicitada.

Este es el código en Python:

def Wirth(i, n, w, k):
    if n == 1:
        return 0
    else:       
        k = w[i]
        t = 2*k + 1

        if t not in w:
            w.append(t)

        t = 3*k + 1

        if t not in w:
            w.append(t)

        return Wirth(i+1, n-1, w, k)

w=[1]
n=50

Wirth(0, n*2, w, 1)
w.sort()
w = w[0 : n]
print w




Y en C# usando Linq:

 class Program
    {
        static int Wirth(int i, int n, ref int[] w, int k, int count)
        {
            if (n == 0 || count >= w.Length)
                return 0;
            else
            {
                k = w[i];
                int t = 2 * k + 1;

                if (!w.Any(c => c == t))
                {
                    count++;
                    w[count] = t;
                }

                t = 3 * k + 1;

                if (!w.Any(c => c == t))
                {
                    count++;
                    w[count] = t;
                }
              
                return Wirth(i + 1, n - 1, ref w, k, count);
            }
        }

        static void Main(string[] args)
        {         
            int n = 50;

            int[] w = Enumerable.Repeat(0, n * 2).ToArray();
            w[0] = 1;

            Wirth(0, n, ref w, 1, 0);

            w = w.Where(c => c != 0).OrderBy(c => c).ToArray();

            for (int i = 0; i < n; i++)
                Console.WriteLine(w[i]);

            Console.Read();
        }
    }


Y obtengo la misma respuesta que PuntoPeek, cuya solución me ha gustado, es bastante elegante :D

jueves, 11 de abril de 2013

VB6: Cómo saber si existe una webcam conectada a la PC

Primero declaramos las funciones SendMessage y capCreateCaptureWindow (si se declaran en un módulo .bas las declaraciones deben ser públicas, para este ejemplo asumiremos que todo el código está dentro de un Form):

Private Declare Function capCreateCaptureWindow Lib "avicap32.dll" _
    Alias "capCreateCaptureWindowA" ( _
    ByVal lpszWindowName As String, _
    ByVal dwStyle As Long, _
    ByVal x As Long, _
    ByVal y As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long, _
    ByVal hwndParent As Long, _
    ByVal nID As Long) As Long

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
    ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Long, _
    lParam As Any) As Long


Private Const CONNECT As Long = 1034


El código que nos dice si hay una webcam conectada es:

Dim mCapHwnd as Long

mCapHwnd = capCreateCaptureWindowA("WebCap", 0, 0, 0, 320, 240, Me.hwnd, 0)
DoEvents

If SendMessage(mCapHwnd, CONNECT, 0, 0) <> 0 Then
     
MsgBox "Se ha detectado una webcam conectada y lista para usarse"
Else
      MsgBox "No se ha detectado una webcam"
End If



Basado en este código de Recursos Visual Basic

miércoles, 27 de marzo de 2013

Code Snippet: Pequeño ejemplo del uso de Linq.Any

Definición de Linq.Any extraído de esta web:
"El operador Any se utiliza para determinar si existe un elemento dentro de una secuencia que cumpla una condición expecífica."

Pero lo que yo necesitaba era un ejemplo concreto para saber si un elemento no existe en una colección usando Linq.Any.
El siguiente código muestra cómo usar Linq.Any para saber si un elemento existe o no en una colección. Es autoexplicativo:

using System;
using System.Linq;
using System.Collections.Generic;

namespace LinqPractice
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable mis_nums = Enumerable.Range(0, 4);
            mis_nums = mis_nums.Select(c => c * 3);

            // mis_nums = {0, 3, 6, 9}

            if (mis_nums.Any(c => c != 7))
                Console.WriteLine("Existe al menos un número que es diferente de 7");

            if (mis_nums.Any(c => c == 9))
                Console.WriteLine("El 9 sí existe en la colección");
            else
                Console.WriteLine("El 9 no existe en la colección");

            if (!mis_nums.Any(c => c == 7))
                Console.WriteLine("El 7 no existe en la colección");
            else
                Console.WriteLine("El 7 sí existe en la colección");
          
            Console.Read();
        }
    }
}


El resultado es:

 

lunes, 11 de marzo de 2013

Visual C++: Cómo hacer que una ventana aparezca maximizada al cargarla

Para una aplicación tipo Win32 se debe buscar en la función Initinstance la línea donde dice ShowWindow:

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   hInst = hInstance; // Almacenar identificador de instancia en una variable global

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)  
      return FALSE;   


  // Visual C++ nos crea esta línea:
  // ShowWindow(hWnd, nCmdShow);

  // debemos reemplazarla por esta otra línea:
   ShowWindow(hWnd, SW_MAXIMIZE);
   UpdateWindow(hWnd);
   return TRUE;
}


Los valores del parámetro que se le pasa a la api ShowWindow están declarados en WinUser.h y son los siguientes:

#define SW_HIDE             0
#define SW_SHOWNORMAL       1
#define SW_NORMAL           1
#define SW_SHOWMINIMIZED    2
#define SW_SHOWMAXIMIZED    3
#define SW_MAXIMIZE         3
#define SW_SHOWNOACTIVATE   4
#define SW_SHOW             5
#define SW_MINIMIZE         6
#define SW_SHOWMINNOACTIVE  7
#define SW_SHOWNA           8
#define SW_RESTORE          9
#define SW_SHOWDEFAULT      10
#define SW_FORCEMINIMIZE    11
#define SW_MAX              11


viernes, 22 de febrero de 2013

Algoritmo para obtener números primos de una forma funcional

Todo empezó cuando me puse a aprender Python (debido a que este curso requiere programar en ese lenguaje) utilizando Python Tools for Visual Studio. Primero debe bajarse e instalarse el Interpreter y, si no se tiene el Visual Studio, o se tiene la versión Express, hay que instalar The Visual Studio 2010 Shell Redistributable Package, y al final instalar Python Tools. Como resultado, tenemos un Python Express :D

Buscando tutoriales. hallé que en esta web proponían el siguiente método para obtener números primos (llamado "El Colador de Eratósthenes", no es el método más eficiente):

nums = range(2, 50)
for i in range(2, 8):
     nums = filter(lambda x: x == i or x % i, nums)


Luego el autor dice: "No sé de algún lenguaje que pueda hacer lo mismo con sus características propias de una forma tan compacta y legible como en Python (excepto para lenguajes funcionales)".

¡Sorpresa! En C# sí se puede:

int[] nums = Enumerable.Range(2, 48).ToArray();
for (int i = 2; i < 8; i++)
      nums = nums.Where(c => c == i || c % i != 0).ToArray();


Sólo hay que importar los espacios de nombres System y System.Linq.
:D

lunes, 21 de enero de 2013

Tutorial: Creando una DLL en Visual C++ 2010 y Usándola en una Aplicación en C#

Electrónica a Martillazos, actualización de la sección de VB6 y C++:
Creando una DLL en Visual C++ 2010 y Usándola en una Aplicación en C#.
Link directo
Un mirror

:D