miércoles, 1 de octubre de 2008

Usando Tablas en Blog's

Un nuevo semestre comienza y los desafíos abundan, solo hay que estar atento. Hace unos días publicaba en El Morrocotudo un diario ciudadano y necesitaba usar una tabla. Tiene un editor muy parecido al de blogger, que permite, como muchos, la inclusión de código html. Bueno, me dije a mi mismo, usaremos las sentencias con TABLE y el resultado fue... funesto, ya que todos los "enter" ingresados para el código, para hacerlo más legible, claro, fueron colocados arriba, de tal manera que luego de muchas lineas en blanco, aparecía la tabla... otro tema fue el ancho, pero bueno, eso se arregla fácil.

Comencé a indagar en Internet y me dí cuenta que el problema es muy común. El tema es que si, escribimos todo junto, sin espacios ni nada, las tablas aparecen normalmente. Claro, eso es fácil cuando tienes un par de filas... pero que pasa si son muchas más? estaré borrando los espacios en blanco y los "enter" uno a uno? (una vez lo hice, puaj! ). Una de las soluciones que encontré es usando las propiedades de concatenar cadenas, usando algun programa de hojas de cálculo... pero que tal si usamos C ? y bueno, en menos de 15 minutos, escribí el siguiente código:


En el cual, en el archivo de texto llamado "datos.txt" simplemente pego todo el código generado por mi editor web, al hacer las tablas y luego, al ser procesado, se crea el archivo "salida.txt" con el código corregido, o sea, sin los "enter" ni los espacios en blanco.

viernes, 8 de agosto de 2008

Acentos en C

Para reconocer caracteres especiales, podemos utilizar el código ascii generado por cada letra. Esto es, reconcer el número que representa a cada caracter. He aquí un programa que busca acentos en la "i" utilizando una conversión forzada de cada elemento del arreglo y comparándolo con el valor de la i acentuada.

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


int main()
{
char entrada[100];
int largo=0,i=0,test=0;
printf("ingresa los datos requeridos \n");
scanf("%[^'0-9']",entrada);
largo= strlen(entrada);

printf("\n lo que usted ingreso es: ");

printf("\n%s y el largo es:
%d\n",entrada, largo);

for(i=0;i<largo;i++)

{

test=(int)entrada[i]; //conversión a entero
if(test==-115) //el -115 representa a la i acentuada en forma grave, " ì "
printf("\n acento en la i encontrado en la pos=%d\n",i+1);
}

system("pause");

}

Para conocer los valores de cada caracter, basta con imprimirlos previa conversión forzada, por ejemplo, utilizando el mismo for que vemos en el programa anterior y luego, imprimr "test" por cada letra.

¿Cómo leer desde teclado e incluir los espacios?

En este post, quisiera compartir una forma (deben existir varias) para, a través del formato que se le da al scanf, poder leer todo lo escrito, hasta algún caracter en especial. En general, estamos acostumbrados a formatear con respecto al tipo de dato a leer, esto es, "%d" para enteros, "%f" para punto flotante, "%l" para long, etc.. Aquí usaremos algo parecido, solo que en vez de que sea algo directo a través de una letra, será con una condición... o sea, leerá "todo hasta un caracter" o "solo ciertos caracteres".

Leyendo hasta encontrar un numero
#include<stdio.h>
#include<windows.h>

int main()

{

char entrada[100];
printf("ingresa los datos requeridos\n");

scanf("%[^'0-9']",entrada);

printf("\n lo que usted
ingresó es: ");

printf("\n%s\n",entrada);

system("pause");

return 0;

}

En el código anterior leemos todo hasta encontrar un número. El "secreto" está en el formato que le damos al scanf. Si nos fijamos bien, en la instrucción:
scanf("%[^'0-9']",entrada) podemos traducirla de esta forma:

% ; indica el comienzo de una conversión de datos
[; indica el comienzo de un rango de datos
^ : el símbolo circunflejo, actua como un "not lógico", o sea dice: no leas...
'0-9': aquí tenemos el rango en sí, o sea, desde 0 a 9.

Ojo que estos son caracteres, por eso utilizamos un arreglo de tipo char, o sea, un string.

Ejemplo de entrada-salida:

ingresa los datos requeridos
hola que tal festival2
usted ingreso
hola que tal festival

Ahora bien para el programa anterior usamos DEV-C++ por eso la librería windows.h y el system("pause").

miércoles, 2 de julio de 2008

Sobre Listas: Programa Completo 1

Después de una toma que duró 41 días, lo mejor es desempolvar el teclado con un resumen de las listas. En este caso, el código presentado tiene por objeto:
  1. Ingresar elementos al final de la lista.
  2. Ver los elementos de la lista.
La lista tiene una estructura compuesta por un número entero. Este ejemplo se irá completando a medida que se le agreguen las siguientes funciones:
  • Insertar en una posición determinada (al principio, al final o en medio de dos nodos).
  • Eliminar de una posición determinada (al principio, al final o en medio de dos nodos).
El código está aquí

lunes, 12 de mayo de 2008

Sobre Listas: Parte 2

Ahora bien, si queremos utilizar funciones para el ingreso de los datos, lo cual parece muy cuerdo, podríamos tener el siguiente código:

#include <stdio.h>

#include <stdlib.h>





#define MAXNOMBRE 20



typedef struct nodo{

char nombre[MAXNOMBRE];

int valor;

struct nodo* sgte;



}nodo;



void MostrarLista(nodo* raiz)

{


printf("\n La lista esta compuesta de los siguientes elementos\n");


nodo* sigue;




for(sigue=raiz;sigue->sgte!=NULL;sigue=sigue->sgte)


printf("NOMBRE: %s \n VALOR: %d \n", sigue->nombre,
sigue->valor);


printf("NOMBRE: %s \n VALOR: %d \n", sigue->nombre,
sigue->valor);

}


void IngresarPrimerElemento(nodo *raiz)

{


printf("lo logre!\n Ingresa un nombre\n");


scanf("%s",raiz->nombre);


printf("Ingresa un valor\n");


scanf("%d",&raiz->valor);

}

void IngresarElemento(nodo *raiz)

{


nodo* sigue;


sigue=raiz;


while(sigue->sgte!=NULL)


sigue=sigue->sgte;




nodo* nuevo;


nuevo = malloc(sizeof(nodo*));


nuevo->sgte=NULL;




printf("lo logre!\n Ingresa un nombre\n");


scanf("%s",nuevo->nombre);


printf("Ingresa un valor\n");


scanf("%d",&nuevo->valor);




sigue->sgte=nuevo;

}

int main()

{

nodo *p;

p=malloc(sizeof(nodo*));

p->sgte=NULL;



IngresarPrimerElemento(p);

IngresarElemento(p);



MostrarLista(p);



return 0;



}

Sobre Listas: Parte 1

Aquí ingresaremos una función para conocer los datos que han sido ingresados en nuestra lista:

#include <stdio.h>

#include <stdlib.h>


#define MAXNOMBRE 20

typedef struct nodo{

char nombre[MAXNOMBRE];

int valor;

struct nodo* sgte;



}nodo;



void MostrarLista(struct nodo* raiz)

{

printf("\n La lista esta compuesta de los siguientes elementos\n");


nodo* sigue;




for(sigue=raiz;sigue->sgte!=NULL;sigue=sigue->sgte)


printf("NOMBRE: %s \n VALOR: %d \n", sigue->nombre,
sigue->valor);


printf("NOMBRE: %s \n VALOR: %d \n", sigue->nombre,
sigue->valor);

}

int main()

{

nodo *p;

p=malloc(sizeof(nodo*));





printf("lo logre!\n Ingresa un
nombre\n");

scanf("%s",p->nombre);

printf("Ingresa un valor\n");

scanf("%d",&p->valor);



nodo *q=malloc(sizeof(nodo*));

p->sgte=q;

q->sgte=NULL;

printf("lo logre!\n Ingresa un
nombre\n");


scanf("%s",p->sgte->nombre);

printf("Ingresa un valor\n");


scanf("%d",&p->sgte->valor);



MostrarLista(p);



return 0;



}

Sobre Listas: Parte 0

Si tuviésemos un nombre y un código por cada nodo de nuestra lista y quisiéramos ingresar datos, digamos, tan solo dos, tendríamos un código como el siguiente:

#include <stdio.h>

#include <stdlib.h>





#define MAXNOMBRE 20



typedef struct nodo{

char nombre[MAXNOMBRE];

int valor;

struct nodo* sgte;



}nodo;

int main()

{

nodo *p;

p=malloc(sizeof(nodo*));



printf("\n Ingresa un
nombre\n");

scanf("%s",p->nombre);

printf("Ingresa un valor\n");

scanf("%d",&p->valor);

printf("\nUsted ha ingresado los
siguientes valores\n");



printf("NOMBRE: %s \n VALOR: %d \n",
p->nombre, p->valor);




nodo *q=malloc(sizeof(nodo*));

p->sgte=q;

q->sgte=NULL;

printf("lo logre!\n Ingresa un
nombre\n");


scanf("%s",p->sgte->nombre);

printf("Ingresa un valor\n");


scanf("%d",&p->sgte->valor);

printf("\nUsted ha ingresado los
siguientes valores\n");

printf("NOMBRE: %s \n VALOR: %d \n",
p->sgte->nombre, p->sgte->valor);





return 0;

}

Lo cual, cubre nuestras expectativas.... ¿cómo hacer para listar los datos sin tener la necesidad de especificar el puntero? Parece ser posible con una función...

sábado, 3 de mayo de 2008

Struct + Archivos y Listas: Una aplicación práctica

La empresa "Arica Up" ingresa los datos de sus empleados en un archivo "empleados.dat" Cada registro contiene:
  • un código de identificación (int)
  • el nombre (string de un máximo de 30 caracteres)
  • el cargo (string de un máximo de 10 caracteres)
  • el sueldo (double)
  • el área en la que trabaja (string de 10 caracteres)
Se desea asignar un bono de:
  • 15% a los que están en la zona Parinacota,
  • un 20% a los que están en la zona Chinchorro
  • 23% a los que están en la zona Centro.
Esto debe generar un archivo llamado "sueldos.dat" el cual contiene el código de identificación y el total a pagar.
  • Sueldos por cargo:
    • Gerente de zona : 2.5 MM
    • Directivo de sección: 1.5 MM
    • Secretarias: 300.000
    • ejecutivo: 600.000
    • recepcionista: 230.000
  • Total a pagar = sueldo(según_cargo) + bono_zona - 12% AFP - 8% Salud
Ejemplo: Si se trata de una secretaria, de la zona chinchorro, el total a pagar será:
300.000=sueldo(secretaria).





























sueldo base secretaria$300.000
bono (incremento de un 20% del sueldo)$60.000
Total bruto$360.000
descuento de un 12% del total bruto$43.200
descuento de un 8% del total bruto$28.800
Total descuentos$72.000
Total a pagar (Total bruto-Total descuentos)$288.000

martes, 15 de abril de 2008

¿Cómo diferenciar entre letras y números?

Sí, tanto letras y números son caracteres. Cada caracter, tiene asociado un código. Esto esta contenido en la tabla ASCII.
Entonces, si conozco el código correcto, podré diferenciar entre una letra o un dígito. Si nos fijamos en la tabla, los dígitos están entre el rango 48, 57 (del 0 al 9), las letras minúsculas en el rango 97, 122 y las mayúsculas 65, 90.
Un algoritmo para diferenciar entre letras y dígitos podría ser el siguiente:

  1. leer caracter de entrada
  2. compararlo con el rango de dígitos
    1. Si es verdadero, imprimir un mensaje de "es un número"
    2. Si no, preguntar por el rango de letras mayúsculas
      1. Si es verdadero, imprimir un mensaje de "es una letra mayúscula"
      2. Si no, preguntar por el rango de letras minúsculas
        1. Si es verdadero, imprimir un mensaje de "es una letra minúscula
        2. Si no, imprimir "es otro caracter".
La idea de preguntar por los tres rangos, es que entre las letras minúsculas y las mayúsculas, existen otros caracteres, así que es mejor asegurarse.

Un programa que realice esta acción podría ser el siguiente:

#include
/*
Este programa diferencia entre letras y números ingresados por teclado,
diferenciando el contenido de la variable, basándose en que, cada caracter
posee un código definido (ASCII).
*/

main()
{
char variable='0';
printf("ingresa una letra o número\n");
scanf("%c",&variable);
printf("el codigo asociado es %d\n",variable);

if(variable<=57 && variable>=48) //variable esta en el rango de digitos
printf("ingresaste un digito \n");
else if(variable<=90 && variable >=65) //variable esta en el rando de letra mayúscula
printf("INGRESASTE UNA LETRA MAYUSCULA\n");
else if(variable<=122 && variable >=97)
printf("ingresaste una letra minuscula\n");
else
printf("ingresaste otra cosa, que no es ni letra ni numero\n");
}

Existen funciones en C\C++ que emulan este procedimientos, isdigit por ejemplo. Aquí dejo un link al respecto

lunes, 14 de abril de 2008

Sobre Manejo de Strings 1

Cuando comparamos entidades, debemos tener presente su naturaleza. En el caso de comparar perros con gatos, nos podríamos encontrar con sorpresas, como las diferencias de tamaño, la lengua del gato y el gusto por el agua. Particularmente, si comparamos números no tenemos grandes problemas en usar relaciones lógicas (<, >, =, etc..).
Por ejemplo, si queremos encontrar un año ingresado por teclado, entre otros almacenados previamente, en un arreglo de enteros, podemos pensar en el siguiente algoritmo:

  1. Leer año a buscar
  2. Mientras no llegue al final
  • comparar el año en el arreglo con el año a buscar
  • si es el buscado, imprimir un mensaje y colocar la bandera de encontrado en 1
  • si no, seguir
3. preguntar por el valor de la bandera, si esta en 0, imprimir un mensaje "el año ingresado no se encuentra, o si esta en 1, algun mensaje de despedida.

El código sería algo como esto:

#include
/*
este programa muestra una búsqueda secuencial de un entero ingresado por teclado
entre un conjunto de enteros almacenados en un arreglo. Cada vez que se encuentra
el número en el arreglo, se imprime junto a su posición.
*/

#define MAX 7

main()
{
int datos[]={1994,1993,1999,2007,2003,2005,2001};
int yearBuscar=0;
int encontrado=0;

int i;
printf("Ingrese el anio a buscar: ");
scanf("%d",&yearBuscar);

for(i=0;i
if(yearBuscar==datos[i])
{
printf("\n %d en la posición %d",datos[i],i+1);
encontrado=1;
}

if(!encontrado)
printf("\nel valor no ha sido encontrado \n");
else
printf("\ngracias por utilizar este programa\n");

}

Uno de los puntos cruciales de este programa es la comparación en el if... lo cual es posible gracias a que tenemos dos entidades del mismo tipo, dos enteros. Veamos un caso parecido, pero ahora, con strings.

Tenemos en un arreglo de strings una lista de nombres, debemos encontrar un nombre ingresado por teclado. Nuestro algoritmo quedaría así:

  1. Leer nombre a buscar
  2. Mientras no se termine el arreglo
  • comparar el nombre en el arreglo con el nombre a buscar
  • si es el mismo, imprimir un mensaje y colocar la bandera de encontrado en 1
  • si no, seguir
3. preguntar por el valor de la bandera, si esta en 0, imprimir un mensaje "el nombre ingresado no se encuentra, o si esta en 1, algun mensaje de despedida.

Ahora bien, para poder utilizar la misma lógica de comparar entidades, podemos ahorrarnos varias líneas de código utilizando la librería string.h
Como necesitamos comparar dos strings, usaremos una de las funciones que esta librería nos provee strcmp ; esto es como decir "string compare", compara strings.

Veamos nuestro código:

#include
#include
/*
este programa muestra una búsqueda secuencial de un string ingresado por teclado
entre un conjunto de strings almacenados en un arreglo. Cada vez que se encuentra
el string en el arreglo, se imprime junto a su posición.
*/

#define MAX 7
#define MAXLETRAS 12

main()
{
char *datos[]={"pedro","maria","valentina","juan","rocío","manuel", "cote"};
char nameBuscar[MAXLETRAS];
int encontrado=0;

int i;
printf("Ingrese el nombre a buscar: ");
scanf("%s",nameBuscar);

for(i=0;i
if(strcmp(nameBuscar,datos[i]) == 0)
{
printf("\n %s en la posición %d",datos[i],i+1);
encontrado=1;
}

if(!encontrado)
printf("\nel valor no ha sido encontrado \n");
else
printf("\ngracias por utilizar este programa\n");
}

A modo de resumen, la función strcmp sirve para comparar string, retorna un entero, dependiendo el "orden" en que los string a comparar esten puestos en los argumentos. Es por esto que, si el entero retornado por la función es cero, podemos afirmar que los string son iguales.