miércoles, 13 de julio de 2011

Extra: programa de clase modificado "pilas"







Aqui esta el programa visto en clase modificado como creí conveniente para hacer una pila.

#include <stdio.h> // imprimir (printf)
#include <stdlib.h> // reservar memoria
#include "pilas.h"

elem* borrar(elem* esto) {
  elem* temp; 
  while (esto != NULL) {
    temp = esto->siguiente;
    free(esto);
    esto = temp; 
  }
  return NULL; 
}

bool buscar(int valor, elem* aqui) {
  if (aqui != NULL) {

    #ifdef DEBUG 
    printf("Buscando por %d en %d.\n", 
       valor, aqui->dato);
#endif 

        if (aqui->dato == valor) {

#ifdef DEBUG
      printf("Son iguales.\n");
#endif

      return TRUE; 

    } else if (aqui->dato > valor) {
      

#ifdef DEBUG
      printf("Ya es mayor. No va a estar.\n");
#endif

      return FALSE; 
    }
    return buscar(valor, aqui->siguiente);
  } else { 

#ifdef DEBUG
    printf("Ya se acabo. No estuvo.\n");
#endif
    return FALSE; // busqueda fallida
  }

}

bool eliminar_elemento(int valor, elem* aqui, 
               elem** inicio) {
  if (aqui != NULL) { // si hay algo
    if (aqui->dato == valor) {
      // hay que borrar el elemento
      if (aqui->siguiente != NULL) {
    aqui->siguiente->anterior = 
      aqui->anterior; 
      }
      if (aqui->anterior == NULL) {
    *inicio = aqui->siguiente;
      } else {
    aqui->anterior->siguiente = 
      aqui->siguiente;
      }
      free(aqui); // borrame
      return TRUE; // eliminacion exitosa
    } else if (aqui->dato > valor) {
      return FALSE;
    }
    return eliminar_elemento(valor, 
                 aqui->siguiente, 
                 inicio);
  }
  return FALSE;
}

// interface para llamadas mas bonitas
bool eliminar(int valor, elem** inicio) {
  return 
    eliminar_elemento(valor, *inicio, inicio);
}

void imprime_elemento(elem* esto) {
  // iterativa
  while (esto != NULL) {
    printf("%d ", esto->dato);
    esto = esto->siguiente;
  }
  return;
}

// interfase que agrega [ ... ] y el \n
void imprimir(elem* lista) {
  printf("[ ");
 imprime_elemento(lista);
  printf("]\n");
  return;
}

elem* agregar(int valor, elem* aqui) {
  elem* nuevo = NULL;

if (aqui != NULL) {
    printf("Estoy en %d, insertando un %d.\n",
       aqui->dato, valor);
  } else {
    printf("No hay nada.\n");
  }


  if (aqui == NULL) { // no hay nadie
    nuevo = (elem*)malloc(sizeof(elem));
    nuevo->dato = valor; // asignar dato
    nuevo->siguiente = NULL; // el unico
    nuevo->anterior = NULL; // el unico
    return nuevo;
  } else {
    if (valor < aqui->dato) {
      nuevo = (elem*)malloc(sizeof(elem));
      nuevo->dato = valor; // pon el valor
      
    // aqui es el primer elemento
    nuevo->siguiente = aqui;
    aqui->anterior = nuevo;
    nuevo->anterior = NULL; 
    return nuevo;
  int pseudoaleatorio() {
  return ((rand() % (MAX - MIN + 1)) + MIN);
    }

    


martes, 12 de julio de 2011

Extra: Ciclos

¿Cómo se logra que algo se repita?
Por medio de un ciclo o bucle que funciona de la siguiente manera: Evalúa una condición de resultar cierta, realiza una acción o bloque de acciones, luego vuelve a evaluar la condición y si nuevamente resulta cierta, realiza la (s) acción (es). Cuando la condición de cómo resultado falso, se sale del ciclo y continúa con la ejecución normal del programa.

¿Hasta cuándo va a repetirse?
Hasta que la condición asignada a dicho bucle deje de cumplirse, siempre y cuando dicha condición sea verdadera..


¿Qué opciones hay para crear repeticiones?

 Existen 3 estructuras repetitivas: While, For y Do .. While
  •  Estructura While

Sintaxis:

while (condición)
        Acción;  //Se ejecuta mientras condición se evalua verdadera (distinta de 0)

En el caso de que el cuerpo del while (acciones a ejecutar en caso de que el condicional se verifique) posea más de una sentencia, todas ellas son encerradas entre llaves:

while (condición)
{
Acción1;
Acción2;
...
}

El condicional es una expresion relacional que puede involucrar operadores relacionales (>, <, >=, <=, ==, !=) y/o operadores logicos (&&, ||, !)

Ejemplo:



/*Programa que imprime la tabla de conversión de
Fahrenheit a Celsius para F = 0, 20, 40,..., 300 */

#include  

 int main(int argc, char** args){

 int Lower, Upper, Step;
 float Fahr, Celsius;

  Lower = 0;     /* límite superior de la tabla de temperaturas*/
  Upper = 300;   /*límite superior*/
  Step = 20;     /* tamaño del incremento*/
  
  Fahr = Lower;
   
  while(Fahr <= Upper){

     Celsius = (5.0/9.0) * (Fahr - 32.0);

     printf("%4.0f F -> %6.1f C\n", Fahr, Celsius);

     Fahr = Fahr + Step;

     } 
return 0;
} 


Nota: Lo que se encuentra entre parentesis es una expresión a evaluar. Mientras el resultado de la misma sea distinto de cero, se ejecutan las sentencias asociadas que se encuentran encerradas entre llaves. A este tipo de sentencias se las llama sentencias compuestas. Si el cuerpo de esta sentencia consiste en una sola sentencia simple, pueden omitirse las llaves. Las sentencias compuestas no llevan el caracter ; como terminador. Para mejorar la legibilidad del programa, conviene indentar las sentencias compuestas.

  • Estructura For

Esta estructura es una generalización de la estructura while. Su función es ejecutar iterativamente el cuerpo del bloque, que como en el caso del while puede ser simple o compuesto. La definición de esta estructura de control posee 3 partes separadas por el caracter ";".

for(inicialización; condición ; reinicialización) 
{ ... ...}

La inicialización puede poseer una sentencia, ninguna, o varias separadas por el caracter ",". Esta parte se ejecuta inmediatamente antes de entrar en el ciclo.

El criterio o condición de control de la iteración. Se evalúa antes de entrar a cada ciclo, inclusive en la primer iteración. Si su resultado es distinto de cero se ejecuta el ciclo; sino se abandona el ciclo y se sigue con la sentencia posterior al cuerpo del for.

La reinicialización, que es ejecutada al final de cada ciclo.


Podemos simular el bloque for con la siguiente lógica:
 
a;
while(b){... ...  c;}




/* Tabla de conversión de grados F a Celsius
utilizando constantes simbolicas y bloque for */

#include 


#define LOWER 0
#define UPPER 300
#define STEP 20

int main(int argc, char** args){

  int Fahr;

    for(Fahr = LOWER; Fahr <= UPPER; Fahr += STEP)

     printf("%4.0f F -> %6.1f C\n", Fahr, (5.0/9.0)*

             (Fahr - 32))
}


Nota:
Uso de constrantes simbolicas. Cuando se requieran valores numericos constantes en un programa, deben definirse como constantes y no usar sus valores numéricos dentro del programa. C permite definir constantes simbolicas (directiva #define al preprocesador) que asocian un simbolo (LOWER, UPPER, STEP) con una expresión (0,300 y 20 respectivamente) de tal manera que el preprocesador reemplaza cualquier ocurrencia de esos simbolos por sus expresiones asociadas.

  • Estructura Do-While


La estructura de control do-while es una variación sobre el bloque while
 
do{ Acción1; Acción2; ...}while(condición);

La diferencia esta en que la condición se chequea al final y las acciones son ejecutadas al menos una vez.

viernes, 8 de julio de 2011

Tarea 4: Ciclos ( Extra )



Diseñe un programa, que dado un ángulo, muestre su seno, coseno o tangente; según lo desee el usuario.
#include 

#include 

void seno (float angulo);

void coseno (float angulo);

void tangente (float angulo);

main()

{

float angulo;

int opcion, ban=1;

clrscr();

while(ban==1)

{

printf("\t\tBIENVENIDO/A\n\n");

printf("Introduzca el valor del angulo, por favor:\n");

scanf("%f", &angulo);

printf("¨Que desea hacer?:\n\n");

printf("********************************************\n");

printf("**** 1. seno del angulo ****\n");

printf("**** 2. coseno del angulo ****\n");

printf("**** 3. tangente del angulo ****\n");

printf("********************************************\n");

scanf("%d", &opcion);

while(opcion<0 || opcion>3)

{

printf("ERROR, la opcion debe estar entre 0 y 3:\n");

scanf("%d", &opcion);

}

clrscr();

switch(opcion)

{

case 1: seno (angulo);

break;

case 2: coseno (angulo);

break;

case 3: tangente (angulo);

break;

}

printf("¨Hay mas datos? (si=1 y no=0)\n");

scanf("%d",&ban);

}

getch();

return 0;

}

void seno (float angulo)

{

float y;

y=sin (angulo);

printf("El seno de %f es %f\n\n", angulo, y);

}

void coseno (float angulo)

{

float y;

y=cos(angulo);

printf("El coseno de %f es %f\n\n", angulo, y);

}

void tangente (float angulo)

{

float y;

y=tan(angulo);

printf("La tangente de %f es %f\n\n", angulo, y);

getch();

}

jueves, 7 de julio de 2011

Extra: Compilación vs interpretacón

¿Qué en sí es una computadora?

También denominada ordenador o computador, es una máquina electrónica que recibe y procesa datos para convertirlos en información útil.

¿Cómo comunicamos con ella? 

El ordenador posee dispositivos de entrada y salida (E/S) que permiten a los usuarios interactuar con la información que éste procesa. Este procesamiento de datos es mucho más amplio que apenas calcular números o imprimir datos. Es posible escribir notas e informes, proyectar, realizar complejos cálculos de ingenieria, utilizarla como medio para la creación de obras fotográficas, musicales y de video y por supuesto interactuar con otras personas.

Los Dispositivos de Entrada son aquellos a través de los cuales se envían datos externos a la unidad central de procesamiento, como el teclado, ratón, escáner, o micrófono, entre otros.

Los Dispositivos de Salida son aquellos que reciben los datos procesados por la computadora y permiten exteriorizarlos a través de periféricos como el monitor, impresora, escáner, plotter, altavoces,etc.

Los Dispositivos de Entrada/Salida (Periféricos mixtos): Hay dispositivos que son tanto de entrada como de salida como los mencionados periféricos de almacenamiento, CDs, DVDs, así como módems, faxes, USBs, o tarjetas de red.

¿Cómo se puede lograr que eso sea más fácil?

La interfaz de usuario es el medio con que el usuario puede comunicarse con una máquina, un equipo o una computadora, y comprende todos los puntos de contacto entre el usuario y el equipo, normalmente suelen ser fáciles de entender y fáciles de accionar. Las interfaces básicas de usuario son aquellas que incluyen elementos como menús, ventanas, teclado, ratón, los beeps y algunos otros sonidos que la computadora hace, y en general, todos aquellos canales por los cuales se permite la comunicación entre el ser humano y la computadora. La mejor interacción humano-máquina a través de una adecuada interfaz (Interfaz de Usuario), que le brinde tanto comodidad, como eficiencia.

¿Que herramientas ocupamos nosotros?

El Software y el Hardware

¿Porqué justamente esas?

El ordenador se compone de un Software y  un Hardware que deben funcionar en conjunto para lograr que la computadora realice los trabajos para los que fue creada. El software hace que una computadora tenga vida y se comporte de la manera que todos conocemos, el hardware que hay no puede funcionar si no hay software que hacen que este trabaje de manera adecuada.

¿Que hacen y como funcionan?

Hardware: Son los componentes físicos de un computador. Es lo que se puede tocar. Ejemplo de estos son: monitor, teclado, ratón o mouse, impresora, escáneres, cámaras, etc.

Software: Es la parte lógica necesaria para que una computadora trabaje, esto permite que el hardware realice las tareas que el usuario necesite, es decir, es la interfaz entre el usuario y los componentes electrónicos que tiene la computadora.
Se divide en:
Software del sistema: son los programas que permiten la conexión directa del usuario con la computadora, estos se puede decir que son vitales para la utilización de la computadora. Es el que va a codificar los mensajes hechos con un click y transportarlos al hardware. Ejemplo de estos son: Linux, Windows, Unix, Ubuntu, entre otros.
Software de desarrollo: como su nombre lo indica, son los programas que permiten el desarrollo de aplicaciones, algunos de estos son java, visual basic, c++, entre otros.
Software de aplicación: son los programas que nos permiten hacer aplicaciones, trabajos, diseño gráfico, entretenimiento, etc. Alguno de estos son: Microsoft Office, Windows Media Player, Corel Draw, OpenOffice, OpenOffice Drawn, entre otros.

martes, 5 de julio de 2011

Programa con sentencia if-else



Este programa imprime sí un número N es par o impar y al mismo tiempo si es positivo o negativo.
#include 

int main(int argc, char** args){

  int N;

  printf("Teclee un número\n");

  scanf("%d", &N);

  if(N>0){

    printf("El numero es positivo\n");

  }

    else{

      printf("El numeroes negativo\n");

    }

      if(N%2==0){

    printf("El numero es par\n");

      }

      else{

    printf("El numero es impar\n");

      }

      return 1;

}

Extra: Sentencias


La sentencia For

La sentencia for tiene el siguiente formato: 

for ( expresion1; expresion2; expresion3)sentencia; 

bloque de sentencias }
En donde expresion1 se usa para realizar la inicialización de variables, usando una o varias sentencias, si se usan varias sentencias deberá usarse el operador , para separarlas. Por lo general, establece el valor de la variable de control del ciclo. expresion2 se usa para la condición de terminación del ciclo y expresion3 es el modificador a la variable de control del ciclo cada vez que la computadora lo repite, pero también puede ser más que un incremento.
Por ejemplo:

int X;
main()

{
for( X=3; X>0; X--) {
printf("X=%d\n",X); 
}
}

Lo cual genera la siguiente salida a pantalla ...    X=3 X=2 X=1

La Sentencia While

La sentencia while es otro ciclo o bucle disponible en C. Su formato es: 
while ( expresion) sentencia; 
donde sentencia puede ser una sentencia vacía, una sentencia única o un bloque de sentencias que se repetirán. Cuando el flujo del programa llega a esta instrucción, primero se revisa si la condición es verdad para ejecutar la(s) sentencia(s), y después el ciclo while se repetirá mientras la condición sea verdadera. Cuando llega a ser falsa, el control del programa pasa a la línea que sigue al ciclo.

En el siguiente ejemplo se muetra una rutina de entrada desde el teclado, la cual se cicla mientras no se pulse A:

main()
{
char carac;
     carac = '\0';    while( carac != 'A') carac = getchar();
}


Antes de entrar al ciclo se inicializa la variable carac a nulo. Después pasa a la sentencia whiledonde se comprueba si carac no es igual a 'A', como sea verdad entonces se ejecuta la sentencia del bucle (carac = getchar();). La función getchar() lee el siguiente carácter del flujo estándar (teclado) y lo devuelve, que en nuestro ejemplo es el caracter que haya sido tecleado. Una vez que se ha pulsado una tecla, se asigna a carac y se comprueba la condición nuevamente. Después de pulsar A, la condición llega a ser falsa porque carac es igual a A, con lo que el ciclo termina.
De lo anterior, se tiene que tanto el ciclo for, como el ciclo while comprueban la condición en lo alto del ciclo, por lo que el código dentro del ciclo no se ejecuta siempre.

Como se observa, dentro del ciclo tenemos más de una sentencia, por lo que se requiere usar la llave abierta y la llave cerrada { ... } para que el grupo de sentencias sean tratadas como una unidad.
Como el ciclo while pueda aceptar también expresiones, y no solamente condiciones lo siguiente es válido:
while ( x-- );
while ( x = x + 1 );

Al contrario de los ciclos for y while que comprueban la condición en lo alto del bucle, el bucledo ... while la examina en la parte baja del mismo. Esta característica provoca que un ciclo do ... while siempre se ejecute al menos una vez. La forma general del ciclo es: 


do {
sentencia;
} while (condición);

Aunque no son necesarias las llaves cuando sólo está presente una sentencia, se usan normalmente por legibilidad y para evitar confusión (respecto al lector, y no del compilador) con la sentencia while.
En el siguiente programa se usa un ciclo do ... while para leer números desde el teclado hasta que uno de ellos es menor que o igual a 100:


main()
{
int num;
do 
{
scanf("%d", &num); } while ( num>100 );
}
Otro uso común de la estructura do ... while es una rutina de selección en un menú, ya que siempre se requiere que se ejecute al menos una vez.

main()
{
int opc;
printf("1. Derivadas\n");
do {  
printf("3. Integrales\n);
printf("2. Limites\n");

printf("Teclear una opcion:");
switch(opc)  
scanf("%d", &opc);
case 1:
printf("\tOpcion 1 seleccionada\n\n");  
break;
case 2:
printf("\tOpcion 2 seleccionada\n\n");  
break;  
case 3:
printf("\tOpcion 3 seleccionada\n\n");
break;
default:                
printf("\tOpcion 3 seleccionada\n\n");
break;

}
    } while( opc !=1 &&  opc != 2  &&  opc != 3);
}
Se muestra un ejemplo donde se reescribe usando do ... while uno de los ejemplos ya mostrados.


main()
{
int x=3;
do { 
printf("x = %d\n", x--);
} while( x>0 ) ;}


Uso de Break y Continue


Como se comento uno de los usos de la sentencia break es terminar un case en la sentenciaswitch. Otro uso es forzar la terminación inmediate de un ciclo, saltando la prueba condicional del ciclo.
Cuando se encuentra la sentencia break en un bucle, la computadora termina inmediatamente el ciclo y el control del programa pasa a la siguiente sentecia del ciclo. Por ejemplo:

main()
{
int t;
for(t=0; t<100; t++)
{
printf("%d ", t); if (t==10) break;
}
}
sentencia if-else
La forma general de esta sentencia es:
if (expresion)
        sentencia 1
else
        sentencia 2
\includegraphics[width=8cm]{im/sintaxis/if-else.eps}
  • Si expresion es verdadera (valor distinto de 0), entonces se ejecuta sentencia 1; en caso contrario, se ejecuta sentencia 2.
  • Si las sentencias son compuestas se cierran entre { }.
  • Las sentencias pueden ser a su vez sentencias if-else.
             if (expresion 1)
                  if (expresion 2)
                       S1 
                  else
                      S2
         else
           S3


Un ejemplo de uso de esta sentencia es el siguiente fragmento de programa, que elige el menor de tres números:


float a, b, c, menor;
a=2; b=4; c=1;

if (a < c) if (a < b) {
  
menor = a;
  
else
if (b < c) menor = c;
} else {

= b; else
     menor
        menor = c;
}

jueves, 30 de junio de 2011

Tarea 2: Operaciones Binarias

Se define como operación binaria aquella operación matemática que necesita el operador y dos operandos (argumentos) para que se pueda calcular un valor.

  •  Conversión de Decimales a Binario, binario a Octal y de binario a Hexadecimal
    Para realizar la conversión de binario a decimal se hace lo siguiente:
  1. Se inicia por el lado derecho del número en binario, c
  2. Cada número se multiplica por 2 y se eleva a la potencia consecutiva (comenzando por la potencia 0).
  3. Después de realizar las multiplicaciones se suman todas y el número resultante será el equivalente al sistema decimal.
Ejemplo:
  • 110101 (binario) = 53 (decimal). 
Proceso:

1*(2) elevado a (0)=1
0*(2) elevado a (1)=0
1*(2) elevado a (2)=4
0*(2) elevado a (3)=0
1*(2) elevado a (4)=16
1*(2) elevado a (5)=32
La suma es: 53

  • Decimal a binario

  Para realizar la conversión de decimal a binario se hace lo siguiente:
1. Se divide el número decimal entre 2 y el resultado entero se vuelve a dividir entre 2 y así sucesivamente.
2. Una vez llegado al 1 indivisible se cuentan el último cociente, es decir el uno final (todo número binario excepto el 0 empieza por uno), seguido de los residuos de las divisiones subsiguientes.
3. El número generado de apartir del último al primero será el binario que buscamos. A continuación se puede ver un ejemplo con el número decimal 100 pasado a binario.
100 |_2
 0   50 |_2
      0  25 |_2         --> 100 \Rightarrow 1100100
          1  12 |_2
              0  6 |_2
                 0  3 |_2
                    1  1
  • Binario a octal

Para realizar la conversión de binario a octal, realice lo siguiente:
1) Agrupe la cantidad binaria en grupos de 3 en 3 iniciando por el lado derecho. Si al terminar de agrupar no completa 3 dígitos, entonces agregue ceros a la izquierda.
2) Posteriormente vea el valor que corresponde de acuerdo a la tabla:
Número en binario 000 001 010 011 100 101 110 111
Número en octal 0 1 2 3 4 5 6 7
3) La cantidad correspondiente en octal se agrupa de izquierda a derecha.
Ejemplos:
  • 110111 (binario) = 67 (octal). Proceso:
111 = 7
110 = 6
Agrupe de izquierda a derecha: 67

  • Binario a hexadecimal

Para realizar la conversión de binario a hexadecimal, realice lo siguiente:
1) Agrupe la cantidad binaria en grupos de 4 en 4 iniciando por el lado derecho. Si al terminar de agrupar no completa 4 dígitos, entonces agregue ceros a la izquierda.
2) Posteriormente vea el valor que corresponde de acuerdo a la tabla:
Número en binario 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Número en hexadecimal 0 1 2 3 4 5 6 7 8 9 A B C D E F
3) La cantidad correspondiente en hexadecimal se agrupa de izquierda a derecha.
Ejemplos:
  • 110111010 (binario) = 1BA (hexadecimal). Proceso:
1010 = A
1011 = B
1 entonces agregue 0001 = 1
Agrupe de izquierda a derecha: 1BA

Existen varios tipos de operadores por ejemplo
  • Los operadores aritméticos pertenecen a dos grupos: unos aceptan operandos de tipo numérico; otros aceptan operando de tipo puntero. Además son de dos tipos; unarios (que aceptan un solo operando) y binarios (que aceptan dos). La clasificación es la siguiente:
Operadores aritméticos unarios:
+    más unitario.
++    Incremento unitario (dos clases)
-       menos unitario.
--      Decremento unitario (dos clases)
Operadores artiméticos binaros:
+       Suma binaria.
-        Resta binaria.
*        Multiplicación
/        División.
%      Resto o módulo.
Estos últimos pueden combinarse con el de asignación = para dar origen a operadores compuestos son los siguientes:
+=       Asigna suma
-=        Asigna diferencia (resta)
*=        Asigna producto
/=        Asigna división
%=       Asigna resto (módulo)

 El lenguaje C proporciona seis operadores para manejo de bits; solo puden aplicados a operandos integrales, esto es char, short, int y long, con o sin signo.
  • El operador binario AND  (&) calcula la operación “y” bit a bit. 
  • El operador binario  OR (|)  calcula la operación “o” bit a bit  
  • El operador binario (^) calcula la operación “o exclusiva”, la diferencia con la anterior es que la “o exclusiva” devuelve True si y sólo si los dos operandos son falsos.
  • El operador unario (~) invierte los bits de su operando.
Tienes además, los operandos binarios (<< , >> ), que desplazan los bits a izquierda o derecha tantas posiciones como se las indiques.

Aquí un ejemplo que ayudará a entender estos operadores.