lunes, 9 de mayo de 2011

Comencemos a soltar las manos...

Bien, con la idea de ir soltando las manos, les propongo el siguiente..mmm como decirlo para que no se estressssssen, jeje, ya, "juego":

Prueben qué pasa al momento de ir variando los formatos de salida del comando printf, por ejemplo usando el siguiente código fuente y modificando los "int" por "float", "short", "double" y los "%d" por "%c", "%l":



#include
#include


int main()
{
        int number = 0;
        int number1;


        printf("number tiene: %d\n number1 tiene %d", number, number1);


return 0;
}


En otras palabras, aprenderemos dos cosas: es mejor asignar un valor inicial a nuestras variables y no es lo mismo imprimir con "%d" que con "%c" o bien "%l". Debemos usar el formato que corresponde...

Dudas o consultas, primero lo intentan, luego lo vuelven a intentar y cuando estén pálidos, lo comentan para retroalimentar.

Un nuevo comienzo

Una generación nueva, promete retomar los ideales que promueve el software libre a través del presente blog.

Veamos si es cierto... Este martes 10 de mayo a las 08:00 hrs. en el hall central de la Universidad de Tarapacá, Arica, re comienza la re-evolución de las consciencias.

pd: sí, también hablaremos de programación en C.

lunes, 4 de abril de 2011

Desde cero...

Una nueva etapa comienza y aquí estoy para hacer un "f5", una actualización a los contenidos de este blog. El objetivo es enseñar lenguaje C/C++ desde un punto de vista práctico, trabajando en base a proyectos. Lo primero es lo primero, jeje, así que... ¿Qué necesitamos para aprender C? 

Primero que todo, necesitamos entender que nuestro código fuente necesita ser interpretado por un programa que lo transforme luego a un lenguaje de máquina... esa es la gracia de los lenguajes de programación, que el programador no se meta con el lenguaje binario, o sea, que pueda decir "printf" cuando quiere imprimir, y no 10110101 00100010 10001010 (sea lo que signifique lo anterior). Esto es, necesitamos un "compilador". ¿Qué compilador vamos a usar?

Para efectos prácticos podremos pensar en uno que sea "multiplataforma" o que tenga versiones para cada rama de sistema operativo que tengamos, esto quiere decir, que funcione bajo window$ o GNU/Linux o Mac, etc. En mi caso, elegiré Code Blocks. (insisto, hay otros más, solo es una elección personal).

Una vez instalado Code Blocks, procedemos a ir a Archivo, nuevo, archivo fuente y escribimos lo siguiente:

#include

int main(){

printf("Hola Mundo, ya comencé a programar");

return 1; 


Luego, vamos a la opción "compilar" y luego, ejecutar. Si todo está escrito bien, debería aparecernos en la ventana de salida el mensaje "Hola mundo, ya comencé a programar".

miércoles, 30 de junio de 2010

¿Cuál es el alumno más alto?

Por fin alguien envió un problema... en fin, el enunciado es algo así:

Se necesita saber cuál, de una serie de alumnos, es el más alto, para esto, se ingresarán sus datos y el programa escrito en C, debe retornar el nombre.

En general, esto se hace con un arreglo struct, en donde se van almacenando los datos y luego se corre una pequeña función para ir buscando el mayor, pero sin struct, se puede hacer, simplemente, almacenando la altura y preguntando por las siguientes, en caso de que se ingrese una altura mayor, se reemplazarán los datos almacenados, si no, se ingresarán los nuevos datos. Solo es importante conservar el nombre y la altura del mayor. Para empezar, un pequeño truco, inicializamos la variable altura en "0" (cero) de tal manera que la primera de las ingresadas sea la mayor y luego se sigue con las demás. 

Existen opciones con respecto al ingreso de datos, se podrían pedir entradas hasta terminar un número determinado (idea chanta, a mi juicio) o bien preguntar  "¿desea seguir comparando alumnos?" o algo así, lo cual es un tanto lento, pero por lo menos da la oportunidad de cerrar la aplicación a cada instante. 

Plan general:

//Inicializar variables:
altura_alumno = 0;
mas_alto = 0;

nombre_alumno_alto[MAXNOMBRE];

nombre_alumno[MAXNOMBRE];

//ingreso de estudiantes

//inicio del ciclo
Ingreso de nombre y almacenar en nombre_alumno
Ingreso de altura y almacenar en altura_alumno

//condición
¿altura_alumno es mayor que mas_alto?
Si es sí: mas_alto = altura_alumno
asignar a nombre_alumno_alto el contenido de nombre_alumno 

//esto se hace con un función  o bien un ciclo, elemento a elemento, no olvidar el nulo al final

Si es no: volver a inicio del ciclo

//fin del ciclo

//Cuando termine el ciclo
Presentar datos, mas_alto y altura_alumno

//fin programa

Muy pronto el código, pero con lo anterior, está más claro que el agua :D


Ahora el código lo pueden descargar desde aquí

jueves, 10 de junio de 2010

Encuentro de ajedrecístas

El problema se trata de crear un programa que coordine la asistencia al evento anual de ponencias de ajedrez. Los oferentes se dividen en "educación" y "clínicas". Se deben asignar sedes y horarios, así como también llevar un control en cuanto a pagos.

Este problema lo realizaré paso a paso, espero comentarios para apoyar la realización. ¡ah! se me olvidaba, usaremos C++ y obviamente todo lo haremos orientado a objetos :D


lunes, 31 de mayo de 2010

Dimensionado de planchas

Es útil escuchar. A veces el entorno nos entrega situaciones... problemas para algunos, oportunidades para mí, de "algo" que se podría mejorar... es el caso del siguiente problema:

Para diversos usos en el campo de la construcción civil, es necesario completar sectores, sean planchas, concreto, etc. Se conoce el alto y el ancho de lo que se requiere cubrir (el espacio total); se conoce también lo que ya está cubierto, por ejemplo, con trozos de concreto o bien con pedazos (rectangulares) de malla; solo falta conocer el trozo exacto, el alto y ancho, del material que falta.

Entonces, el programa debe generar la salida, el alto y ancho, de lo que falta, haciendo coincidir o cubriendo un espacio total con lo que ya se tiene, o sea: Salida = Total - Lo_que_se_tiene.

Actualmente, este programa ya existe y es usado por una empresa, solo si los clientes compran el trozo faltante ahí. La idea transversal de este ejercicio, es liberar el código, para que todas las personas tengan la libertad de elegir dónde comprar sus materiales para conseguir el área que les falta.

¿Se animan?

lunes, 24 de mayo de 2010

¡Manden sus preguntas!

De una conversación informal nació la idea de reflotar este espacio, así que envíen sus dudas para ir generando comunidades de aprendizaje en torno al lenguaje C/C++.

domingo, 16 de agosto de 2009

Problemas de la vida diaria: Campeonato de fútbol escolar

En una reunión de Chile Deportes se elegían los grupos que conformarían la final regional de fútbol escolar. Una persona, armada de un proyector (data show) y un notebook, lo  último de HP, iba rellenando tablas hechas en word 2007 (puaj!) con el nombre de los establecimientos que participarían, copiando y pegando a su vez, de una lista que se completó con los representantes presentes en el evento. Los números de las tablas, eran elegidos "al azar" desde una tómbola, de esas que uno compra en la feria para jugar loteria (puaj 2). ¿Tanta tecnología invertida para tan poco? pensé entre mí.

Mi afán no era el fútbol, yo esperaba el ajedrez, pero cuando ví cuánto se demorarían se me ocurrió crear un programa que hiciera "la misma pega", pero mucho más rápido. Claro, si le aplicaba C al asunto, todo andaría mejor. Entonces, en su primera versión, arreglos; en su segunda versión, arreglos y archivos y en su tercera versión, objetos y archivos. ¿qué tal?

Requerimientos:
  • Almacenar nombres de establecimientos, de un largo no mayor a los 60 caracteres, con sus respectivos números de lista
  • Asignar a ciertos establecimientos previamente ingresados la calidad de cabezas de serie (estos no van al sorteo)
  • Crear una función que tome la lista de los establecimientos y elija aleatoriamente, solo entre los que no son cabezas de serie, aquellos que van a ir rellenando las tablas
  • Supondremos un total de 30 establecimientos, 5 grupos de 6.


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.