el recurso de c

153

Upload: wuicho-pereyra

Post on 11-Nov-2015

223 views

Category:

Documents


0 download

DESCRIPTION

Lenguaje C

TRANSCRIPT

  • Tabla de ContenidoPrlogo....................................................................................................................4

    Prlogo del 2003.................................................................................................4Prlogo del 2014.................................................................................................4

    PARTE I: LO MS BSICO....................................................................................5Introduccin........................................................................................................5Conceptos generales..........................................................................................5Variables y constantes........................................................................................5Instrucciones de entrada / salida........................................................................6Secuencias de escape.....................................................................................11Aritmtica en C.................................................................................................11Archivos de inclusin........................................................................................17Variables globales y locales y reglas de alcance.............................................18

    PARTE II: PROGRAMACIN ESTRUCTURADA................................................20Condicin if-else...............................................................................................20Condicin switch-case......................................................................................23Ciclo for.............................................................................................................25Ciclo while.........................................................................................................29Ciclo do-while...................................................................................................30

    PARTE III: FUNCIONES.......................................................................................33PARTE IV:ARREGLOS Y ESTRUCTURAS.........................................................44

    Arreglos unidimensionales...............................................................................44Arreglos de tamao no predefinido..............................................................57

    Arreglos de dos o ms dimensiones................................................................59Arreglos con tamao no predefinido............................................................65

    Arreglos de ms dimensiones..........................................................................67Estructuras........................................................................................................69Cadenas de caracteres....................................................................................72

    PARTE V: APUNTADORES..................................................................................76Apuntadores a variables...................................................................................77Apuntadores y funciones..................................................................................79Apuntadores y arreglos....................................................................................82Arreglos de apuntadores..................................................................................87Argumentos de la lnea de comandos..............................................................92

    PARTE VI: ARCHIVOS.........................................................................................93PARTE VII: MEMORIA DINMICA.....................................................................108

    Listas enlazadas simples................................................................................108rboles binarios..............................................................................................116

    APNDICE A: LA BIBLIOTECA ESTANDAR.....................................................136stdio.h.............................................................................................................136

    Archivos......................................................................................................136Salida con formato.....................................................................................137

  • Entrada con formato...................................................................................138Entrada y salida de caracteres...................................................................139Funciones de entrada y salida directa.......................................................140Funciones de colocacin en archivos........................................................140Funciones de error.....................................................................................141

    string.h............................................................................................................141math.h.............................................................................................................142stdlib.h.............................................................................................................144assert.h...........................................................................................................145time.h..............................................................................................................145

    APNDICE B: ALGUNOS PROBLEMAS PROPUESTOS.................................146APNDICE C: RECOMENDACIONES Y TEMAS NO VISTOS.........................149

    3

  • Prlogo

    Prlogo

    Prlogo del 2003Antes que nada quiero agradecer a las personas que me apoyaron para publicareste libro, la Lic. Ana Gabriela Hernandez, la Ing. Karina Requena, el Ing Juan Carlos Saenz, el Ing. Claudio Arzola, el Ing. Jess Valles y a Luz Cristina Hernandez, que hizo la portada.

    El libro lo escrib pensando en algo que fuera lo ms claro posible y que fuera directo al punto, en lo personal no me gustan los libros donde lo que abunda es la paja, y segn yo, creo y deseo que este prlogo sea la nica paja que tenga este libro. Hablando de la claridad y de ir directo al grano, este libro no abunda en ejemplos, presenta un ejemplo que pretenda ilustrar lo ms posible el tema y lo explica a profundidad. Por eso a lo largo del libro recomiendo crear situaciones distintas y practicar lo ms que se pueda, porque el libro te dice cmo hacer las cosas, pero no tiene un ejemplo para cada cosa distinta. El libro no es para nada largo, al contrario, por lo mismo recomiendo que se lea completo no es la gran biblia de C, pero si lo lees completo tendrs una plataforma bastante slida en los aspectos fundamentales (o sea los ms importantes) del lenguaje. Es preferible que tengas algo de experiencia con algn otro lenguaje de programacin o con el diseo de algoritmos, pero no es del todo necesario, solo necesitaras poner ms atencin.

    Es tiempo de terminar con este prologo, si bajaste el libro desde Internet o lo copiaste en un disco lo puedes regalar a quien t quieras, pero no lo modifiques ni lo plagies. Aunque no es un sper libro ni te cost mucho adquirirlo implic un trabajo para m, un trabajo que espero que valores y que te sea muy til. Disfrutaentonces el libro y salo bien, mucha suerte :) ...

    Prlogo del 2014Hace muchos aos que escrib este pequeo libro, era estudiante de quinto semestre de ingeniera y no tena la formacin que tengo ahora, aunque quiz tena ideas ms frescas. Este libro, a pesar de sus errores, pareci gustarle a la gente. Hace tiempo que doy clases de programacin y pens que podra utilizarlo como material de texto, igual el trabajo ya estaba hecho. Se le hicieron un algunas correcciones, sobre todo en ortografa, adems se incluyeron algunas notas y actualizaciones a la versin C11, lo dems qued prcticamenteigual, este librito ya tena su esencia. Espero que te sirva, es gratis!

    4

  • PARTE I: LO MS BSICO

    PARTE I: LO MS BSICO

    Introduccin.El lenguaje C lo escribieron Dennis Ritchie y Brian Kernigham cuando trabajabancon Ken Tompsom en el desarrollo de una nueva versin del sistema UNIX, en los laboratorios Bell, o sea que C se escribi para escribir UNIX. C es un lenguaje muy compacto porque el ejecutable que resulta es muy pequeo, es muy potente y flexible, aparte de que tiene gran portabilidad porque un cdigo que se escribe para un sistema en particular puede correr sin modificaciones, o con muy pocas, sobre otro sistema diferente, aparte de que es independiente delhardware. C es un lenguaje muy pequeo en el sentido de que no tiene muchas instrucciones, lo que lo hace amplio es su biblioteca de funciones, que es algo que lo hace muy flexible porque uno puede escribir su propia librera de funciones y usarla en los programas.

    Algo que quiero aclarar es que mucha gente trata a C y a C++ como la misma cosa, esa gente se equivoca. El lenguaje C es un lenguaje imperativo, se basa en una secuencia de rdenes para simular o para resolver problemas, pero el lenguaje C++ es un lenguaje orientado a objetos, nada que ver. La forma de manejar varios aspectos en C es diferente a la de C++. C++ ofrece varias cualidades que C no tiene y viceversa, as que hazte a la idea de que este libro es de C y no de C++.

    Conceptos generales.Las fases para hacer un programa son teclear un cdigo fuente, compilarlo a cdigo objeto, y finalmente se enlaza para obtener un ejecutable.1

    El cdigo fuente es un archivo de texto que contiene todas las instrucciones que han de ejecutarse para alcanzar la meta que el programador desea. El compilar un programa es transformar todas las instrucciones del programa a un lenguaje que la computadora pueda entender. Este cdigo objeto tiene referencias a otrasfunciones y datos externos, o sea que no estn incluidos en el mismo cdigo fuente, que al momento de enlazarlo se junta con los otros programas objetos delos archivos que se necesiten para que el programa funcione. Y por ltimo tenemos el programa ejecutable que es un cdigo que la mquina puede entender y ejecutar.

    Variables y constantes.En un programa, y supongo que ya sabes ms o menos qu es un programa y cmo se compone, hay valores que pueden cambiar o que deben admitir datos

    1 Hablando en trminos muy generales para un lenguaje de tipo compilado.

    5

  • PARTE I: LO MS BSICO

    que el usuario necesite, como la temperatura, el promedio de una persona o lo que sea, estos datos son variables y pues siempre estn sujetos a sufrir cambios, por otro lado tenemos valores que no deben cambiar como la constante o algn parmetro importante para que el programa funcione bien.

    Tanto las variables como las constantes tienen tipos de datos, C tiene varios tipos de datos, pero los ms bsicos son:

    int: valor entero, pondra el rango admitido, pero depende en mucho del sistema.

    float: flotantes, nmeros como 3.14159 o 1.23 E16.

    char: caracter, han de saber que en C no hay tipo de datos "cadena", cmo guardar una palabra o algo as? Eso lo vemos despus.

    Al declarar una variable as se le permite cambiar en cualquier momento, en el caso de las que queremos que sean constantes se pueden declarar de la siguiente manera.

    const char letra = 'a';

    As el valor de letra no puede ser modificado por accidente.

    Las variables pueden tomar cualquier nombre, excepto los que sean palabras reservadas como switch o for, adems de que no deben contener smbolos como comillas o parntesis. La longitud no es limitante, pero por lo regular no deben de tener mas de treinta y dos letras, ms o menos, porque hay algunos compiladores que no soportan nombres ms largos. Otra condicin es que no empiecen con un nmero, aparte C es caso sensitivo, o sea que las minsculas no son iguales a las maysculas, por lo que Var es diferente que var, lo mismo aplica para todas las instrucciones, que deben estar en minsculas, y para los datos de entrada, as que no es lo mismo teclear e y E, son datos diferentes.

    Vamos a trabajar con esos datos por lo pronto para pasar a otros temas ms avanzados con ms facilidad.

    Instrucciones de entrada / salida.Hasta ahora podemos escribir, bueno no, no podemos, sabemos que hay tipos de datos y todo eso, pero cmo podemos pedir un valor o desplegarlo en la pantalla? Personalmente no pondra ese tema en este punto de mi "curso", pero voy a tratar de apegarme al mximo a lo que piden en la escuela.

    Se va a trabajar con dos funciones de entrada y salida, la funcin de salida va a

    6

  • PARTE I: LO MS BSICO

    ser printf y la de entrada va a ser scanf, por ejemplo una lnea como la que sigue.

    printf("Que demonios hace esto?");

    Imprime "Que demonios hace esto?" pero sin las comillas. Esas se ponen en la funcin para delimitar la cadena que se va a imprimir. Pero bueno vamos a juntarlo que hemos visto hasta ahora para escribir el primer programa en C. Por cierto,no pienso poner detalles acerca de cmo crear el cdigo fuente y de cmo compilarlo, eso tiene que ver de qu clase de compilador ests usando y pues no puedo adivinar.

    /*Esto es un comentario*/

    #include /*este es un archivo de cabecera, luego te explico, por ahora solo ponlo*/

    /*si este archivo el programa no hace nada*/

    int main(int argc, char **args)/*inicia la funcin principal, me choca decirlo, pero no preguntes solo ponlo as*/

    {

    printf("Hola mundo!!!");

    return 0;

    }

    Que bonito! Pero y eso de qu sirve? Por lo pronto teclea el programa y gurdalo con la extensin .c, ponle el nombre que quieras y consrvalo.

    /*esto es un comentario*/Es importante poner comentarios en los programas, para acordarnos que hicimos y que otras gentes puedan entender qu pasaba por nuestra mente cuando escribimos esas lneas de cdigo. Hay otra forma de poner comentarios, que es ms propia de C++, que no es lo mismo que C, pero a veces funciona. Esta forma es poner dos diagonales (//) al principio de cada lnea de comentario.

    7

  • PARTE I: LO MS BSICO

    #includeEsta parte es muy importante, aqu incluimos un archivo, que es el que tiene las funciones de entrada y salida, su nombre significa STandardD Input Output, la extensin .h se refiere a head o cabecera, se les llama as porque siempre se ponen a la cabeza del cdigo fuente. Hay muchos archivos de cabecera y ojal que los veamos despus.

    int main(int argc, char **args){ ... ... return 0;}En C todo se divide en funciones o segmentos de cdigo que hacen alguna tarea en especial, regresan algn tipo de valor o no regresan nada y tambin reciben datos o no, la funcin main es la directora de todas las dems, nada funciona sin ella, en este caso main regresa un valor entero (int) mediante la lnea return 0; esta vez solo regresa un 0, los valores que recibe se os pasa el sistema operativo.

    De vuelta con las funciones de entrada / salida, sabemos que un programa no sirve de nada si no regresa un resultado til, la cosa es cmo poner los nmerosy datos importantes en la salida o la entrada de nuestros programas, veamos el siguiente cdigo.

    #include

    int main(int argc, char **args)

    {

    int numero = 10; /*el nmero vale 10*/

    printf("el numero vale %d", numero);

    return 0;

    }

    8

  • PARTE I: LO MS BSICO

    Podrs ver la notacin "%d" al final de la cadena, esto le dice a la funcin que enese punto inserte el valor entero decimal que viene a continuacin, luego despus de la coma viene la variable que tiene que imprimir, no es tan complicado despus de todo. Ese mismo programa pudo haberse escrito as.

    ...

    int main(int argc, char **args)

    {

    printf("el numero vale %d", 10);

    return 0;

    }

    El resultado es el mismo, lo que a la funcin printf le interesa es recibir un valor entero, no le importa de donde venga. Hay ms formatos para imprimir diversos tipos de valores, son los que siguen.

    %d Imprimen un valor entero en notacin decimal.

    %x Valor entero de forma exadecimal.

    %o Pone un entero en notacin octal.

    %f Valor flotante.

    %c Imprime un caracter.

    No son todos los formatos de entrada / salida, pero s nos sacan de casi cualquier apuro.

    Vamos a ver como poner varias cosas dentro del mismo printf, mira el siguiente programa.

    #include

    int main(int argc, char **args)

    {

    int val = 5;

    char letra = 'o'; /*nota que el caracter se delimita por ' '*/

    9

  • PARTE I: LO MS BSICO

    printf("El numer%c es %d", letra, val);

    return 0;

    }

    Como ves, se pueden poner varios argumentos en la funcin printf y se van recogiendo en orden, o sea que si pongo printf("%d %f", 10.56, 4) es un error, sedebe poner printf("%d %f", 4, 10.56) en este programa vimos cmo colocar caracteres y cmo se inicializan, no pierdas el detalle de poner las comillas simples para encerrar el caracter que se va a poner.

    Los formatos de salida son los mismos que los formatos de entrada, con unas pocas diferencias, revisa el siguiente cdigo para aceptar valores desde el teclado.

    #include

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

    int num1, num2, num3; /*si, se pueden poner varias variables dentro de la misma declaracin*/

    printf(" Introduce un numero: ");

    scanf("%d", &num1);

    printf(" Introduce otros dos numeros: ")

    scanf("%d %d", &num2, &num3);

    printf("numero 1 = %d, numero 2 = %d, numero 3 = %d", num1, num2, num3);

    return 0;

    }

    Como podrs adivinar el primer scanf lee un numero entero y lo pone en "num1",el detalle de poner un & delante del nombre de la variable es muy importante, si no lo pones pues el nmero que metiste no se va a guardar en la variable, luego vemos qu significa ese smbolo. La parte ms complicada viene en el segundo scanf, vienen dos variables, aqu lo que pasa es que hay que poner el numero 2,un espacio y luego el numero 3, en lo personal no me gusta usar esa clase de

    10

  • PARTE I: LO MS BSICO

    formato, pero cada quien...

    Secuencias de escape.Si estuviste compilando y corriendo los programas, cosa que espero que hagas y que experimentes un poco, te aseguro que es la mejor forma de aprender. Si lohiciste te habrs fijado en lo feo que imprime las cosas, para eso tenemos unas secuencias de escape que nos permiten dar cierto formato a la impresin (tanto como una terminal lo permite), hay secuencias de escape para poner una nueva lnea, para retroceder sobre la lnea, etc., son los siguientes.

    \n Nueva lnea

    \t Tabulador horizontal

    \\ Diagonal inversa

    \v Tabulador vertical

    \' Apostrofe

    \r Regreso de carro

    \" Comillas

    \b Regresar un espacio

    \o Nmero octal, p Ej. \o25

    \f Avance de forma

    \x Nmero exadecimal, p Ej. \x16.

    Por ejemplo para escribir "hola mundo!!!" sin que el prompt empiece en la mismalnea y el programa quede medio difcil de entender se pone as.

    printf("\n\t\"Hola mundo!!!\"\n\n");

    Escribe algunos programas o lo que quieras donde puedas revisar las secuencias de escape para que veas cmo funcionan, ya que domines bien las funciones de entrada y salida vamos a ver cmo hacer operaciones con nmeros.

    Aritmtica en C.Se supone que ya sabes (muy poco) de cmo introducir variables y como

    11

  • PARTE I: LO MS BSICO

    imprimirlas, resulta ms o menos claro que la mayora de los programas deben realizar clculos numricos para que sirvan de algo, las operaciones que podemos hacer son las siguientes.

    Suma: su smbolo es "+", si queremos sumar dos nmeros la sintaxis es a+ b

    Resta: "-", a - b

    Multiplicacin: "*", igual que las dems, a * b

    Divisin: su smbolo es "/"

    Mdulo: Supongo que es algo ms o menos nuevo, su smbolo es "%", si queremos saber cual es el residuo de 5/2 pues escribimos 5 % 2, en este caso 5/2 = 2 y el residuo es 1

    Asignacin: El famossimo signo "igual" o "=", la asignacin se hace de derecha a izquierda. c = a + b est bien escrito, pero a + b = c no va a hacer exactamente lo que queremos

    Incrementos: Son operadores unitarios, o sea que solo se usan con una variable, no como la suma que requiere dos variables, escribir ++var es como decir "incrementa la variable var en uno antes de usarla", en cambioescribir var++ sera decir "usa la variable var y luego la incrementas en uno". Tambin se puede usar la resta poniendo --var o var--, pero as no se puede mostrar bien su funcionamiento, ser ms claro cuando veamosciclos.

    Tambin hay operadores para comparar, como el > (mayor que), o el

  • PARTE I: LO MS BSICO

    printf(" Escribe el numero a: ");

    scanf("%d", &a); /*como repaso: recuerda que %d significa entero decimal y noolvides el (&)*/

    printf(" Bien, ahora escribe el numero b: ");

    scanf("%d", &b);

    c = a + b; /*suma, puedes poner los smbolos pegados si quieres*/

    printf("\n\tLa suma de %d + %d es %d!!!\n\tQu padre\n", a, b, c);

    return 0;

    }

    Por favor haz el programa, escrbelo bien y crrelo para que veas cmo trabaja. Un consejo, no s que compilador ests usando, estoy seguro de que ya habrs cometido algunos errores y pues no has de haber batallado mucho para corregirlos porque son programas muy chicos, pero procura leer muy bien los mensajes que tu compilador te d, generalmente el error est una lnea antes dedonde te dice el compilador. Te recomiendo que hagas este programa y una vez que funcione bien le quites un punto y coma por ah y veas el mensaje de tu compilador, o quita el return, quita un &, alguna coma o lo que sea para que te acostumbres al funcionamiento de tu compilador y agarres prctica para resolvererrores, la vas a necesitar.

    Espero que ya hayas hecho lo que te ped, revisa las lneas siguientes.

    int a, b, c; /*ya habamos visto que se pueden poner varias declaraciones en la misma lnea*/

    c = a + b; /*suma, puedes poner los smbolos pegados si quieres*/

    printf("\n\tLa suma de %d + %d es %d!!!\n\tQu padre\n", a, b, c);

    Fjate que estamos trabajando con tres variables distintas, ese programa se

    13

  • PARTE I: LO MS BSICO

    puede hacer con solo dos variables. Cambia las lneas anteriores por estas lneas.

    int a, b;

    printf("\n\tLa suma de %d + %d es %d!!!\n\tQue padre\n", a, b, a+b);

    Por ltimo borra la lnea donde haces la suma de c = a + b y compila el programa otra vez, crrelo y ve el resultado que te arroja.

    El siguiente programa muestra la cmo se usa la operacin de mdulo (residuo).

    #include

    int main(int argc, char **args)

    {

    int num, mod;

    printf(" Escribe un numero: ");

    scanf("%d", &num);

    mod = num % 3;/*mod = residuo de num / 3*/

    printf(" El residuo de %d entre 3 es %d\n", num, mod);

    return 0;

    }

    Este programa tambin se puede escribir as.

    #include

    14

  • PARTE I: LO MS BSICO

    int main(int argc, char **args)

    {

    int num;

    printf(" Escribe un numero: ");

    scanf("%d", &num);

    printf(" El residuo de %d entre 3 es %d\n", num, num % 3);

    return 0;

    }

    En C se pueden transformar los tipos de datos en caso de que se necesite. Por ejemplo si escribimos esto.

    float a, b;

    int c;

    ...

    ...

    c = a+b;

    El compilador regresa un error porque no podemos guardar un flotante en un entero, pero si la suma la escribimos as.

    c = (int)(a+b);

    A esto se le llama conversin explcita de tipo, o sea que estamos obligando a lo que resulte de sumar a+b a convertirse en un valor entero. Las versiones ms nuevas de ANSI C no marcan error, quiz una advertencia, lo que ocurre en estecaso es que al querer guardar un valor flotante dentro de una variable entera el valor se redondea y se pierden datos. Por ejemplo, si a = 2.3 y b = 1.4, a + b = 3.7, si c es entera al hacer c = a+b, entonces c = 2.3 + 1.4 o sea c = 3.7 el resultado final sera que c = 3.

    Por otro lado C convierte los tipos de datos segn las operaciones realizadas con ellos utilizando algo llamado promocin de tipos, siempre el resultado de una operacin ser del tipo ms grande involucrado

    15

  • PARTE I: LO MS BSICO

    int * float = float porque float es ms grande que int.

    float / int = float

    int / int = int, por ejemplo 7/2 = 3.

    Otro detalle importante que hay que conocer es la precedencia de los operadores en C.

    La siguiente tabla muestra la lista de operadores ordenados por precedencia. Los que estn en la misma celta tienen la misma precedencia.

    Operador Descripcin Asociatividad

    ++ --()[].->

    Post- incremento y decrementoLlamada a funcinElemento de vectorSeleccin de elemento por referenciaSeleccin de elemento con puntero

    Izquierda a derecha

    ++ --+ -! ~(type)*&sizeof

    Pre- incremento y decrementoSuma y resta unitariaNOT lgico y NOT binarioConversin de tipoIndireccinDireccin deTamao de

    Derecha a izquierda

    * / % Multiplicacin, divisin y mdulo

    Izquierda a derecha

    + - Suma y resta> Operaciones binarias de desplazamiento

    < >=

    Operadores relaciones "menor que", "menoro igual que", "mayor que" y "mayor o igual que"

    == != Operadores relaciones "igual a" y "distinto de"

    & AND binario^ XOR binario| OR binario&& AND lgico|| OR lgicoc?t:f Operador ternario Derecha a

    16

  • PARTE I: LO MS BSICO

    izquierda

    =+= -=*= /= %==&= ^= |=

    Asignaciones

    ,

    Este es el operador de menor prioridad en C. Sirve para separar una coleccin de expresiones, que se irn evaluando de izquierda a derecha

    Izquierda a

    Fuente: http://es.wikipedia.org/wiki/Anexo:Operadores_de_C_y_C%2B%2B#Precedencia_de_operadores

    Archivos de inclusin.Como viste, en todos los programas que hemos hecho viene la inclusin del archivo del archivo stdio.h, este es parte de la biblioteca estndar. Y ya te haba explicado que ah vienen todas las instrucciones de entrada y salida. Trata de quitar esa lnea y vers que el compilador de manda errores en las funciones de entrada y salida. Esos archivos son para guardar funciones que se usan mucho y pues es pesado estarlas escribiendo, a veces yo los uso para dividir mis programas en archivos ms chicos y fciles de leer. Al poner el nombre del archivo entre "" le decimos al compilador que lo busque en su propio directorioinclude, en cambio si le ponemos comillas le damos la ruta completa, por ejemplo #include "c:\\mio.h" busca precisamente ese archivo y no lo busca en otro lado. Si ponemos #include "lynx.h" lo busca en el mismo directorio donde est el cdigo fuente. Vamos a hacer un experimento, teclea el siguiente cdigo.

    /*contenido de cabeza.h*/

    #include

    int a;

    int b;

    int c;

    /*fin de cabeza.h*/

    Guarda este archivo como cabeza.h, dentro del mismo directorio escribe el siguiente cdigo.

    17

  • PARTE I: LO MS BSICO

    /*contenido de cabeza.c*/

    #include"cabeza.h"

    int main(int argc, char **args)

    {

    a = 5;

    b = 6;

    c = a+b;

    printf("La suma es %d\n", c);

    return 0;

    }

    Ahora guarda este cdigo como cabeza.c en el mismo directorio donde guardaste cabeza.h y compila el programa, bsicamente el resultado es el mismo que si hubieras escrito todo en el mismo archivo.

    Variables globales y locales y reglas de alcance.Como habrs notado en el ejemplo anterior, las variables a, b y c quedaron afuera de la funcin main, eso se conoce como variable global, ya que en C todose divide en funciones cada funcin tiene sus propias variables, cuando las variables se declaran fuera de todas las funciones, como en el ejemplo que acabamos de ver, estas variables son accesibles desde todas partes del programa, por eso se les llama variables globales. Cuando las variables se declaran dentro de una funcin, como main por ejemplo, solo son visibles para esa funcin y no para las dems, por eso se llaman variables locales.

    En C tambin existen bloques que pueden tener sus propias variables, veamos el siguiente cdigo y checa el resultado que da.

    #include

    int main(int argc, char **args)

    {/*inicio de un bloque, bloque 1*/

    18

  • PARTE I: LO MS BSICO

    int a = 5;/*variable local*/

    {/*inicio de un bloque, bloque 2*/

    int a = 13;/*otra variable, pero propia del bloque dos, la variable

    a del bloque 1 es invisible aqu*/

    printf("Dentro del bloque 2 a vale %d\n", a);

    }

    /*a la salida del bloque 2 a vale 5, nunca cambi su valor*/

    printf("Dentro del bloque 1 a vale %d\n", a);

    return 0;

    }

    En este caso hay dos variables a en el programa, pero la a del bloque 2 "oculta" a la a del bloque 1.

    #include

    int main(int argc, char **args){/*bloque 1*/

    int a = 5;

    {/*bloque 2*/

    int b = 10;

    /*dentro del bloque 2 a (del bloque 1) es visible*/

    printf("Dentro del bloque 2 a vale %d y b vale %d\n", a, b);

    }

    /*fuera del bloque 2 b es invisible, no existe*/

    return 0;

    }

    19

  • PARTE I: LO MS BSICO

    Aqu vemos que la variable a es visible en el bloque 2, pero b no es visible en el bloque 1, lo que pasa es que una variable es visible "hacia adentro" de los bloques, pero no hacia afuera, por eso de las variables globales, ya que se declaran muy afuera son visibles en todos los bloques. El truco es que si dentro de un bloque o funcin declaramos una variable con el mismo nombre que una de "ms afuera", la de ms afuera no ser visible, solo se podr trabajar con la de ms adentro. Tienes que trabajar un poco poniendo a prueba lo que vimos aqu, ya que es la manera en que puedas aprender, este libro es solo la lnea de salida para que sepas qu es C y cmo usarlo.

    Ahora que ya vimos las primicias de C, ms o menos como son los errores, variables, etc., podemos pasar a la siguiente parte, que es la programacin estructurada.

    PARTE II: PROGRAMACIN ESTRUCTURADAEn un programa que se puede considerar ms o menos til deben existir estructuras de control que permitan tomar decisiones o hacer una tarea repetidas veces. C tiene varias estructuras de control para trabajar con ellas, vamos a empezar por la ms sencilla: la decisin.

    Condicin if-else.A veces es necesario decidir entre dos caminos o dos acciones distintas si una condicin, o varias se cumplen, la primer estructura para tomar decisiones que vamos a ver es el if, que a veces es acompaado por else. Para tomar decisiones hay que evaluar condiciones, en C tenemos operadores lgicos y relacionales, son los siguientes.

    Relacionales:

    Mayor que >

    Menor que =

    Menor o igual que

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    Negacin !

    Vamos a suponer que queremos decir que "si a es mayor o igual que 3 y b es diferente de c", esto se puede escribir as: "(a >= 3) && (b != c)". As es, puedes poner parntesis para separar expresiones o para agruparlas.

    Pero es mejor que hagamos unos programas para poder ver cmo funcionan losoperadores y la decisin if. El siguiente programa toma un nmero, lo compara con diez y te dice si es mayor o menor.

    #include

    int main(int argc, char **args)

    {

    int num;

    printf("\tIntroduce un numero: ");

    scanf("%d", &num);

    /* if(num > 10) equivale a decir "si num es mayor que 10"*/

    if(num > 10)

    {

    /*en caso de que num sea mayor que diez imprime el mensaje*/

    printf(" Tu numero es mayor que diez\n");

    }

    /*se sale del if y se continua con el programa*/

    return 0;

    }

    El programa es muy sencillo, simplemente compara el nmero con diez e imprime un mensaje si es mayor, el funcionamiento de la instruccin if es muy simple, ahora vamos a cambiar un poco el programa, si el nmero es mayor que diez va a imprimir el mensaje, pero de lo contrario va a imprimir otro mensaje. Cambia el siguiente cdigo...

    21

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    If(num > 10)

    {

    printf(...

    }

    /*justo aqu se agrega un else, que quiere decir "de lo contrario"*/

    else

    {

    printf(" Tu numero es menor o igual a diez\n");

    }

    Al poner esas ltimas lneas es como decir "si es mayor que diez haz esto, de lo contrario haz esto otro". Se pueden poner sentencias ms complicadas para tomar decisiones, por ejemplo para evaluar rangos de valores. El siguiente pedazo de programa ve que el nmero est entre 100 y 200, que seran los lmites permitidos, en cazo de que el nmero este fuera de ese rango ser rechazado.

    If( (num >= 100) && (num

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    que est muy bien.

    If( (cal >= 60) && (cal

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    char op;

    printf(" Elige una letra de la a a la e: ");

    scanf("%c", &op);

    /*en esta lnea se le dice a switch que va a trabajar con la variable op*/

    switch(op)

    {

    case 'a': /*en caso de que op sea a*/

    printf(" Elegiste la letra a\n");

    break; /*esta instruccin es importante*/

    case 'b':

    printf(" La segunda letra del alfabeto\n");

    break;

    case 'c':

    printf(" Esta no es una vocal\n");

    break;

    default: /*default actua cuando no se eligi una letra correcta

    no es necesario ponerla, pero puede ser muy util*/

    printf(" No elegiste las letras que te dije!!! :-(");

    }

    return 0;

    }

    Creo que no necesita mucha explicacin el cmo funciona el switch, puede funcionar con enteros, flotantes o caracteres. Dentro de los casos hay una instruccin nueva, break es una instruccin que rompe todas las estructuras, en este caso break hace que el programa se salga de la estructura switch, a veces es importante ponerla. Escribe el mismo programa, pero qutale todos los break's, juega con l y ve que es lo que pasa si eliges una b por ejemplo. Creo que no te va a gustar qu es lo que pasa. Ahora regresa los break's a donde deben de ir y quita la instruccin default (y tambin todo lo que est dentro del

    24

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    default), es mejor que veas ms o menos cmo funciona si le quitas el default, sifunciona, pero ya no te dice si te equivocaste de letra.

    Ciclo for.En C hay tres tipos de ciclos, el ciclo do-while, while y el for, la verdad es que no encuentro cmo explicarte como funciona el ciclo for sin usar ejemplos, as que vamos a hacer un programa.

    El siguiente programa va a presentar un men, se van a tener dos opciones, imprimir todos los nmeros pares del 0 al 100 o imprimir los nones del 0 al 100. Claro que necesitamos ciclos para hacer todo eso, seran muchas lneas de cdigo. Para hacer el programa vamos a usar un switch, dos if's y dos ciclos for.

    #include

    #define N 100 /*algo nuevo, definir valores previos*/

    int main(int argc, char **args)

    {

    int i;

    int op;

    /*imprimiendo el men*/

    printf("\n\t\tMenu\n\n");

    printf("\t1) Imprimir los nones\n");

    printf("\t2) Imprimir los pares\n");

    printf(" Cual es tu opcion? ");

    scanf("%d", &op);

    switch(op)

    {

    case 1:

    /*el ciclo for es como decir "desde i = 0; mientras que sea menor que N;

    incrementa i de uno por uno*/

    for(i=0; i

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    {

    if( (i % 2) == 1 ) /*si el numero entre dos da 1 como residuo*/

    /*parece que falta algo? quit las llaves a propsito*/

    printf(" %d ", i);

    }

    break;

    case 2:

    for(i=0; i

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    quieras y va a incrementarlo el la medida que tu quieras, y va a hacer eso mientras a potencia sea menor o igual 1000.

    #include

    #include /*una librera nueva, puras matemticas*/

    #define N 100

    #define MAX 1000

    int main(int argc, char **args)

    {

    int num, exp, pot, inc;

    printf(" Desde que numero quieres empezar? ");

    scanf("%d", &num);

    printf(" Cual quieres que sea el exponente? ");

    scanf("%d", &exp);

    printf(" Cual quieres que sea el incremento? ");

    scanf("%d", &inc);

    for(num; num

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    hacer asignaciones. Por otro lado tenemos la expresin num+=inc, es que en C hay dos formas de asignar valores, eso equivale a escribir num = num+inc, se puede poner en todos lados, no solo en el for.

    En este programa incluimos el archivo math.h este archivo de cabecera tiene funciones matemticas como senos y cosenos, nmeros absolutos o la potencia,que fue la que utilizamos aqu. Este for est muy raro, primero nada ms est el nombre de una variable en el primer parmetro, pero esa variable ya tiene un valor, as que no hay problema. En el segundo parmetro hay una expresin ms compleja, es como decir "mientras num sea menor o igual a N y que pot, que es el resultado de num elevado a la exp, sea menor o igual a MAX", es complicado pero ahorra lneas de cdigo, por ltimo el parmetro que queda incrementa a num segn el valor de inc. Fjate en la parte que dice "pot = (int)pow(num,exp)", en la parte donde est int entre parntesis, recuerda que es una conversin de tipo, lo que pasa es que pow siempre regresa un valor doble, que es un flotante pero ms largo, as que tuvimos que convertirlo a entero para poder usarlo, en las versiones ms recientes de C se puede omitir la conversin explcita, solamente se obtienen algunas advertencias a la hora de compilar. Vamos a escribir otro programa que haga lo mismo, pero con la instruccin break.

    #include

    #include

    #define N 100

    #define MAX 1000

    int main(int argc, char **args)

    {

    int num, exp, pot, inc;

    printf(" Desde que numero quieres empezar? ");

    scanf("%d", &num);

    printf(" Cual quieres que sea el exponente? ");

    scanf("%d", &exp);

    printf(" Cual quieres que sea el increnmento? ");

    scanf("%d", &inc);

    28

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    for(num; num

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    if(letra != '\n')

    {

    getchar();

    printf("%c\n", letra);

    }

    }

    printf("Hasta luego\n");

    return 0;

    }

    Este programita muestra dos cosas nuevas, la funcin getchar y el ciclo while. En la condicin del ciclo while aparece la sentencia (letra = getchar()) != 'z', getchar es una funcin que toma caracteres desde la entrada estndar, que es elteclado, cuando pulsamos una tecla esta se mete en un buffer, y en el momento que prensamos enter la empujamos hacia el programa, lo mismo pasa con scanf. En la condicin del ciclo pues, se introduce un caracter y ah mismo se evala, si no es z se entra al ciclo, sencillo. Dentro del ciclo nos topamos con el if, que pregunta si la letra es diferente a '\n', pero ese es una secuencia de escape, lo que pasa es que esa secuencia de escape significa "enter" as que lo que pregunta en realidad es que si el usuario tecle enter en vez de un caracter, recuerdas el enter que empujaba el caracter hacia adentro? Lo que pasa es que si se meti una letra y luego un enter este se queda en el buffer, y causa muchos problemas a las funciones que agarran datos desde el teclado, lo que hago con ese if es ver si no se meti un enter solo, en cuyo caso no hay problema, pero si se meti una letra habr problemas, as que sacamos ese enter con otro getchar y listo, nuestro teclado est limpio. Y, aprovechando el if, si el usuario meti un caracter que no sea enter pues imprime el valor, eso para no imprimir lneas en blanco. Prueba a quitar ese control del if para el enter que se queda atorado, vers que te imprime lneas que no deberan de aparecer, otra cosa que pasa es que al pedir un valor ms adelante, si no limpiamos ese enter, simplemente no toma el caracter siguiente sino el enter atorado y pues causa problemas, no sabes cuantos topes me di a causa de eso.

    Ciclo do-while.El programa que acabamos de hacer (el del while), tiene una pequea falla, yo quera que imprimiera la z otra vez, pero no la pone! Pero el seor Ritchie

    30

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    tambin tuvo el mismo problema un da y pues hizo el ciclo do-while. Lo que pasa con el ciclo while es que evala primero la condicin y luego entra al ciclo, pues el ciclo do-while entra primero y evala la condicin al ltimo, vamos a cambiar el programa para que ponga la z que quiero.

    #include

    int main(int argc, char **args)

    {

    char letra;

    printf("Introduce las letras que quieras, para salir introduce una z\n");

    do

    {

    letra = getchar();/*puedes poner un scanf si quieres*/

    if(letra != '\n')

    {

    getchar();/*aqu no pongas un scanf*/

    putchar(letra);

    putchar('\n');

    }

    }while(letra != 'z');

    printf("Hasta luego\n");

    return 0;

    }

    Listo, el programita ya imprime la z que quera, la diferencia entre el ciclo do-while y el ciclo while es muy pequea, pero puede significar mucho. Aparte vimos una funcin nueva, putchar, seguro has de saber ingls y has de saber lo que significa, "pon un caracter". Esta funcin pone un caracter, pero solo uno, nos puede ser de mucha utilidad en algunas ocasiones, esta funcin pone el

    31

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    caracter que le digas, como putchar(letra), pone el contenido de letra en la pantalla. En el caso de putchar('\n') pues es como poner un enter, una lnea nueva. Puedes poner putchar('a') para escribir una a en la pantalla.

    Ahora vamos a suponer que el usuario tiene su teclado con las maysculas activadas y nunca va a poder salir del ciclo porque no va a poner una z minscula. En los ciclos while y do-while tambin se pueden poner cosas ms complicadas. Mira el siguiente cdigo del programa que acabamos de hacer.

    #include

    int main(int argc, char **args)

    {

    char letra;

    printf("Introduce las letras que quieras, para salir introduce una z\n");

    do

    {

    letra = getchar();/*puedes poner un scanf si quieres*/

    if(letra != '\n')

    {

    getchar();/*aqu no pongas un scanf*/

    putchar(letra);

    putchar('\n');

    }

    }while( (letra != 'z') && (letra != 'Z') );

    printf("Hasta luego\n");

    return 0;

    }

    Listo, ahora el pobre usuario podr terminar de ver el programa sin asustarse en el do-while le ponemos un and lgico para que vea si la letra es z o Z. Por cierto,

    32

  • PARTE II: PROGRAMACIN ESTRUCTURADA

    no olvides el punto y coma que va al ltimo del do-while.

    Se supone que tambin debo ensearte a hacer ciclos anidados, pero te lo dejo de tarea, son como los if's, solo pones uno dentro de otro. Ya mero terminamos la parte dos del libro y aunque no lo creas ya sabes mucho de cmo programar en C, en realidad C es muy sencillo y pequeo, se podra decir que ya sabes ms o menos la mitad de lo que debes de saber, dominando estas bases te aseguro que a casi cualquier problema que encontrars una buena solucin. Lo ltimo de este tema es una referencia a los ciclos infinitos, es simple, supongamos que haces un ciclo, pero la condicin siempre se cumple, eso quiere decir que nunca saldrs del ciclo, que grave, no? Debes tener cuidado con esos detalles para que tus programas no se ciclen.

    PARTE III: FUNCIONESTe acuerdas que el principio del libro te expliqu que C se divide en funciones?Esa es la parte bella de la programacin, dividir en pedazos pequeos el problema para resolverlo con ms facilidad. Digamos que necesitamos un programa que calcule la temperatura promedio de cada da y luego haga una grfica para ver la variacin de la temperatura en un mes. Pues se puede hacer una funcin que calcule la temperatura promedio en un da y otra que imprima lagrfica de barras. As si una parte tiene algn error es ms fcil de localizar porque tenemos los componentes aislados.

    Vamos a hacer un programa que calcule el rea de un cuadrado y que calcule el ngulo de un vector, vamos a ponerle un men para usar casos y llamar a dos funciones que vamos a crear.

    #include

    #include

    void area(void); /*prototipos de funcin*/

    void angulo(void);

    int main(int argc, char **args)

    {

    int op;

    printf("Pulsa 1 para sacar el rea de un cuadrado o pulsa 2 para sacar el ngulo de un vector. ");

    33

  • PARTE III: FUNCIONES

    op = getchar();

    if(op != '\n')

    {

    getchar();

    }

    switch(op)

    {

    case '1':

    area();/*mandamos llamar a nuestra funcin*/

    break;

    case '2':

    angulo();

    break;

    }

    return 0;

    }

    void area(void)/*nuestras funciones*/

    {

    float lado;

    printf(" Cuanto mide el lado del cuadrado? ");

    scanf("%f", &lado);

    /*imprimir el cuadrado de lado*/

    printf("El area del cuadrado es %.2f\n", pow(lado,2));

    }

    void angulo(void)

    {

    float x, y, tan, ang;

    34

  • PARTE III: FUNCIONES

    const float pi = 3.14159265;

    printf("Introduce la cordenada x: ");

    scanf("%f", &x);

    printf("Introduce la cordenada y: ");

    scanf("%f", &y);

    tan = x/y; /*la tangente es el cateto opuesto sobre el adyacente*/

    ang = 180 * atan(tan) / pi;/*el ngulo viene en radianes, hay que convertirlo a grados*/

    printf("El angulo es %.2f\n", ang);

    }

    Te voy a explicar el programa parte por parte.

    void area(void);Las funciones regresan y admiten valores por lo general, la primer palabra en la declaracin de una funcin es el tipo de dato que regresa. En este caso la primerpalabra es void, que quiere decir que no va a regresar ningn valor, por ejemplo int main(int argc, char **args) indica que la funcin main debe regresar un valor entero. Lo siguiente en la declaracin de una funcin es el nombre de la funcin, su declaracin tiene las mismas reglas que para las variables, y claro, no debe tener el nombre de alguna otra variable que se llame igual. Por ltimo entre los parntesis van los valores que va a recibir la funcin, pueden ser de cualquier tipo, al igual que el valor de retorno (casi), en este caso se puso void, que indica que no va a recibir nada. En el caso de la funcin main(), se supone que no va a recibir valores, pero se debera escribir int main(int argc, char **args). Ocurre algo, en C el no poner nada entre los parntesis de la declaracin de la funcin supone que esta puede recibir cualquier parmetro, a diferencia de C++, que significa que no va a recibir nada, como si funcion() fueraigual a funcion(void). En lo personal no uso esa caracterstica de C, prefiero poner void cuando no pienso recibir nada en la funcin y declarar los parmetroscuando s quiero que la funcin los reciba.

    Pero no te he explicado por qu la funcin se debe declarar al principio, es comouna variable, se debe declarar antes de usarla, este es ms o menos el mismo

    35

  • PARTE III: FUNCIONES

    caso. Podras escribir todas las funciones antes de main, porque todas las funciones deben ser declaradas antes de quien las invoca, pero es ms lo, mejor escribes todos los prototipos de las funciones que vayas a usar antes de main y ya los puedes escribir donde se te d la gana despus de main. Entoncesya sabes por qu puse los nombres de las funciones antes de main y las funciones las escrib despus de main, es buena costumbre hacer eso. Recuerda adems que si en el prototipo (arriba de main) escribiste int funcion(void), abajo de main la funcin debe llevar el mismo nombre.

    int op;...op = getchar();...case '1':Por qu puse op como int y en el resto del programa lo trato como caracter? Esun truco que aprend, resulta que un char es un int disfrazado de letra, cuando escribes int numero = 'a' en realidad no le pones la letra a sino su cdigo ASCII, entonces puedes engaar al programa hacindole creer que est trabajando conun char. Si pusiramos algo como int truco = '@'; y luego printf("%d", truco); escribira un 64 en la pantalla, y "alt + 64 = @". Si ves la tabla ASCII vers que laclave de @ es 64.

    area()Al escribir el nombre de la funcin con sus parntesis la estamos mandando llamar para que haga lo que tiene que hacer. Es como cuando escribimos char letra = getchar(); mandamos llamar la funcin getchar y el valor que regresa, un int que se puede hacer pasar por caracter, lo guardamos en letra.

    void area(void){

    ...

    ...

    ...}En esta parte est la funcin con todo lo que tiene que hacer. Pareca ms

    36

  • PARTE III: FUNCIONES

    complicado, no crees?

    Ya vimos cmo trabajan las funciones sencillitas, ahora vamos a hacer una funcin que saque el factorial de un nmero, pero lo nuevo es que el factorial va a ser un valor de retorno y el nmero lo va a recibir como parmetro.

    #include

    long fact(int);/*el prototipo de la funcin*/

    void main(void)/*vamos a cambiar un poco*/

    {

    int num;

    printf(" Escribe el numero para sacar su factorial: ");

    scanf("%d", &num);

    printf(" El factorial de %d es %d\n", num, fact(num));

    }

    long fact(int a)

    {

    int i;

    long fact = 1;

    for(i=1; i

  • PARTE III: FUNCIONES

    long fact(int);En este prototipo de funcin vemos un tipo de dato nuevo, long es un entero y setrata como tal, pero es ms largo, si un entero normalmente trabaja con 16 bits, que le da un rango de -2 +1 a 2 -1 el long trabaja con 32 bits, el doble, as que puede almacenar nmeros desde -2+1 a 2-1 (puede variar segn la implementacin) hay otro tipo de variable entera, short, que trabaja con la mitad de bits, o sea que en un procesador de 32 bits trabajara con 8 bits que nos dara un rango de valores de -127 a 127. Pero eso no es todo todos estos, aparte del char y los flotantes (float y double), se pueden hacer sin signo la palabra unsigned, en el caso del unsigned int cambia el rango de 0 a 65535, pero bueno, volvamos a nuestras funciones, ya sabemos que esta funcin va a regresar un valor long, que puede ser muy grande, que se va a llamar fact y que va a recibir un valor entero. En los prototipos de funcin no es necesario poner elnombre de las variables, solo el tipo, si quieres puedes poner el nombre de la variable, pero no pasa nada si no lo haces.

    printf(" El factorial de %d es %d\n", num, fact(num))En este printf llamamos la funcin fact como un parmetro ms, cmo es esto? Ya lo habamos visto antes, el valor que regresa fact es el valor que printf imprime en nuestro mensaje. Al poner fact(num), le estamos mandando ese entero para que trabaje con l.

    long fact(int a){

    ...

    ...return fact;

    }Aqu empezamos a trabajar con nuestra funcin aqu s debemos poner el nombre de la variable que va a recibir, puede ser diferente, puede llamarse comosea siempre que siga siendo entero, as que se me ocurri ponerle a. Escribimostodas las instrucciones y al ltimo est el return fact, puedes poner el return donde se te antoje, puede ser dentro de un if o un switch, como sea, pero generalmente va al ltimo. Return manda el valor de regreso a quien quiera que haya llamado a la funcin, en este caso le manda el valor de fact a la funcin printf para que lo imprima.

    38

  • PARTE III: FUNCIONES

    Como ves no es tanto show, simplemente ir por pasos y fijarse bien como es la sintaxis de C. Las funciones pueden recibir un chorro de parmetros, pero solo pueden regresar un valor, vamos a hacer un clon de la funcin pow para sacar potencias, pero limitada a solo trabajar con enteros.

    #include

    long pot(long, int);

    int main(int argc, char **args)

    {

    int num;

    int exp;

    printf("Introduce el numero: ");

    scanf("%d", &num);

    printf("Introduce el exponente: ");

    scanf("%d", &exp);

    printf("La potencia es %d\n", pot(num, exp));

    return 0;

    }

    long pot(long n, int e);

    {

    int i;

    long p = 1;

    for(i=0; i

  • PARTE III: FUNCIONES

    Como puedes ver, una funcin puede recibir cualquier tipo de parmetro y pueden ser diferentes entre s, adems de que pueden ser varios de ellos.

    Hasta ahora hemos llamado funciones y les hemos mandado parmetros, pero han sido pasos "por valor". Lo que quiere decir es que el programa crea una copia de las variables y trabaja con las copias, a veces es mejor (ya sea por espacio en memoria o por otras cosas) que las variables no se copien, sino que la funcin trabaje con las originales. Esto lo vamos a ver despus, vamos a hacer un programa que muestre cmo se copian las variables. Este programa vaa tomar un valor entero y le va a sacar su cuadrado.

    #include

    int cuad(int);

    int main(int argc, char **args)

    {

    int a;

    printf("Introduce un numero para sacar su cuadrado: ");

    scanf("%d", &a);

    printf("El cuadrado de %d es %d\n", a, cuad(a));

    return 0;

    }

    int cuad(int a)

    {

    a *= a;

    return a;

    }

    Espero que lo hayas escrito y hayas visto como funciona, en la funcin cuad estamos cambiando el valor de a, incluso lo estamos regresando a main, pero el

    40

  • PARTE III: FUNCIONES

    valor de la a de main no cambi, as se ve muy claro que la a de cuad era solo una copia. Ahora vamos a ver una peculiaridad de C, si decimos que una funcinva a recibir enteros le mandamos enteros, pero en realidad esto puede cambiar, mira el siguiente cdigo.

    #include

    float mitad(float);

    int main(int argc, char **args)

    {

    int a;

    printf("Introduce un numero para sacar su cuadrado: ");

    scanf("%d", &a);

    printf("El cuadrado de %d es %f\n", a, cuad(a));

    }

    float cuad(float a)

    {

    a *= a;

    return a;

    }

    Es el mismo programa (ms o menos), pero le estamos mandando un entero a una funcin que supuestamente solo recibe flotantes, lo que pasa es que C convierte el tipo de dato siempre y cuando no haya perdida de datos, as que puedes hacer una funcin que acepte double's y mandarle short's sin ningn problema, pero no trates de mandarle un float a una funcin que reciba enteros porque vas a tener problemas2, al menos warnings por parte del compilador y prdida de datos.

    Ya te sabes algunos trucos y ya sabes que una funcin te puede servir para

    2 Actualmente se puede hacer conversin implcita a tipos de dato ms pequeos, lo cual implica prdida de datos, pero el compilador no genera un error, slo una alerta.

    41

  • PARTE III: FUNCIONES

    dividir el programa en pedazos ms sencillos, aparte de que si haces el mismo procedimiento varias veces dentro de un programa te ahorras escribir el mismo cdigo varias veces, lo pones en una sola funcin y lo mandas llamar las veces que quieras. Pero que tal si te digo que saques el factorial de un nmero sin usar ciclos? Te voy a ensear el siguiente cdigo y por favor ponle mucha atencin, esto es un detalle de C que te va a servir muchsimo.

    #include

    long fact(int);

    int main(int argc, char **args)

    {

    int num;

    printf("Introduce un numero para sacar su factorial: ");

    scanf("%d", &num);

    printf("El factorial de %d es %d\n", num, fact(num));

    return 0;

    }

    long fact(int a)

    {

    if(a != 0)

    {

    return(a * fact(a-1));

    }

    else

    {

    return 1;

    }

    }

    42

  • PARTE III: FUNCIONES

    Recuerdas la frmula del factorial? Era algo como !n = n * (n-1) * (n-2) * ... * (1).En forma recursiva la frmula sera !n = n * !(n-1). En este programa vemos dos cosas, que se pueden poner operaciones entre parntesis para que return se encargue de ellas, pero bueno eso es parte integral de C, y se puede hacer en todos lados, como en fact(a-1), no hay problema por eso, lo otro es que una funcin se puede llamar a s misma, eso se llama recursividad, si miras la frmula recursiva de la frmula del factorial es exactamente la misma que escriben el return, funciona y lo hace bien.

    Hay dos tipos de recursividades, la interna y la externa, la interna es esta que acabamos de ver, la externa es cuando la funcin 1 llama a la funcin 2, y esta llama otra vez a la funcin 1 y as las dos funciones recurren entre s. Mira bien la funcin fact, mira que tiene una condicin, y en un punto tiene que regresar unvalor fijo, en la recursividad debe haber una condicin para que en un punto dado la funcin no se vuelva a llamar a s misma (o a otra en el caso de la recursividad externa), en este caso me fui siguiendo la frmula, el uno es el ltimo numero que se multiplica y el factorial de 0 es 1 as que hice que cuando el valor recibido fuera 0 la funcin regresara un 1, ese es el tope o caso base.

    Ya hemos avanzado bastante, supongo que en este punto haz de pensar que losprogramas que estamos haciendo estn muy simples, pero no puedo poner programas ms complejos en el libro, solo puedo darte las herramientas para que escarbes y te sea ms fcil aprender a programar en C. De todas formas el libro no te sirve de nada si no tratas de complicarte la vida un poco y tratas de hacer experimentos, puedes combinar lo que quieras, poner ciclos dentro de los switchs, o poner switchs dentro de los ciclos, puedes mezclar todo con todo, programar es como jugar lego, tienes las piezas y las armas a tu gusto. Yo solo te estoy dando las piezas para que juegues, lo dems es cosa tuya. Creo que vamos bien hasta este momento, no hemos visto muchas funciones de la biblioteca estndar, pero hemos visto algunos trucos y propiedades de C que te van a servir mucho. Ya estamos listos para entrar al siguiente tema, los arreglos,aparte en el siguiente tema vamos a ver las estructuras, que son un tipo de dato que tarde o temprano vas a usar mucho, como no hallo donde ponerlo pues lo vamos a ver en la siguiente parte del libro. Por favor tmate un descanso repasaun poco lo que ya vimos, porque de ahora en adelante vamos a hacer programas de ms de 100 lneas, porque me interesa que aprendas a leer cdigo y que veas unos buenos ejemplos. En realidad C es muy sencillo y muy pequeo, y hasta este punto vamos muy bien y creo que te he podido explicar todo de la forma ms simple, pero vamos a ver ms ejemplos, y va a ser lo largodel libro.

    43

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    PARTE IV:ARREGLOS Y ESTRUCTURAS

    Arreglos unidimensionalesCreo que te has de seguir preguntando cmo poder guardar el nombre de una persona o cualquier cadena, aparte vamos a suponer que queremos almacenar unos cincuenta nmeros flotantes para sacar su promedio despus, creo que est muy difcil poner 50 variables diferentes y llevar el control de todas ellas. Para cosas como esas tenemos los arreglos, es un tipo de dato que puede contener muchos elementos del mismo tipo. El siguiente programa que vamos a hacer va a almacenar la temperatura diaria promedio durante una semana, o seaque son siete nmeros diferentes, les va a sacar su promedio y los va a imprimir.

    #include

    #define N 7 /*numero de elementos del arreglo*/

    int main(int argc, char **args)

    {

    float arr[N]; /*un arreglo de 7 flotantes*/

    int i;

    float prom = 0; /*este va a ser el promedio*/

    printf("A continuacin introduce las temperaturas\n");

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    Como ves aqu agrupamos 7 flotantes dentro de una sola variable, aunque las 7 son independientes entre s es ms fcil tratarlas como un grupo que por separado. Vamos a ver el programa parte por parte para que entiendas como funciona esto de los arreglos.

    #define N 7En esta parte defin un numero, que voy a utilizar para definir el tamao del arreglo y el ciclo que se va a usar.

    float arr[N];Aqu viene la novedad, float arr se entiende, es un flotante que se llama arr, pero float arr[N] qu? Cuando escribo float arr[N] estoy diciendo que voy a hacer N variables flotantes, pero que las quiero tratar como un arreglo o matriz, como sea. Digamos que tengo una caja dividida en 7 ms pequeas puedo guardar 7 flotantes diferentes en la misma "caja".

    float prom =0;Hay un detalle importante que haba olvidado, vamos a usar prom para ir sumando las temperaturas y sacarles su promedio, me gustara que cambiaras esta lnea por float prom; y vieras lo que pasa. En C cuando creamos una variable esta puede tomar cualquier valor, no sabemos cul puede ser, si se va ausar una variable hay que inicializarla primero.

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    arr[2]). En la lnea que dice prom += arr[i] es donde se nota bastante como, aunque todas formen parte del mismo arreglo, pueden ser tratadas como variables independientes y hacer operaciones con ellas.

    prom /= N;El nmero que definimos puede ser usado como una constante, as que tambinse pueden hacer operaciones con l. Entonces aqu ya tenemos el promedio de toda la semana.

    printf("El promedio es %.3f", prom);Fjate en la parte que dice %.3f, ya he puesto cosas as, pero no te haba explicado para qu sirve, si has hecho tus programas ya te habrs dado cuenta de al poner %f imprime el nmero con seis decimales, esto se puede aumentar oreducir poniendo %.7f o %.1f, creo que sobra decir cuantos decimales pone el %.3f.

    Ahora vamos a ver cmo se puede inicializar un arreglo, es sencillo. Mira el siguiente cdigo, aparte vas a ver el ordenamiento burbuja.

    #include

    #define N 10

    int main(int argc, char **args)

    {

    int arr[] = {10, 1, 9, 2, 8, 3, 7, 4, 6, 5}; /*as se inicializa un arreglo*/

    int i, j, swap; /*swap es una variable de intercambio para el ordenamiento*/

    printf(" El ordenamiento burbuja\n\n");

    printf("El arreglo en desosren es: ");

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    printf("%d, ", arr[i]); /*recuerda que cuando es solo una instruccin no se necesitan comillas*/

    printf("\b\b.\n");

    /*aqu empieza el ordenamiento burbuja*/

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    getchar();

    }

    }

    char minuscula(char a){

    if(a >= 65 && a

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    limpia(op);

    op = minuscula(op);

    switch(op){

    case 'a':

    llenar(arr);

    a = 1;

    getchar();

    break;

    case 'b':

    if(a == 1){

    ordena(arr, 'a'); /*a de ascendente*/

    }else{

    printf("Aun no has llenado el areglo\n");

    }

    break;

    case 'c':

    if(a == 1){

    ordena(arr, 'd'); /*d de descendente*/

    }else{

    printf("Aun no has llenado el arreglo\n");

    }

    break;

    case 'd':

    printf("Hasta luego!!!\n");

    break;

    default:

    printf("Tecla incorrecta\n");

    }

    system("pause"); /*otra llamada a ms-dos*/

    50

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    }while(op != 'd' && op != 'D');

    return 0;

    }

    void llenar(int a[]){

    int i;

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    for(j=0; j

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void limpia(char a){ if(a != '\n'){ getchar(); }}Ya te haba explicado cmo el enter empuja a los datos desde el teclado, pero se queda atorado en el buffer del teclado y nos jala broncas, en esta parte dondeagarramos el caracter y lo metemos y si no fue un enter solo jalamos el enter que se qued atorado. Habrs notado que esta funcin no tiene prototipo, es que le escrib al modo antiguo, hasta arriba. Recuerda que si haces eso tienes que escribirla arriba de donde est la primera vez que la invoques, si invocas una funcin que no tiene prototipo y est escrita abajo de tu invocacin el programa no la va a encontrar, estos son problemas.

    char minuscula(char a){ if(a >= 65 && a

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    puedes poner system("dir") o system("md lynx"). Esta funcin est en la librera stdlib.h

    Lo dems se me hace ms complicado explicarlo, trata de leer bien el programa y de ver cmo funciona para que entiendas bien cmo est estructurado el programa.

    Ahora vamos a ver otro detalle de los arreglos y las funciones, recuerdas que alpasar una variable a una funcin el programa haca una copia de esta? Pues con los arreglos es diferente, veamos...

    #include

    #include

    #include

    #define N 10

    void llena(int []);

    void imprime(int []);

    void ordena(int []);

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

    int a[N];

    llena(a);

    printf("El arreglo original: ");

    imprime(a);

    printf("\n");

    ordena(a);

    printf("El arreglo despues de ordenarse: ");

    imprime(a);

    printf("\n");

    return 0;

    }

    54

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void llena(int b[]){

    int i;

    srand(time(NULL));

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    computadora. Se ve como el arreglo pasa por todas las funciones pero sin copiarse, el arreglo pasa ntegro, as que ten cuidado porque los arreglos no se copian, esto es porque no son variables normales, son parte de los apuntadores o punteros, esos los vemos despus. Ahora te voy a explicar las cosas nuevas que hay en este programa.

    #includeLa librera time.h tiene las funciones para saber y manipular la hora. No es que queramos cambiar la hora en este programa, pero hay una funcin que nos servir.

    void llena(int b[]){ int i; srand(time(NULL)); for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    Arreglos de tamao no predefinidoExiste una forma ms conveniente de crear arreglos, le podemos pedir al usuario que nos diga el tamao antes de crear el arreglo. Mira el siguiente programa.

    #include

    #include

    #include

    void llenar(int n, int a[]){

    int i;

    srand(time(NULL));

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    t = a[j];

    a[j] = a[j+1];

    a[j+1] = t;

    }

    }

    }

    }

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

    int t;

    printf("Dime el tamao de tu arreglo: ");

    scanf("%d", &t);

    if(t>1){

    int arreglo[t];

    llenar(t, arreglo);

    printf("Tu arreglo es:\n");

    mostrar(t, arreglo);

    ordenar(t, arreglo);

    printf("Tu arreglo ordenado es:\n");

    mostrar(t, arreglo);

    }else{

    printf("Ese tamao no es vlido\n");

    }

    return 0;

    }

    scanf("%d", &t);if(t>1){ int arreglo[t];Aqu le preguntamos al usuario el tamao y luego vemos que el valir sea

    58

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    correcto, no podemos tener arreglos de tamao -2 y un tamao de 1 sera absurdo. EL tamao del arreglo se define utilizando la variable t (int arreglo[t]), as si t vale 5 el tamao del arreglo ser 5.

    void llenar(int n, int a[])void mostrar(int n, int a[])void ordenar(int n, int a[])Las funciones que trabajan con ese arreglo deben saber el tamao que este tendr, por eso se este define como parmetro, ya que puede ser cualquier cosa. A la hora de invocar la funcin se le mandan el tamao y el arreglo.

    Arreglos de dos o ms dimensiones.Tambin puede haber arreglos de varias dimensiones, y se puede hacer lo mismo que con los arreglos de una sola dimensin. Se puede declarar un arreglo flotante de 3x3 con la lnea float arr[3][3], o de 4x5x3 con la lnea float arr[4][5][3]. En el siguiente programa vamos a llenar un arreglo de 3x3, lo vamos a multiplicar por 2 y lo vamos a imprimir.

    #include

    #define N 3

    void llenar(int [][N]);

    void multiplica(int [][N]);

    void imprime(int [][N]);

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

    int a[N][N]; /*declaro un arreglo de NxN*/

    llena(a);

    multiplica(a);

    imprime(a);

    return 0;

    }

    59

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void llena(int b[][N]){

    int i, j;

    printf(" Vamos a llenar el arreglo\n");

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    printf("|\n");

    }

    }

    El programita no requiere de mucha explicacin, lo que cambia es la forma de declarar el parmetro en las funciones y cmo declarar el arreglo. Aparte del tratamiento que hay que darle ya que hay que llenar dos dimensiones. Mira bien la forma en que declar las funciones, puse que iba a recibir un arreglo con los corchetes correspondientes, pero en el segundo corchete tuve que poner el tamao del arreglo por ejemplo si declaro un long arr[2][3], al declarar una funcin tendra que escribir void funcin(long [][3]), por ejemplo. Un detalle que deb de haberte explicado hace mucho, observa la lnea printf("| %3d ", d[i][j]), al poner %3d estoy diciendo que ponga tres espacios, un entero que valga 4023 s se va a imprimir completo, a veces es necesario que la impresin que de ms o menos presentable y esto nos ayuda, ya te lo haba explicado con los flotantes, como %.3f, pero la verdad es que hasta ahora supe que se poda hacer con los enteros tambin (y aun as me atrev a escribir un libro).

    En este programa vamos a ver cmo inicializar un arreglo de dos dimensiones.

    #include

    #define N 4

    #define M 3

    void imprime(int [][M]);

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

    int a[][M] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

    imprime(a);

    return 0;

    }

    61

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void imprime(int b[][M]){

    int i, j;

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    } printf("|\n"); }}Esta funcin se encarga de imprimir el arreglo, lo imprime rengln por rengln, claro que para hacer eso tiene que ir al primer rengln y luego imprimir la casilla correspondiente de cada columna.

    Francamente es complicado explicar bien cmo se mueven los programas dentro de los arreglos multidimensionales, este programa es sencillo, pero puede resultar muy fcil confundir los renglones con las columnas y el cmo moverse sobre ellas. Vamos a ver un programa, este mismo, pero que ordene los nmeros para que se presenten de menor a mayor de izquierda a derecha y de arriba a abajo.

    #include

    #define N 4

    #define M 3

    void imprime(int [][N]);

    void ordena(int [][M]);

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

    int a[][M] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

    printf("Este es el arreglo original\n\n");

    imprime(a);

    ordena(a);

    printf("\nEste es el arreglo ordenado\n\n");

    imprime(a);

    return 0;

    }

    63

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void imprime(int b[][M]){

    int i, j;

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    for(j=0; j

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void llenar(int m, int n, int a[][n]){

    int i, j;

    srand(time(NULL));

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

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

    int a, b;

    printf("Dime la cantiad de filas: ");

    scanf("%d", &a);

    printf("Dime la cantiad de columnas: ");

    scanf("%d", &b);

    if(a>1 && b>1){

    int arreglo[a][b];

    llenar(a, b, arreglo);

    printf("Tu arreglo es:\n");

    mostrar(a, b, arreglo);

    printf("Tu arreglo transpuesto es:\n");

    transponer(a, b, arreglo);

    }else{

    printf("Ese tamao no es vlido\n");

    }

    return 0;

    }

    Bsicamente es lo mismo, lo que vale la pena que veas es que en las funciones los parmetros se definen utilizando las dimensiones, las cuales son parmetros tambin (void transponer(int m, int n, int a[][n])).

    Arreglos de ms dimensionesLlevo dos aos programando en C, es muy poco, pero ya me s algunos buenostrucos, es que C es muy sencillo y compacto. En este tiempo nunca he necesitado una matriz de ms de dos dimensiones, pero el siguiente programa (lo hice por curiosidad) trabaja con una matriz de tres dimensiones. Es muy complicado ver como inicializa los valores y cmo se pueden acomodar (al menos lo es para m), pero pens que sera una buena referencia.

    67

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    #include

    #define N 4

    #define M 3

    #define O 2

    void imprime(int [][N][O]);

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

    int a[][M][O] = {23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

    imprime(a);

    return 0;

    }

    void imprime(int b[][M][O]){

    int i, j, k;

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    reto, aunque la respuesta es sencilla.

    El primer programa debe presentar un men con cuatro opciones, la primera es cargar dos arreglos de 3 x 3 con los datos del usuario, la segunda es sumar las dos matrices y el resultado hay que almacenarlo dentro del segundo arreglo, la tercer opcin sera imprimir el arreglo (y que se vea presentable), por ltimo la opcin para salir.

    El segundo va a tener cuatro opciones tambin, la primera es cargar dos arreglos de 3 x 3, la segunda es multiplicar los dos arreglos y guardar el resultado en un tercer arreglo, por ltimo hay que imprimir el resultado en la opcin tres, y la opcin 4 sera salir del programa.

    Mucha suerte, pareciera que no, pero en el libro viene todo lo que necesitas parahacer los programas, el ingenio lo pones t, dale una repasada al libro, ya hicimos un programa que presenta un men ms o menos decente y ya hemos trabajado con arreglos de dos dimensiones, el primer programa no est tan difcil, pero el segundo tiene su chiste. Te recomiendo que hagas un trazado de cmo lo haras si t fueras la computadora, usa lpiz y papel para ir paso por paso y as te inventas un mtodo, Cuando hagas tus programas has las pruebasde escritorio, que son escribir paso por paso lo que va haciendo el programa, asvez qu te falta o qu te sobra. chale ganas y tomate el tiempo que necesites. Cuando termines con eso y ya te sientas bien con los arreglos vamos a pasar al siguiente tema y vamos a ver las estructuras, adems de otro uso de los arreglos, las cadenas de caracteres, que para entonces sern pan comido para ti.

    Estructuras.Ya vimos que un arreglo puede contener varias variables del mismo tipo, pero ahora hay un problema, el siguiente problema es que necesitamos capturar y listar la informacin de 10 alumnos, la informacin de cada alumno tiene su nombre, su matrcula y su promedio. Son muchos datos, necesitamos alguna estructura de datos que los pueda contener todos. El siguiente programa va a contener tres variables distintas dentro de la misma estructura, vamos a ver cmo se da de alta una estructura (declararla), y cmo manipular sus datos.

    #include

    struct datos{

    int a;

    float b;

    69

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    char c;

    };

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

    struct datos misdatos;/*asi podremos usar la estructura*/

    misdatos.a = 4; /*asi se accede a los datos de la estructura*/

    misdatos.b = 5.5;

    misdatos.c = '!';

    printf("Dentro de la estructura a vale %d, b vale %.1f. Que padre%c\n", misdatos.a, misdatos.b, misdatos.c);

    return 0;

    }

    No es tan difcil, una estructura es como un tipo de dato, cuando escrib struct datos misdatos fue como decir "oye, crame una variable que se llame misdatos para usar la estructura esta". Y para acceder a los datos de la estructura pues lo hacemos con el punto, para separar el nombre de nuestra variable especial (misdatos) y el elemento que est adentro de la estructura.

    #include

    struct datos{

    int a;

    float b;

    char c;

    };

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

    struct datos misdatos;/*asi podremos usar la estructura*/

    misdatos.a = 4; /*asi se accede a los datos de la estructura*/

    misdatos.c = '!';

    70

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    printf("Cuanto quieres que valga b? ");

    scanf("%f", &misdatos.b);

    printf("Dentro de la estructura a vale %d, b vale %.1f. Que padre%c\n", misdatos.a, misdatos.b, misdatos.c);

    return 0;

    }

    Ves? Puedes hacer lo que sea, no hay problema, puedes hacer arreglos de estructuras, pasarlas a las funciones, ordenarlas, lo que sea. En el siguiente programa vas a ver otra forma de declarar una estructura, en los dos programas anteriores misdatos es local, pero se puede hacer como una variable global, recuerdas qu es una variable global?

    #include

    struct datos{

    int a;

    float b;

    char c;

    }misdatos;

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

    misdatos.a = 4; /*asi se accede a los datos de la estructura*/

    misdatos.c = '!';

    printf("Cuanto quieres que valga b? ");

    scanf("%f", &misdatos.b);

    printf("Dentro de la estructura a vale %d, b vale %.1f. Que padre%c\n", misdatos.a, misdatos.b, misdatos.c);

    return 0;

    }

    As se declara el nombre de la estructura en forma global, creo que ya ests listo

    71

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    para seguir con el problema del principio de la seccin.

    Cadenas de caracteresVamos a hacer un arreglo de diez estructuras, pero a nivel local en main, ese arreglo de estructuras va a almacenar los datos de los diez alumnos (nombre, matrcula y promedio) los va a ordenar en base a la matrcula y por ltimo los va a imprimir en orden.

    #include

    #include

    #define A 10 /*corresponde a alumnos*/

    #define N 50 /*largo del nombre*/

    struct alumnos{

    int mat;

    char nombre[N]; /*un arreglo de caracteres*/

    float prom;

    };

    void captura(struct alumnos []);

    void ordena(struct alumnos []);

    void imprime(struct alumnos []);

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

    struct alumnos a[A]; /*se supone que as declaramos el arreglo de estructuras*/

    captura(a);

    ordena(a);

    imprime(a);

    return 0;

    }

    72

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    void captura(struct alumnos a[]){

    int i, j;

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    sprom = a[j].prom;

    a[j].mat = a[j+1].mat;

    strcpy(a[j].nombre, a[j+1].nombre);

    a[j].prom = a[j+1].prom;

    a[j+1].mat = smat;

    strcpy(a[j+1].nombre, snombre);

    a[j+1].prom = sprom;

    }

    }

    }

    }

    void imprime(struct alumnos a[]){

    int i;

    printf("Lista de los alumnos\n");

    for(i=0; i

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    importante. Mira las siguientes lneas del programa.

    while((a[i].nombre[j] = getchar()) != '\n' && (j++ < N));

    a[i].nombre[j] = '\0';

    En el ciclo while estoy metiendo los caracteres de uno por uno hasta que se introduce un enter, es un ciclo que no lleva nada adentro, todo serio, pero hay una lnea despus, que es a[i].nombre[j] = '\0', qu es '\0'? Diagonal inversa cero quiere decir "fin de lnea", has un experimento, escribe un programa cuya nica lnea de salida sea printf("Hola mun\0do\n") y ve que es lo que pasa. En el programa que acabamos de ver declar el nombre con 50 caracteres, siempre que se declara un arreglo el ltimo elemento es '\0', solo que es invisible para el programador, ese espacio no lo contamos y est bien, podemos meter 50 caracteres a nuestro arreglo char nombre[N] y todo va a estar bien. Pero en el caso de que solo metamos 23 caracteres y luego mandemos a imprimir el arreglo vamos a toparnos con un mal detalle, imprime nuestros 23 caracteres mas 27 de pura basura, por eso puse la lnea a[i].nombre[j] = '\0' al final, para que ponga el fin de la cadena justo despus de que terminemos de escribir. Espero que eso haya quedado ms o menos claro, ahora quiero que veas la lnea strcpy(snombre, a[j].nombre) Esta es una funcin que viene en la librera string.h y copia cadenas, lo que hace es copiar el contenido de a[j].nombre a snombre, hay ms funciones para el manejo de cadenas de caracteres en esa librera, pero no se pueden ver todas.

    Por otro lado hay otras funciones de entrada y salida, que las podemos encontrar en la librera stdio.h, te acuerdas de la funcin putc? De getchar ni te pregunto, pues estas funciones son las hermanas, solo que trabajan con cadenas. Mira el siguiente cdigo.

    #include

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

    char cadena[50];

    printf("Introduce una frase: ");

    gets(cadena);

    puts(cadena);

    printf("%s", cadena);

    return 0;

    }

    75

  • PARTE IV:ARREGLOS Y ESTRUCTURAS

    Con estas funciones, me refiero mucho ms a gets4, nos podemos olvidar, aunque no del todo por favor, del detalle del famoso '\0', funcionan bien.

    Solo falta el cmo inicializar una cadena, sencillo...

    #include

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

    char cadena[] = "Hola peque\xa4o saltamontes";

    puts(cadena);

    return 0;

    }

    Ya estamos muy avanzados en el lenguaje C, solo necesitas mucha prctica, te voy a poner un problema ms o menos interesante. Has un programa que capture una cadena, no importa el largo, siempre que sean ms de cinco letras, e imprima la cadena en orden inverso, te recomiendo que no uses gets sino el ciclo while para capturar y tambin para imprimir.

    Pues a practicar y a practicar, una vez que te sientas bien con lo de las cadenas y las estructuras vamos a pasar a la parte 5, vamos a ver lo bueno de C, lo que le da su potencia, son los apuntadores, es un tema que puede ser un fastidio, pero cuando entiendes bien como funcionan los apuntadores puedes hacer bastantes cosas sin mucha dificultad.

    PARTE V: APUNTADORESAlgo que hace de C un lenguaje muy potente son los apuntadores, nos dan mucha flexibilidad y potencia. Digamos que la memoria principal del sistema es como un barrio, un apuntador sera el viejito que se sabe las direcciones de todos los que viven ah, te puede decir la informacin que necesitas de cada persona que vive en ese barrio sin que tengas que ir hasta ella. En los problemas de memoria dinmica, por ejemplo, hay una funcin que encuentra unespacio libre y lo aparta, luego esa funcin regresa la direccin de la memoria que puede ser utilizada, para acceder a esa direccin se necesitan apuntadores.O para manejar cadenas de caracteres y arreglos (es lo mismo), en realidad lo que se hace es trabajar con apuntadores. Es mucho ms fcil y eficiente poner

    4 La funcin gets se considera insegura y se recomienda fgets en cambio

    76

  • PARTE V: APUNTADORES

    un dato en una direccin de memoria, hacer un apuntador hacia esa variable y poder trabajar con esa variable a travs del apuntador, a distancia. En este temavamos a trabajar mucho tiempo, al principio los apuntadores son complicados, sobre todo al tratarse de cadenas y arreglos (aunque sea lo mismo los vamos a diferenciar), pero se usan mucho, ya lo vers. Entonces es mejor trabajar muchocon esto.

    Apuntadores a variables.Lo ms bsico de un apuntador es el que apunta a una variable sencilla, vamos a ver qu significa el ampersand (&) de la funcin scanf y tambin los dos trminos bsicos tratando con apuntadores.

    Lo primero que quiero que hagas (por el momento), es que aprendas esto.

    & Significa "direccin de" y * significa el "valor que esta en (tal direccin)". Cmo es esto? Mira el siguiente cdigo y por favor escrbelo y hazlo correr.

    #include

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

    int var;

    printf("La direccion en memoria de var es %p\n", &var);

    return 0;

    }

    La salida del programa es una lnea como "printf("La direccion en memoria de var es %p\n", &var);", espero que ya te haya cado el veinte de lo que quiere decir el &, se refiere a la direccin de memoria de la variable. Entonces ahora te puedo decir que al escribir scanf("%d", &variable) estamos diciendo algo como "recoge un valor entero decimal y lo pones en la direccin de memoria fulana de tal".

    Un apuntador es una variable pequea que guarda la direccin de memoria de una variable, puede ser de cualquier tipo, desde int hasta struct, aparte puede ser void (apuntador genrico). En el siguiente cdigo se muestra como usar un apuntador.

    #include

    77

  • PARTE V: APUNTADORES

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

    int a;

    int *b = &a; /*el apuntador se inicializa con la direccin a donde va a apuntar*/

    printf("La direccion de a es %p (en hexadecimal)\n", &a);

    printf("El puntero b apunta hacia esta direccin %p\n", b);

    printf("Introduce el valor de a: ");

    scanf("%d", &a);

    printf("El valor de *b es %d\n", *b);

    printf("Vuelve a cambiar el valor de a: ");

    scanf("%d", b);

    printf("Ahora a vale %d\n", a);

    printf(" a + 2 es %d y *b + 2 es %d\n", a+2, *b+2);

    return 0;

    }

    En este programa hay dos cosas muy importantes, *puntero representa lo que vale la variable o sea que variable es ms o menos igual a *puntero y puntero representa la direccin de la variable o sea que &variable es como puntero. Vamos a ver el cdigo parte por parte, espero que ya lo hayas compilado y hecho correr.

    int a;int *b = &a;En estas lneas declaramos una variable entera, luego declaramos un puntero y lo inicializamos, se debe inicializar con la direccin de la variable a la que va a apuntar, aparte ambos deben de ser del mismo tipo, un puntero char no puede apuntar a un flotante, as que tuve que declarar un puntero int para apuntar a una variable int.

    printf("La direccion de a es %p (en hexadecimal)\n", &a);printf("El puntero b apunta hacia esta direccin %p\n", b);

    78

  • PARTE V: APUNTADORES

    En estas lneas imprimimos la direccin de la variable a en cdigo hexadecimal, en la segunda lnea imprimimos el valor verdadero del apuntador b, que es la direccin de a.

    printf("Introduce el valor de a: ");scanf("%d", &a);printf("El valor de *b es %d\n", *b);En este pedazo vemos como podemos cambiar el valor de a y verlo usando el apuntador, nota que al poner el asterisco ponemos el valor que est en dicha direccin de memoria, recuerda lo que escrib antes: "& significa 'direccin de' y *significa el 'valor que esta en (tal direccin)'".

    printf("Vuelve a cambiar el valor de a: ");scanf("%d", b);printf("Ahora a vale %d\n", a);Aqu cambiamos el valor de a usando su apuntador en la funcin scanf, acurdate lo que significa poner el ampersand en una variable normal, aqu usamos el apuntador y obtenemos el mismo resultado.

    printf(" a + 2 es %d y *b + 2 es %d\n", a+2, *b+2);En esta lnea puedes ver cmo se pueden hacer operaciones tanto con la variable como con el apuntador (usando su asterisco claro).

    Apuntadores y funciones.Vamos a ver un uso de los apuntadores, uno bueno, espero recuerdes que cuando pasamos un valor a una funcin lo que se haca en realidad era copiarloy trabajar con la copia. A veces no queremos que un programa ha