Anda di halaman 1dari 153

PRLOGO CAPTULO N 0 : INTRODUCCIN CAPTULO N 1 : DIAGRAMAS DE FLUJO

Smbolos utilizados en Diagramas de Flujo Instrucciones de Asignacin Instrucciones de Entrada y Salida Instrucciones de Control Inicio y Trmino Niveles de un diagrama de flujo. Contadores Anlisis del diagrama. Operadores Matemticos: Estructura While (Mientras) Resumen Diagramas de Flujo Resumen Diagramas de Flujo Operador Mdulo Problemas Resueltos y Propuestos

4 5 6
6 7 7 7 8 9 11 14 15 17 20 21 24 26

CAPTULO N 2 : LENGUAJE C
Un poco de historia Forma General del Lenguaje C. Estructura de un Programa Bibliotecas Indentacin Identificadores Comentarios Tipos de datos fundamentales Resumen Palabras clave Operadores Operadores Matemticos Operadores de Relacin Operadores Lgicos Comenzando a Programar Declaracin de variables Asignacin: Inicializacin Entrada / Salida Estndar printf() scanf()

36
36 37 38 39 39 39 40 40 41 41 41 42 42 42 42 43 44 44 44 46

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Resueltos y Propuestos

50

CAPTULO N 3: ESTRUCTURAS DE CONTROL


Estructura if Proposicin if - else Estructura while (Mientras) Algo ms del if Algo ms del while Estructura for Ciclo do-while Proposicin break Proposicin Continue Proposicin switch Problemas Resueltos y Propuestos

54
54 54 56 59 60 61 62 63 63 63 66

CAPTULO N 4 : FUNCIONES EN C
Instruccin return Variables Globales y Locales Llamadas a Funciones Paso de Parmetros a funciones Paso de variables por valor Problemas Resueltos y Propuestos

72
73 74 75 77 78 83

CAPTULO N 5 : ARREGLOS O MATRICES


Arreglos de n-dimensiones Constantes Simblicas Cadenas de Caracteres Cadenas sin tamao definido Como retornar un string Arreglos como parmetros Problemas Resueltos y Propuestos

87
89 90 94 95 96 97 101

CAPTULO N 6 : MODOS DE ALMACENAMIENTO


Variables Automticas (auto) Variables Externas (extern) Variables Registro (register) Variables Estticas (static) Variables estticas externas

110
110 110 111 112 112

CAPTULO N 7 : PUNTEROS EN C
Operador & Operador * Paso de parmetros por referencia Aritmtica de Punteros Algo ms sobre punteros malloc, free y sizeof
Profesor: Roberto Uribe P.

113
113 114 115 118 119 119
Pg. N 2

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Un ejercicio grfico Problemas Propuestos

121 124

CAPTULO N 8 : TYPEDEF, STRUCT Y UNION


Typedef Estructuras Arreglos de estructuras Algo ms sobre estructuras Estructuras Anidadas Funciones y Estructuras Punteros a Estructuras Algo ms sobre punteros a estructuras Uniones (unin) Problemas Resueltos y Propuestos

125
125 126 127 131 131 133 134 135 136 138

CAPTULO N9 : ARCHIVOS EN C (EN CONSTRUCCIN)


Tipo usado en archivos FILE Funciones para manejo de archivos Un ejemplo interesante con fread

144
144 144 144 149

LTIMAS NOTAS ANEXO N 1 : ESTRUCTURA DE UN COMPILADOR ANEXO N 2 : ALGUNOS CONCEPTOS

151 152 153

Profesor: Roberto Uribe P.

Pg. N 3

Programacin de Computadores y el Lenguaje C

(versin 2003)

UNIVERSIDAD DE MAGALLANES FACULTAD DE INGENIERA ESCUELA DE COMPUTACIN

Programacin de Computadores Profesor: Roberto Uribe Paredes

Prlogo

Cada vez que hacemos uso de una computadora, debemos enfrentarnos a distintos software, que van desde el sistema operativo hasta las planillas electrnicas, procesadores de texto, software de comunicacin, etc. Todos ellos son programas, y han demandado un arduo trabajo que involucr tanto a analistas, diseadores y programadores. Las etapas en el desarrollo de un software son bastantes y generalmente no fciles, ms an cuando en la actualidad las necesidades son complejas. El presente texto no pretende abarcar el rea de desarrollo de software ni las etapas de este, sino insertar al alumno en el pensamiento lgico, necesario para desarrollar nuestros primeros programas. Para cumplir este objetivo primero se emplea un mtodo grfico para resolucin de problemas, Diagramas de Flujo. Luego se inserta al alumno en el formalismo de un lenguaje de programacin, C, empezando por resolver los problemas vistos con el mtodo anterior. Finalmente, se van complicando los problemas a resolver, ahora slo utilizando el lenguaje formal, de tal manera de ir adquiriendo los conocimientos necesarios para resolver ciertos problemas. El texto1 contiene problemas y ejercicios resueltos para cada captulo, adems, cada uno de estos ejercicios tiene el anlisis y la explicacin del mtodo usado para resolverlo. Tambin se incluye la ejecucin de algunos de los programas, es decir, el cmo funciona. Al finalizar el curso el alumno estar capacitado para analizar, resolver e implementar soluciones (programas) a diversos problemas de aplicaciones computacionales.

La primera versin del texto comenz a escribirse en 1995.


Pg. N 4

Profesor: Roberto Uribe P.

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Captulo N 0 : Introduccin

Dentro de los mtodos usados para resolver problemas en lo que llamamos programacin estructurada est el conocido como Diseo Top-Down. Este consiste en dividir el problema en partes, de tal manera de crear subproblemas que son ms fciles de resolver, si estos subproblemas son lo suficientemente complicados, entonces se vuelve a dividir. Esta divisin se hace hasta dejar pequeos problemas, los cuales se pueden resolver como mdulos independientes. Luego de esto se van uniendo los mdulos (soluciones) de tal manera de resolver el problema original. El diseo top-down responde a la idea de que es ms fcil manejar pequeos problemas y resolverlos uno a uno a enfrentar un slo problema de mayor complejidad. Cuando se habla de este diseo se lo asocia a la frase dividir para reinar, que es el mismo concepto, es decir, dividir nuestro problema para cumplir nuestros objetivos. En los primeros captulos de este texto los problemas planteados son lo bastante sencillos para poder resolverlos como un mdulo. Posteriormente cuando la complejidad aumenta se aplica el diseo top-down, esto es posible ya que nuestros pequeos problemas los resolvemos en lo que conoceremos como funciones.

Profesor: Roberto Uribe P.

Pg. N 5

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N 1 : Diagramas de Flujo La programacin de computadores, es darle rdenes a un computador, comnmente escritas, para ello existen pasos previos: - Para qu queremos programarlo? - Qu secuencia de rdenes ser la ms eficiente? - Qu lenguaje emplearemos? Por lo general para responder a estas interrogantes se hace uso de diagramas (se entiende ms fcilmente un mapa que una secuencia de coordenadas). Existen a lo menos tres formas grficas para representar soluciones a problemas: - Diagrama de Flujo. - Diagrama de BOHM y Jacopini - Diagrama F.P.L. (First Programming Languaje). El ms comn es el Diagrama de Flujo. Los diagramas de flujo estn siendo cada vez menos utilizados, esto debido, a que los computadores tienden cada vez ms a los lenguajes naturales. Los niveles en que se representa un diagrama pueden ser tres: * Nivel conceptual * Nivel Algortmico. * Nivel Instruccin. Definir estos tres niveles es arbitrario y depende de la complejidad del problema. Antes de comenzar a solucionar un problema hay que tener muy claro cuales son los objetivos generales que se persiguen, esto es, saber exactamente lo que se esta pidiendo (Para qu queremos programarlo?). El prximo paso a seguir es determinar una secuencia de instrucciones que de solucin al problema, esta secuencia se conoce como "Algoritmo", para problemas clsicos como ordenar y buscar existen ya diferentes algoritmos de solucin. Ejemplos de algoritmos de ordenacin: - Mtodo de la Burbuja - Mtodo de Seleccin - Algoritmo de Mezcla

Smbolos utilizados en Diagramas de Flujo Todo lenguaje de programacin posee tres tipos bsicos de instrucciones: - Asignacin - Entrada/Salida
Profesor: Roberto Uribe P. Pg. N 6

Universidad de Magallanes - Departamento de Ingeniera en Computacin

- Control (Los diagramas de flujo no estn ajenos a esta clasificacin). Instrucciones de Asignacin Se refiere comnmente a acciones a seguir o clculos que quedan almacenados en algn lugar (variables de memoria): Ejemplos:
Tomar Lapiz Sumar A y B

producto=A*B

Se usa el rectngulo para identificar asignaciones. Instrucciones de Entrada y Salida Toda mquina en general requiere comunicarse con el mundo exterior (generalmente usuarios), es decir, necesita de instrucciones de entrada y salida, estas se denotan por un rombo (o romboide). Ejemplos :
Imprimir Datos Leer Palabra

Salida

Entrada

Los rombos se acompaan de una flecha, que indica la entrada o salida de informacin. Instrucciones de Control Un programa es una secuencia de instrucciones que dependiendo de resultados parciales, la secuencia puede ser alterada. Para ello se utiliza el smbolo:

No

Pregunta

Si

Dependiendo de la condicin, si es verdadera o falsa toma uno de los sentidos.

Profesor: Roberto Uribe P.

Pg. N 7

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejemplo:
No Nota >= 50 Si

Reprobado

Aprobado

Se utiliza a veces el smbolo de decisin con ms de dos salidas, por ejemplo:

<30

NotaFinal >=30

>=50

Reprobado

Da Examen

Aprobado

Inicio y Trmino Para especificar el Principio o fin de una secuencia, se utiliza el smbolo.

Ejemplo:
Inicio

Proceso

Fin

Los smbolos de diagramas de flujo se unen con rectas, dos rectas se pueden unir, pero una recta no puede dividirse en dos.

Profesor: Roberto Uribe P.

Pg. N 8

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ejemplos:
Paso1 Sumar i y j

Error

Paso2

Paso3 Paso1 Paso4 Paso2

Fin

Incorrecto !!

Correcto !!
Para que exista una bifurcacin en un Diagrama de Flujo., necesariamente debe existir un smbolo de decisin.
Sumar i y j

Correcto !!
No Pregunta? Si

Paso1

Paso2

Niveles de un diagrama de flujo. - Nivel Conceptual - Nivel Algortmico - Nivel Instruccin

Profesor: Roberto Uribe P.

Pg. N 9

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejemplos: 1). Nivel Conceptual: (Llamada de telfono)


Inicio

2) Nivel Algoritmo (llamada de telfono pblico)


Inicio

Levantar fono Buscar Telfono No Discar Insertar Moneda Discar Colgar No Fin Contestan? Si Hablar Hay Tono? Si

Hablar

Colgar Fin

3) Nivel Instruccin. Ejemplo: Leer A y B, luego sumar A y B y asignarla a C.


Inicio

Leer A Leer B C=A+B

Fin

Profesor: Roberto Uribe P.

Pg. N 10

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Lo que hace el programa anterior es leer dos variables A y B desde algn dispositivo de entrada (como el teclado), sumarlas y asignar el resultado a C.
Inicio

A=5 B=6 C=0

C=A+B

Fin

En este caso A y B ya tenan valores asignados antes de la suma. La suma de "A" y "B" se asigna a "C", independiente del valor anterior de "C". Este ejemplo hace lo mismo que el anterior, pero se inicializan las variables al comienzo del programa. En ambos ejemplos se utilizaron instrucciones bsicas de entrada, salida y de asignaciones. El nivel de instruccin es mas prximo a la programacin de computadores, los niveles anteriores son simplemente para representar divisiones ms gruesas de un problema, como las situaciones cotidianas indicadas.

Contadores Los contadores son variables de memoria (de ahora en adelante "variable"), que se incrementan o decrementan de acuerdo a la necesidad del programador, se denotan de la siguiente manera (asignacin):

contador=contador+1

El smbolo igualdad tiene un significado diferente que en aritmtica, "lo que existe a la derecha es una expresin y lo que existe a la izquierda es una variable". Una vez realizada la operacin la variable asume el valor de la expresin. Para este caso, el contador fue incrementado en 1. Generalmente los contadores son utilizados por ejemplo, para llevar la cuenta de los datos que vamos a ingresar por teclado, cuantos datos estamos imprimiendo en pantalla, es decir, en ciclos o iteraciones. En si un contador forma parte de una asignacin.
Profesor: Roberto Uribe P. Pg. N 11

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejemplo de asignaciones e incrementos:


Inicio

A=0 B=5 A=A+1

A=0,B=5

A=1

A=A+B

A=6

Fin

La forma de analizar este diagrama es de la siguiente manera: - A parte en 0, B se inicializa en 5. - Luego en la lnea A=A+1, esto se reemplaza por A=0+1, es decir A queda igualada a 1 (se incrementa en 1). - Finalmente A=A+B, se reemplaza por A=1+5, es decir 6 (se incrementa en 5). Ejercicio 1.1: Suponga que para aprobar una asignatura, a un alumno se le calcula el promedio aritmtico, luego si este es superior o igual a 50, entonces esta aprobado (eximido), si el promedio es menor a 50, pero mayor o igual a 30, tiene derecho a dar examen. Si el promedio es menor que 30, reprueba sin derecho a dar examen, la escala de evaluacin es de 0 a 100. Entonces, Sumar tres notas, si el promedio es mayor o igual a 50, entonces "eximido", si es mayor o igual que 30 y menor que 50, entonces "da examen", si es menor que 30, entonces "reprobado". El examen vale 30% y el promedio 70%. Realizaremos un primer intento de programa. Como son tres notas las que hay que leer, entonces crearemos tres variables, una para cada nota. Tambin una variable para almacenar la suma y otra para el promedio. Sin Lectura del examen, slo imprimiendo "eximido", "da examen" y "reprobado".

Profesor: Roberto Uribe P.

Pg. N 12

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Inicio Leer Nota1 Leer Nota2 Leer Nota3 Suma=Nota1+Nota2+Nota3 promedio=suma/3

Es No promedio>=50 Si

Es No promedio>=30 Si Eximido

Reprobado

Da Examen

promedio Fin

El promedio se imprime al final para evitar hacerlo tres veces (una por cada bifurcacin). El promedio podra haberse calculado sin necesidad de utilizar la variable suma, es decir, slo con promedio=(nota1+nota2+nota3)/3, utilizando las mismas normas que en matemticas (sea la suma entre parntesis). Esto depende exclusivamente del programador. En nuestro programa falt calcular la nota final si el alumno da examen. Una nueva versin de nuestro diagrama sera:

Profesor: Roberto Uribe P.

Pg. N 13

Programacin de Computadores y el Lenguaje C

(versin 2003)

Inicio

Leer Nota1 Leer Nota2 Leer Nota3 Suma=Nota1+Nota2+Nota3 promedio=suma/3

Es No promedio>=50 Si

Es No promedio>=30 Si NotaFinal=promedio

NotaFinal=promedio

Examen

NotaFinal=Examen*0.3+promedio*0.7

NotaFinal Fin

Anlisis del diagrama. En nuestro problema necesitbamos lee 3 notas, por lo tanto hacemos 3 lecturas, una para cada nota, en diagramas de flujo esto no es tan estricto, podran haberse ledo las 3 notas dentro de un mismo smbolo.
nota1, nota2, nota3

Profesor: Roberto Uribe P.

Pg. N 14

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Luego de esto sumamos las notas y se lo asignamos a la variable suma, posteriormente obtenemos el promedio. Como ya se tiene el promedio de las notas y necesitamos saber si este es mayor o igual a 50, si esta entre 30 y 49 o si es menor a 30. Entonces primeramente preguntamos si es mayor o igual a 50 , para ello utilizamos el smbolo de pregunta (smbolo de control). De esto obtenemos dos lneas, en una sacamos por pantalla aprobado, en la otra lnea volvemos preguntar es mayor o igual a 30, con esto tenemos si da examen o reprueba. En este caso se utiliz la variable nota_final para imprimir una sola vez el resultado al final del programa (diagrama). Las variables utilizadas fueron: nota1 nota2 nota3 suma promedio nota_final : primera nota leda. : segunda nota que se lee. : es la variable donde se almacena la tercera nota. : variable que guarda el resultado de la suma de las notas., : promedio de las notas. : nota final obtenida.

Operadores Matemticos: Estos se utilizan para realizar los clculos necesarios en los programas, estos van en el lado derecho de una asignacin, es decir en la expresin. En el ejemplo anterior se utiliz el operador suma en la lnea suma=nota1+nota2+nota3 y el operador divisin en la lnea promedio=promedio/3. Los operadores matemticos son: + * / : : : : Suma Resta Multiplicacin Divisin

Existe otro operador, el mdulo o resto de la divisin entera, este se ver al final de este captulo. Ejercicio 1.2: En la mayora de los problemas se necesita repetir alguna operacin (repeticiones o iteraciones). Entonces, resolver un algoritmo para el clculo del promedio con "N" notas, donde el nmero de notas es un valor conocido. Cuando se dice que una variable tiene un valor conocido, esto implica que se ingresa al programa, en este caso va teclado. Para simplificar el problema, eliminar la condicin cuando la nota es menor de 30, o sea con nota menor a 50 se da examen.

Profesor: Roberto Uribe P.

Pg. N 15

Programacin de Computadores y el Lenguaje C

(versin 2003)

Solucin (Existen otras): - Utilizaremos las variables del ejercicio anterior. - Para el ejercicio 2 agregaremos dos variables: Num_Notas : nmero de notas a leer. cont : contador de notas, servir para saber cuando terminar el programa. Esta variable se inicializar en 1. - Entonces:
Inicio

cont=1 suma=0 promedio=0 nota_final=0 Num_Notas=0 nota=0

Leer Num_ Notas

Es No cont<=Num_Notas Si

promedio=suma/Num_Notas

Leer nota suma=suma+nota

Es No Promedio>=50 Si

cont=cont+1

Leer Examen nota_final=examen*0.3+ promedio*0.7

nota_final=promedio

imprimir nota_final Fin

Profesor: Roberto Uribe P.

Pg. N 16

Universidad de Magallanes - Departamento de Ingeniera en Computacin

En este ejercicio se inicializ todas las variables, esto se usa como norma para ayudar a mantener el orden en los programas.

Estructura While (Mientras) La estructura denotada por:


Es ?

No

Si

Se puede utilizar como "estructura while", la palabra "Es" se reemplaza por "Mientras", en el ejercicio 2.

Mientras

No

cont<=Num_Notas

Si

Proceso

Entonces se produce un ciclo o "Loop". La idea del ciclo while es formular la siguiente pregunta: Mientras, la condicin sea verdadera .... hacer .... Una forma adecuada de ver si un programa funciona correctamente es trazndolo, en nuestra jerga diramos que lo ejecutamos en papel. Para ello creamos tantas columnas como variables declaradas tengamos, luego vamos colocando valores en las columnas a medida que las variables asuman estos valores, con esto vemos el comportamiento de cada variable y de los ciclos. Por ejemplo veamos la ejecucin del ejercicio N 1.2. Primero supongamos que las notas que se van a leer son tres, 60, 60 y 50, entonces el comportamiento de las variables sera como se muestra en la tabla siguiente:
1 2 3 4 Num_Notas 0 3 nota 0 60 60 50 suma 0 60 120 170 cont 1 2 3 4 promedio 0 nota_final 0 examen

55

55

Profesor: Roberto Uribe P.

Pg. N 17

Programacin de Computadores y el Lenguaje C

(versin 2003)

Imagine que se va ejecutando sentencia a sentencia (cada sentencia esta representada por una figura). En la fila 1 se muestra la inicializacin de todas las variables, menos examen. La siguiente instruccin es la lectura de Num_Notas (cantidad de notas), se ingresa un 3 al programa, y en la ejecucin se coloca el 3 en la variable que corresponde, esto se ve en la fila 2. Luego se para en la instruccin de control y se pregunta Es cont<=Num_Notas, entonces cont tiene el valor 1 y Num_Notas es 3, por lo tanto el control del programa se va por la alternativa si. Despus de esto viene la instruccin de lectura, donde se ingresa la primera nota, si ingresamos el 60, entonces la variable nota asume este valor, y lo agregamos en nuestra tabla en la fila 2 (columna nota). Pasamos a la siguiente instruccin, suma=suma+nota, el valor se suma es 0 y el valor de nota es 60, entonces la suma da 60, este valor lo colocamos en la fila 2 columna suma. Seguido se incrementa el contador en cont=cont+1, como cont vala 1, entonces ahora vale 2, con esto se termina el primer ciclo ya que el control vuelve hacia arriba y nuevamente se hace la pregunta Es cont<=Num_Notas. Como cont es menor que Num_Notas, entonces el control se va por la derecha (alternativa si), se lee la segunda nota (60) y se asigna a la variable nota, luego a suma se le asigna suma+nota, el valor de suma es 60 y nota vale 60, por lo tanto ahora suma tiene el valor 120, este valor se coloca en la fila 3, columna suma. La siguiente instruccin es el incremento del contador, cont tena el valor 2, ahora se incrementa en 1, por lo tanto ahora tiene el valor 3. El control vuelve a la instruccin de control, como cont sigue siendo menor o igual que Num_Notas, entonces el control entra nuevamente en el ciclo. Se lee la nota 50, se hace la suma de nota que vale 50 y suma que vale 120, entonces ahora suma vale 170. Luego el contador cont se incrementa en 1, es decir, queda en 4. Retorna a la instruccin de control y ahora la condicin va a ser falsa, ya que cont tiene el valor 4 y Num_Notas 3, entonces el control elige la alternativa no. La siguiente instruccin es promedio=suma/Num_Notas, con esto promedio asume el valor 55, este se coloca en la fila 4. Luego se pregunta Es promedio>=50, esto verdadero, por lo tanto se va por la alternativa si. Luego se realiza la asignacin nota_final=promedio, este se ve en la fila 4, ahora nota_final vale 55. Finalmente el valor 55 se imprime en pantalla. Como ejercicio analice cuando las notas ingresadas son 60, 45, 40 y 50. La ejecucin resultara como la siguiente tabla:
1 2 3 4 5 Num_Notas 0 4 nota 0 60 45 40 50 suma 0 60 105 145 195 cont 1 2 3 4 5 promedio 0 nota_final 0 examen

48,75

50,625

55

Profesor: Roberto Uribe P.

Pg. N 18

Universidad de Magallanes - Departamento de Ingeniera en Computacin

En este caso el promedio es menor que 50, entonces se debe dar examen, suponiendo que en el examen se obtuvo un 55, entonces se calcula la nota final multiplicando promedio por 0.7 y examen por 0.3. Finalmente nota_final va a valer 50,625. El problema recin resuelto, slo permite 1 alumno. Ejercicio 1.3: - Para el problema anterior (N 1.2), resolver para un curso completo, donde el N de alumnos es un dato conocido. Obtener promedio e imprimirlo. - Para simplificar el ejercicio, slo se calcular el promedio de los alumnos, no la determinacin si se dar o no examen.

Profesor: Roberto Uribe P.

Pg. N 19

Programacin de Computadores y el Lenguaje C

(versin 2003)

Inicio

cont_alum=1 Num_Alum=0 cont_notas=1 suma=0 promedio=0 Num_Notas=0 nota=0

Leer Num_ Alum

Mientras No cont_alum<= Num_Alum Si

cont_notas=1 suma=0

Fin

Leer Num_ Notas

Leer Nombre_ Alumno

Mientras cont_notas<= Num_Notas Si Leer nota No suma=suma+nota

cont_notas=cont_notas+1

promedio=suma/Num_Notas

promedio Nombre_ Alumno

cont_alum=cont_alum+1

Profesor: Roberto Uribe P.

Pg. N 20

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Resumen Diagramas de Flujo Como regla general, un programa se hace de la siguiente forma:
Inicio

Inicializacin de Variables

Ingreso de Datos

Clculos

Resmenes

Impresin de Resultados Fin

- Estructura If.....Then.....Else
IF ELSE (Falso) No THEN (Verdadero) Si

Condicin ?

PROCESO

PROCESO

- Estructura While
WHILE

(Falso)

Condicin ?

HAGA (Verdadero)

Proceso

Profesor: Roberto Uribe P.

Pg. N 21

Programacin de Computadores y el Lenguaje C

(versin 2003)

Existen dos tipos de estructura while: 1.- Cuando se conoce a priori el nmero de veces que se repite un proceso, - Promedio Nota - Clculo para n alumnos 2.- Cuando no se conoce las veces que se repite un proceso. Ejemplo:

F=
i=1

1/i

Determinar F de tal manera que si 1/i 10 -3, entonces terminar. Es decir, se van obteniendo resultados hasta que el rango sea menor o igual a 0,001. Con esto se obtiene una aproximacin del resultado.

Inicio

F=0 i=1 Eps=0,001

While No 1/i >= Eps Si

i ,F Fin

F = F + 1/ i

i=i+1

Como el contador i va aumentando, entonces 1/i va disminuyendo. - Cuando se conoce antes la cantidad de iteraciones de un proceso, la estructura While puede reemplazarse por una estructura For (Para), esta se simboliza de la sgte. manera:

Profesor: Roberto Uribe P.

Pg. N 22

Universidad de Magallanes - Departamento de Ingeniera en Computacin

contanotas: 1

Si

Proceso

Es decir, el contador contanotas se ir incrementando de 1 hasta n, y por lo tanto el proceso dentro del ciclo for se realizar n veces. Para el ejercicio del promedio de un curso con "N" alumnos y "N" notas (ejercicio N 3), si utilizamos ciclos for, nuestro diagrama quedara:
Inicio

cont_alum=1 Num_Alum=0 cont_notas=1 suma=0 promedio=0 Num_Notas=0 nota=0 Leer Num_ Alum

cont_alum: 1

Num_Alum

Si

suma=0 Num_Notas Nombre_ Alumno

Fin

cont_notas: 1

Num_Notas

Si Leer nota

suma=suma+nota

promedio=suma/Num_Notas

promedio Nombre_ Alumno


Profesor: Roberto Uribe P. Pg. N 23

Programacin de Computadores y el Lenguaje C

(versin 2003)

Con estructura for se eliminan la inicializacin de contadores y el incremento de estos. Ms adelante veremos que el for proporcionado por el lenguaje C es mucho ms flexible. Nota: Todos los lenguajes de programacin poseen las estructuras hasta ahora vistas, o por lo menos asignacin, if y while (o alguna instruccin para iteraciones).

Operador Mdulo Aparte de los operadores aritmticos comunes, existe uno llamado mdulo, este se usa en variadas aplicaciones y su uso es bastante frecuente en programacin. El operador mdulo nos permite obtener el resto de la divisin entera, ejemplo: 5:2=2 1 -------> resto de la divisin sea, 5 dividido 2 es igual a 2 y sobra 1, este es el mdulo o resto. Utilizaremos el smbolo % para denotar el operador mdulo, que es precisamente el que utiliza C. Para el ejemplo anterior, 5 % 2 -----> 1 Otros ejemplos: 12 : 3 = 4 0 -------> resto (mdulo) 26 : 3 = 8 2 -------> mdulo es decir, 12 % 3 -----> 0 26 % 3 -----> 2 Ejercicio 4: - Hacer un programa en el cual se ingrese un nmero y como resultado se indique si es par o impar. Entonces, sabemos que un nmero par es aquel que cuando se divide por 2 su resto es 0, por lo tanto el diagrama sera:

Profesor: Roberto Uribe P.

Pg. N 24

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Inicio

num=0

Ingrese un Nmero num

No

(num % 2)=0

Si

El nmero es impar

El nmero es par

Fin

Dentro de las aplicaciones tpicas donde se utiliza el mdulo estn, determinar si un nmero es o no primo, obtencin de los n primeros nmeros perfectos, hacer que cualquier nmero sea convertido en otro dentro de un rango especfico. Por ejemplo, para el ltimo caso, suponga que se obtienen nmeros entre 0 y 999, y se desea convertirlos al rango 0 a 10, el proceso principal sera: datonuevo= num % 11 Es decir, cualquier nmero mdulo 11 dara un nmero entre 0 y 10 (y en este caso quedara almacenado en la variable datonuevo). Generalmente se usa para que cualquier nmero obtenido de un proceso de generacin de nmeros al azar (nmeros aleatorios) est dentro del rango deseado.

Profesor: Roberto Uribe P.

Pg. N 25

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Resueltos y Propuestos Los siguientes ejercicios son clsicos en los primeros cursos de programacin. Se recomienda al alumno que resuelva los problemas y luego los compare con las soluciones planteadas en el libro, recuerde que un problema se puede resolver de muchas formas (demasiadas quiz!). Para cada solucin propuesta en el libro, ejecute en papel el programa, de esa manera se dar cuenta del funcionamiento de este. Resueltos: 1.Hacer el diagrama de flujo que calcule: xy , donde x e y son valores conocidos. 2.Resolver :
x = i
i =1 n

n : valor conocido

3.-

Escribir el diagrama de flujo para la ecuacin de 2 grado en la forma : ax2 + bx + c = 0


a, b, c constantes conocidas

con : x1 =

b + b 2 4 a c 2a b b 2 4 a c 2a

x2 =

4.-

Hacer un diagrama de flujo que lea un archivo de datos numricos : Condiciones : a) cuente los nmeros ledos b) entregue el mayor nmero ledo c) entregue el menor nmero ledo

Condicin de fin de archivo es eof (eof : end of file), es decir cuando el dato ledo es eof, entonces terminar el programa. 5.Crear un programa que lea una serie de nmeros y finalmente entregue una lista de cuantos eran pares y cuantos impares. La condicin de trmino ser cuando la cantidad de impares o pares supere 15. 6.Escribir el diagrama de flujo para la sumatoria :
Pg. N 26

Profesor: Roberto Uribe P.

Universidad de Magallanes - Departamento de Ingeniera en Computacin

y = xi
i =1

n, x : valores conocidos

7.-

Realizar el diagrama de flujo para el calculo de factorial de N. Tomar en cuenta : 0! = 1 1! = 1 N! = N*(N-1)! = N*(N-1)*(N-2)* .... *(N-N)! N : valor conocido

8.-

Escribir el diagrama de flujo para ex donde : ex = 1 + x1 + x2 + x3 + ...... + xn n! 1! 2! 3!


x : valor conocido, n=1000

Propuestos: 9.Resolver : sen x = x - x3 + x5 - x7 ...... ((-1)n *x2n+1) (2n+1)! 3! 5! 7! con x en radianes. x : valor conocido, n=10 10.Se define "promedio geomtrico" como : Prom = n (nota1 nota 2. ....notaN Realizar diagrama de flujo para resolver dicho problema. Asuma que es posible realizar la operacin de "raz ensima de un nmero" ( n ); donde n valor conocido. 11.- Escriba un programa (diagrama de flujo) que calcule a sobre b.
a a! = b b !(a b )!

a,b,c: valores conocidos.

12.-

Cree un diagrama de flujo que obtenga el resultado de la siguiente sumatoria:

Profesor: Roberto Uribe P.

Pg. N 27

Programacin de Computadores y el Lenguaje C

(versin 2003)

(2i 1)
i =1

(suponga n conocido)

13.- Resuelva la siguiente expresin :

x
i=1

(2n-1)

/(2n-1)!

- La condicin de trmino es : x(2n-1) < 0.001 (2n-1)! 14.Escriba un diagrama de flujo que transforme un nmero de cualquier base a decimal. Simplificacin: asuma que la base no es mayor a 10. Debe indicar la base a la que pertenece el nmero y la cantidad de dgitos que contiene este. Ejemplo : Para transformar el nmero 143 en base 5 a decimal el programa debera funcionar as:
Programa que transforma nmeros a decimal : ingrese la base : 5 ingrese la cantidad de dgitos : 3 ingrese digito 1 : 1 ingrese digito 2 : 4 ingrese digito 3 : 3 El nmero en base 10 es : 48

Note que la base puede ser cualquiera ingresada por teclado.

Profesor: Roberto Uribe P.

Pg. N 28

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Soluciones: 1.x elevado a y es la multiplicatoria de x y veces, es decir, esto lo asociamos a un ciclo que nos permita ir de 1 hasta y. Usualmente al ciclo va ligado un contador que lleve en nmero de veces del ciclo. Tambin, debemos tomar en cuenta una variable auxiliar que nos permita ir almacenando el valor anterior de la multiplicatoria. Lo ltimo es que x e y son valores conocidos, entonces debemos ingresarlos, por ejemplo por teclado.
Inicio x=0 , y=0 cont=1 resultado=1 x,y

While No cont<= y resultado=x*resultado "x elevado a y es", resultado Fin cont = cont + 1 Haga

Finalmente, debe tomar en cuenta que la variable auxiliar resultado se inicializa en 1, esto dado que 1 es el neutro multiplicativo, no puede ser 0, ya que el resultado final sera 0. El contador cont podra comenzar en 0, pero habra que modificar la condicin del while por cont<y (menor absoluto), de otro modo el resultado sera errneo (se multiplicara una vez mas). Para un mejor entendimiento de la solucin ejecute (en papel) el programa y modifique los valores de resultado y cont, de tal manera de comprobar los errores que se provocaran. Nuestro programa funciona para x distinto de 0 e y mayor o igual a 0, de otra manera el programa arrojara un resultado errneo. Modifique el diagrama para tomar en cuenta los casos anteriores.

2.Para este ejercicio, la sumatoria va de 1 hasta n, con n conocido (ingresado al programa). Entonces, los elementos que necesitamos son: un ciclo (por ejemplo while), un contador y una variable auxiliar que almacena la suma sucesiva.

Profesor: Roberto Uribe P.

Pg. N 29

Programacin de Computadores y el Lenguaje C

(versin 2003)

Inicio

i=1 ,x=0 n=1

"Sumatoria de i, de 1 hasta n, Ingrese n mayor o igual a 1." n

While No i<=n x=x + i "El resultado de la sumatoria es ", x Fin Haga

i=i+1

Observe que en este caso la sumatoria (variable x) comienza en 0. El programa podra modificarse de tal manera que si el valor ingresado es menor que 1, entonces enviar un mensaje de error al usuario.

3.Para este caso no es necesario utilizar ciclos, ya que se conocen todos los valores de los datos y slo se debe resolver la frmula indicada. Lo nico que hay que considerar es cuando el discriminante de la ecuacin sea negativo, en este caso, como no podemos obtener la raz de un nmero negativo, entonces lo que hacemos es que la salida por pantalla slo represente al nmero imaginario. En este caso no se podra operar con un nmero imaginario, sin embargo, en un lenguaje de programacin se podran crear las estructuras necesarias para realizar las operaciones entre nmeros imaginarios.

Profesor: Roberto Uribe P.

Pg. N 30

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Inicio a=0,b=0 ,c=0 discr=0 x1=0,x2=0 "resolucin de la ecuacin cuadrtica: ax2+bx+c=0 Ingrese valores para: a, b, c" a,b,c

Si No a=0 discr=b*b-4*a*c x1=-c/b "x = ", x1 Si No discr>=0 discr=-discr x1=(-b+ discr )/(2*a) x2=(-b - discr )/(2*a) "Soluciones Reales", "x1 = ", x1 "x2 = ", x2 Si Si

"Soluciones Imaginarias" "x1= ", - b/(2*a), "+", discr /(2*a), "i" "x1= ", - b/(2*a), "-", discr /(2*a), "i"

Fin

En la solucin al problema se tom en cuenta cuando el valor de a es 0, en ese caso la ecuacin resulta de primer grado, por lo tanto la frmula para resolverla es la trivial. Cuando el resultado son nmeros imaginarios, la salida por pantalla es slo representativa. Asuma que en este caso, lo que esta entre comillas dobles es texto y lo dems son valores. Un ejemplo de una solucin imaginaria en nuestro diagrama podra ser (para a=2,b=4,c=5):
x1 = -2 + 12 i x2 = -2 - 12 i

4.Para este problema podemos tomar en cuenta los siguientes supuestos: se puede leer un dato numrico y preguntar si este es eof. A pesar de que los datos estn en un archivo, se ocupa el mismo smbolo para la entrada.
Profesor: Roberto Uribe P. Pg. N 31

Programacin de Computadores y el Lenguaje C

(versin 2003)

En este caso debemos usar un ciclo while que termine cuando el dato sea igual a eof. No se puede usar for, ya que no se sabe la cantidad de veces que se repite el ciclo. No es necesario usar un contador.
Inicio dato,max,min

dato Si dato=EOF

No

Si "No existen datos"

max=dato min=dato

No

While dato<>EOF

Haga Si dato>max max=dato

"El mximo es:", max, "El mnimo es:", min

Si dato<min min=dato dato

Fin

En nuestro programa se ha considerado el caso en que el archivo este vaco, es decir, el primer dato es EOF. Luego de haber ledo el primer dato, se asigna como mximo y mnimo, esto resulta lgico dado que es el nico dato ledo. La primera iteracin no afecta, sin embargo, al leer el segundo dato, este se compara con el mximo (el dato anterior), si resulta ser mayor, entonces se reemplaza, de igual manera con el mnimo. As sucesivamente se va comparando el nuevo dato con el mximo y mnimo anterior. 5.Para el siguiente diagrama, sabemos que tenemos que leer una serie de nmeros, pero no sabemos cuantos. Entonces, necesitamos un ciclo cuya condicin de trmino sea "la suma de pares o impares sea mayor o igual a 15", por lo tanto, se crean dos variables, una que cuente los pares y la otra los impares. Para terminar el ciclo una u otra debe ser mayor o igual a 15
Profesor: Roberto Uribe P. Pg. N 32

Universidad de Magallanes - Departamento de Ingeniera en Computacin

(basta que uno llegue a 15 para terminar). Es esencial notar la importancia del o en la pregunta.
Inicio cuenpar=0 cuenimpar=0 num=0 "Ingrese Datos

Si

Si cuenpar>15 No

Si

Si cuenimpar>15

No num Si (num mod 2)=0

No Cantidad de "Pares:, cuenpar Impares:,cuenimpar Fin

Si

cuenimpar=cuenimpar+1

cuenpar=cuenpar+1

Las dos condiciones del diagrama anterior se pueden reemplazar por una sola.

Si

While cuenimpar>15 o cuenpar>15

No

Nota: La condicin podra haber sido:


No While cuenimpar<=15 y cuenpar<=15 Si

Es decir, "si ambos son menores que 15, entonces lea datos". Note que estn invertidos los smbolos y se reemplaz el o por el y. 6.Este problema involucra una sumatoria y una multiplicatoria (potencia). Si utilizramos funciones (mdulos) podramos resolver la sumatoria y llamar al mdulo que calcula el xi cada vez (con un i diferente por vez). Sin embargo, por ahora resolveremos ambos problemas en un solo ciclo.
Profesor: Roberto Uribe P. Pg. N 33

Programacin de Computadores y el Lenguaje C

(versin 2003)

Entonces, necesitamos una variable que almacena la sumatoria (suma) y otra la potencia (pot), con un contador (i) que vaya de 1 a n.
Inicio suma=0, pot=1, i=1 n

No

While i<=n

Si pot=pot * x

La sumatoria es :", suma Fin

suma=suma + pot i=i + 1

Este ejercicio puede haber sido resuelto usando la estructura for. Modifique el programa para que arroje un error si el n ingresado es menor que 1.

7.El factorial de un nmero es la multiplicatoria de 1 hasta el nmero, adems, sabemos que si el nmero es 0 o 1, el factorial es 1.
Inicio fact=1 i=1 n

Si

Si n=0

No i:1 n Si fact=fact * i

El factorial es :", fact Fin

Observe que si n es igual a 0, la lnea va directo hacia un smbolo de salida. Esto es correcto dado que fact se inicializ en 1 y por lo tanto la salida para n=0 ser 1.

8.El este ejercicio el ciclo iterar hasta 1000, sin embargo, esto es a modo de ejemplo, dado que al usar un compilador cualquiera el programa fallara por un problema de overflow
Profesor: Roberto Uribe P. Pg. N 34

Universidad de Magallanes - Departamento de Ingeniera en Computacin

(esto es lgico ya que 1000! es un valor excesivamente grande). Al traducir el diagrama a un lenguaje el valor 1000 debe modificarse por otro (ejemplo 10).
Inicio eelevx=1,x=0 pot=1,div=0 fact=1, i=1 x

No

While i<=1000

Si pot=pot * x

e elevado a x es :", elevx Fin

fact=fact * i div=pot / fact eelevx=eelevx + div i=i + 1

Observe que la variable elevx comienza en 1, esto es para obtener el primer valor de la sumatoria. Usualmente, para el clculo de este tipo de constantes se utiliza un rango, de tal manera que cuando este sea despreciable, entonces se termina el programa. Por ejemplo, cuando la variable div sea inferior a 0,001, entonces agregar el valor que se obtenga en el prximo ciclo no influir demasiado en nuestra respuesta. Modifique el programa de tal manera que este termine cuando div sea menor o igual a
0,001.

Profesor: Roberto Uribe P.

Pg. N 35

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N 2 : Lenguaje C

Un poco de historia C es un lenguaje de propsito general, es decir, se pueden desarrollar aplicaciones de diversas reas. Dentro de sus principales caractersticas podemos mencionar que, es un lenguaje estructurado, tiene una abundante cantidad de operadores y tipos de datos, es un lenguaje de nivel medio, pero se puede codificar a alto nivel, produce cdigo objeto altamente optimizado, posee punteros y capacidad de aritmtica de direcciones. C fue creado en los Laboratorios Bell de AT&T para correr originalmente en el sistema operativo Unix, sin embargo en la dcada de los 80 aparecieron versiones para computadores personales. Existe una ntima relacin entre Unix y C, ya que el primero fue reescrito en C, as como el propio compilador de C y la mayora de las herramientas de Unix, sin embargo, no esta ligado a ningn sistema operativo o mquina. C fue diseado por Dennis Ritchie en 1972 a partir de un lenguaje llamado B escrito por Ken Thompson en 1970, que a su vez fue inspirado en uno llamado BCPL concebido por Martin Richard en 1967. Entre sus mltiples ventajas podemos mencionar que C es un lenguaje muy portable, es decir, es independiente de la arquitectura de la mquina y con alguna o ninguna modificacin un programa puede correr en una amplia variedad de computadores. Es relativamente flexible en la conversin de datos (a veces se toma como desventaja). Su eficiencia y claridad han hecho que el lenguaje ensamblador casi no haya sido utilizado en Unix. El compilador de C es pequeo y tiene un gran podero debido a sus mltiples bibliotecas. Sin embargo, tiene sus desventajas y entre ellas se puede mencionar: la excesiva libertad en la escritura del cdigo fuente hace que muchas veces se cometan errores de programacin, que, por ser correctos sintcticamente no se detectan en tiempo de compilacin o a simple vista. Carece de instrucciones de entrada y salida, de manejo de strings (cadenas de caracteres), quedando el trabajo en manos de las bibliotecas provocando con esto algunos problemas de portabilidad. Hay mltiples ejemplos de aplicaciones construidas en C, como ser: construccin de sistemas operativos, procesadores de texto, administradores de bases de datos (por ejemplo Clipper), programas para Windows y Windows 95, las APIs (Application Program Interface) de las Libreras de Enlace Dinmico (DLL) de Windows estn construidas mayoritariamente en C. Con algo de experiencia se pueden crear compiladores, sobre todo con ayuda de herramientas como Lex y Yacc que tambin estn hechas en C.

Profesor: Roberto Uribe P.

Pg. N 36

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Forma General del Lenguaje C. Para crear un programa en C, se escribe el cdigo fuente (programa), luego se compila y finalmente se enlaza con las bibliotecas (se hace un link, en nuestra jerga diramos se linkea). Cdigo Fuente Compilar Enlazar (link) Todo lenguaje de programacin posee palabras claves, estas son aquellas palabras que reserva el lenguaje para identificar ciclos, estructuras y en general cualquier cosa que sea parte de instrucciones, por ejemplo, las palabras while, if, struct son palabras claves en C. En C las palabras claves o reservadas deben escribirse en minsculas, esto ya que C diferencia entre maysculas y minsculas (a diferencia del lenguaje Pascal). El Lenguaje C se escribe a partir de un programa principal y de funciones, el programa principal tambin es una funcin (funcin principal), y se denomina main(), esta debe estar siempre presente y es la primera en ser llamada. Para hacer un programa en C, lo primero que se debe hacer es crear el programa fuente (con extensin ".c") en un editor de textos, en el caso de Unix, este puede ser el llamado vi que esta presente en la mayora de las versiones de este sistema operativo, entonces se hara de la siguiente manera:
vi <nombre_del_programa_c>

luego escribir el programa, salir del editor y compilarlo con el compilador cc u otro que posea el sistema:
cc <nombre_del_programa_c>

Despus de esto se genera el archivo ejecutable a.out, que se ejecuta:


a.out

./a.out

(los smbolos "./" especifican en directorio actual)

Luego se podra cambiar el nombre del ejecutable con el comando mv de unix, esto sera:
mv a.out <nombre_nuevo>

o compilar el programa con la opcin -o:


cc -o <nombre_archivo_ejecutable> <nombre_del_programa_C>

Profesor: Roberto Uribe P.

Pg. N 37

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejemplo: 1) vi primero.c 2) cc primero.c quedara a.out 1) vi primero.c 2) cc -o primero primero.c el ejecutable sera primero

Para el caso de los compiladores para computadores personales, estos vienen en ambientes que integran un editor de texto y el compilador. En este caso para compilar y enlazar se usa el men del editor o teclas de funcin (Hot keys), esto ltimo depende del producto. En la actualidad, todos o la mayora de los compiladores de C soportan el estndar ANSI de C. Dependiendo de la mquina donde se ejecute el compilador, se incluyen bibliotecas aparte para diferentes procesos, como ser, bibliotecas con funciones para aplicaciones grficas, etc. Estructura de un Programa Cuando se escribe el programa se recomienda usar el siguiente formato:
llamadas a bibliotecas declaracin de funciones declaracin de variables globales (prototipos de funciones)

main() { declaracin de variables locales sentencias } definicin de funciones

Nota: Dentro de las sentencias tambin se pueden encontrar llamadas a funciones, las funciones son escritas del siguiente modo:
func() { declaracin de variables locales sentencias }

o tambin:
func(variables de paso) declaracin de variables de paso { declaracin de variables locales sentencias }

A las variables de paso, se llamarn parmetros de la funcin. Sin embargo, las funciones se tratarn ms adelante.
Profesor: Roberto Uribe P. Pg. N 38

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Bibliotecas Por lo general las bibliotecas contienen funciones creadas por el programador o entregadas con el producto. Por ejemplo las funciones de entrada y salida vienen especificadas en la biblioteca de entradas y salidas estndar stdio.h (Standar Input Ouput Header). Cuando desde el programa fuente se llama a una funcin que no esta escrita en dicho programa, al compilar se mantiene el nombre y luego al enlazar con las bibliotecas se busca el nombre de la funcin dentro de estas. Para poder utilizar una biblioteca o archivo de cabecera se usa el smbolo # seguido de la palabra reservada include, luego el nombre de la biblioteca, esto se hace al comienzo del programa. Por ejemplo, para llamar a la biblioteca stdio.h se hace de la siguiente manera:
# include <stdio.h>

El nombre aparece entre menor y mayor (< >), esto significa que al enlazar buscar el archivo en el directorio especificado para los archivos de cabecera, si el archivo aparece entre comillas dobles (" "), entonces lo buscar en el directorio actual, es decir desde donde se ejecuta el programa, por ejemplo:
# include "stdio.h"

sin embargo, stdio.h siempre se encuentra en el directorio donde estn todas las bibliotecas, es decir se utiliza <>. Indentacin Este concepto se refiere a mantener un orden dentro de la programacin, es decir para que un programa sea ordenado y legible, entre otras cosas, este debe de ser modular y adems ser indentado, para revisiones futuras y mantencin de los programas. Indentar es simplemente ubicar en columnas diferentes los ciclos o estructuras internas a otras, por ejemplo:
#include <stdio.h> main() { . int i,suma=0; . i=0; . while(i<=10) . { . . i=i+1; . . . . suma=suma+i; . } . printf("\n sumatoria=%d }

\n" ,suma);

Identificadores Estos son simplemente los nombres que pueden asumir variables o constantes dentro del programa. Existen algunas restricciones para los identificadores: - No deben ser iguales a nombres de palabras reservadas o bibliotecas.
Profesor: Roberto Uribe P. Pg. N 39

Programacin de Computadores y el Lenguaje C

(versin 2003)

- Deben comenzar con una letra o el caracter _. - No deben tener en medio el caracter espacio. Entonces, las variables o constantes comienzan con una letra o el caracter '_' y luego pueden ser letras, dgitos o '_'. Ejemplo de identificadores:
Contador Conta var1 _variable3_ Suma_total

Recuerde: en C se diferencia entre maysculas y minsculas, por lo tanto, la variable var1 es distinta a VAR1. Comentarios Un comentario es una cadena de caracteres que no es tomada en cuenta por el compilador, esta va dentro de "/*" y "*/", Ejemplo:
/* esto es un comentario */

se utilizarn por lo general para documentar los programas, o sea para hacerlo ms legible y ordenado, o simplemente para referencias personales del programador, por ejemplo: para indicar las ltimas modificaciones hechas al programa, as el programador sabe que fue lo ltimo que hizo en el programa.
/* Esta es la ultima version, lo ultimo que hice fue: Crear la funcion de ingreso de datos. La funcion de impresion de resultados funciona en forma correcta. Ya son las 3 de la maana y aun no termino mi tarea. */

Puede parecer no necesario, pero generalmente los programadores tienen varias versiones de sus programas, las cuales van modificando, hasta que logran terminar una en forma completa y sin errores. Ocurre tambin que los programas pueden ser dejados de lado y vueltos a retomar tiempo despus, tpicamente uno no se acuerda de las ltimas modificaciones hechas o de las cosas que funcionaban y de las que no. Tipos de datos fundamentales Los tipos de datos son los tipos de valores que puede tomar una variable, ya sea numrico, caracter u otro. Por ejemplo, en C, el nmero 1 no es igual a 1,00; esto debido a que el primero es un nmero entero y el segundo es un flotante (o nmero real). Los tipos de datos fundamentales en C son:

Profesor: Roberto Uribe P.

Pg. N 40

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Tipo char short int int long int unsigned char unsigned short int unsigned int unsigned long int float long float void

largo bytes(MS-DOS) 1 2 2 4 1 2 2 4 4 8 0

Nombre caracter entero corto entero entero largo caracter sin signo entero corto sin signo entero sin signo entero largo sin signo flotante doble o flotante largo vaco

abreviado short long unsigned short unsigned unsigned long double

Por lo tanto, el nombre de cada tipo de dato es una palabra reservada.

Resumen Palabras clave auto break case char continue default do double else enum extern float for goto if int long register return short sizeof static struct switch typedef union unsigned void while. Cuando recin se comieza a programar en C, se ocupan slo algunas de estas.

Operadores Son caracteres especiales que tienen un significado especfico o determinado, estos indican al compilador realizar operaciones matemticas o lgicas. Operadores Matemticos
- menos unuario - resta + suma * producto / divisin -- Decremento ++ Incremento % mdulo = asignacin

Precedencia (prioridad de los operadores matemticos): Operadores


- (unuario) * / % + =
Profesor: Roberto Uribe P.

Asociatividad
++ -derecha a izquierda izq. a derecha izq. a derecha derecha a izq.
Pg. N 41

Programacin de Computadores y el Lenguaje C

(versin 2003)

Operadores de Relacin Estos se utilizan dentro de proposiciones del tipo while, if, for; es decir, en estructuras de control .
< > <= >= == != : : : : : : menor que mayor que menor o igual que mayor o igual que igual a distinto de (no igual a)

Operadores Lgicos
! && || : negacin (unuario) : y lgico : o lgico not and or

Prioridad:
! < == && || <= != > >=

Tabla de verdad para los operadores lgicos


! (not) && (and) || (or) x y !x x&&y x||y __________________________________________________ 0 0 1 0 0 0 1 1 0 1 1 0 0 0 1 1 1 0 1 1

__________________________________________________

Existen estos mismos operadores (y algunos ms) para trabajar a nivel de bit, pero estos se vern despus en un apartado.

Comenzando a Programar Cada vez que se escribe una lnea, esta debe llevar ";" al final, con lo cual el compilador entiende que llega al final de una instruccin o proposicin. Esto no ocurre en las llamadas a Bibliotecas (#include) y en las definiciones (#define) o cuando es una sentencia compuesta (una lnea compuesta), es decir en el caso de un ciclo if, while, for, case, etc. Declaracin de variables Antes de usar una variable dentro de un programa, es necesario indicarle al compilador que va a ser usada, para ello se declara:
Profesor: Roberto Uribe P. Pg. N 42

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Declaracin:
<tipo> <lista_de_variables>; tipo ::= es el tipo de dato a utilizar char, int, float, etc. lista_de_variables::=<variable1[,variable2[,variable3........]]]>

la coma se usa para separar dos variables, lo anterior indica que puede ir ms de una variable. Ejemplo:
main() { int conta; char siono,primera_le; int suma,promedio,i; float exponencial; . . . }

/* se declara una variable entera */ /*ambas variables son de tipo caracter*/ /*se puede volver a repetir el tipo*/ /*variable de punto flotante */

Si una variable es de un tipo determinado, esto implica que puede tomar valores slo del tipo indicado. Por ejemplo, si una variable es del tipo int no puede asignrsele valores con decimales. Recuerde: es lo mismo
int i; int j; int k;

que
int i, j, k;

Asignacin: Como ya es sabido, una asignacin es almacenar en una variable el resultado de una operacin o proceso. En "C" una asignacin se representa como:
<variable> = <expresin>;

donde:
expresin ::= expresin operador_matemtico expresin

o
expresin ::= constante|variable

Ejemplo:
a=5; expo=max; /* a la variable a se le asigna el valor 5 (constante)*/ /* a la variable expo se le asigna el contenido de la variable max*/ expofin=ult+4; /* a expofin se le asigna el contenido de la variable ult sumada a la constante 4*/

Profesor: Roberto Uribe P.

Pg. N 43

Programacin de Computadores y el Lenguaje C

(versin 2003)

Inicializacin Esta es una asignacin que se utiliza para dar un valor de inicio a una variable. Ejemplo:
main() { int i=0,j=0,k; int suma; k=1; suma=(k+1)*200;/*la variables*/ . . }

/*inicializacion en la declaracion i, j*/ /*inicializacion despues de ser declarada*/ inicializacion puede ser hecha usando

Otros ejemplos de asignaciones:


sumatoria=sumatoria*nota; /*Expresion involucra multiplicacin de variables*/ /*expresion es una constante de tipo /*a resultado se le asigna el valor retornado por la funcion factorial*/

primela_le='A'; caracter*/ resultado=factorial(dato);

El ltimo ejemplo es ms complejo, en este caso el valor que retorna de la funcin factorial se asigna a la variable resultado. Funciones se ver en el prximo captulo.

Entrada / Salida Estndar A diferencia de otros lenguajes, no existen instrucciones de entrada y salida, para ello existe una librera. La biblioteca (o archivo de cabecera) llamada stdio.h contiene todas las funciones de entrada y salida estndar, entre ellas las funciones printf() y scanf(). La f significa que es entrada o salida con formato. printf() Esta es la funcin de salida por pantalla, su formato es el siguiente:
printf(cadena_de_control,lista_de_argumentos)

La cadena de control comienza y termina con comillas dobles, dentro de estas va una cadena de caracteres que puede incluir caracteres de control o formato. La lista de argumentos se refiere a indicar las variables que sern mostradas o impresas. Ejemplo:
/* Mi primer programa */ /* primer.c */

#include <stdio.h> main() {


Profesor: Roberto Uribe P. Pg. N 44

Universidad de Magallanes - Departamento de Ingeniera en Computacin

printf("Este es el primer programa que entiendo"); return 0; }

Nota: Este programa funciona correctamente, luego en Unix sera:


$ cc primer.c $ a.out Este es el primer programa que entiendo$

se compila (el nombre es primer.c) se ejecuta este es el resultado.

El smbolo $ es el prompt del sistema operativo Unix. Notar que en el ejemplo no se utiliz lista de argumentos, la cadena de control slo fue usada para imprimir una cadena de caracteres (palabras). Cuando se comienza a estudiar un nuevo lenguaje, lo primero que hay que aprender de l es como imprimir algo en pantalla, el segundo paso es leer desde teclado. Si se desea imprimir el valor de una variable se debe utilizar el formato adecuado. El formato comienza con el caracter "%", luego le sigue el caracter de conversin, entre estos no debe haber espacios en blanco. El caracter de conversin es aquel que indica cual es el tipo de dato que se imprimir, es decir, si es entero, caracter, etc.

Caracter de conversin c d e f g s p

tipo caracter entero nmero flotante en notacin cientfica punto flotante con el formato e o f , es ms corto cadena de caracteres (string) puntero

Si se le agrega la l o L a entero o flotante se indica que es long. Ejemplo:


#include <stdio.h> main() { int a=20,b; int c=0 ; b=50; c=a*b; printf("a * b = %d", c ); printf("\n a=%d y b=%d" , a, b ); return 0; } Cadena de Control

Cadena de Control Lista de argumentos

Lista de argumentos

Profesor: Roberto Uribe P.

Pg. N 45

Programacin de Computadores y el Lenguaje C

(versin 2003)

Para a, b y c se uso formato entero. En Unix, la salida de este programa sera:


a * b = 1000 a=20 y b=50

Los caracteres barra invertida (backslash) y n juntos, provocan un retorno de carro (return) en pantalla. Los espacios dentro del printf tambin aparecen en pantalla (note el primer espacio de la segunda lnea). Dentro de la funcin printf se usan caracteres de control (o secuencia de escape), para ello se usa el caracter \ (barra invertida) seguida de algn otro caracter, por ejemplo, algunos caracteres especiales se representan como: caracter nueva lnea \n tabulador \t comillas \ retorno de carro \r apstrofos \ barra invertida \\ retroceso \b alimentacin de forma \f valor ascii 10 9 34 13 39 92 8 12

En los strings se usa el caracter nulo \0 para indicar el fin de la cadena de caracteres. scanf() Esta es la funcin para entrada estndar, se utiliza de un modo parecido a la anterior. Ejemplo:
int numdato; printf("ingrese el nmero de datos:"); scanf("%d",&numdato); /*ingreso de numdato*/

Entonces utiliza formato, en este caso %d indica que se lee con formato entero. En el ejemplo el caracter "&" se usa para indicar la direccin de memoria, es decir, "lee a un valor con formato entero y lo guarda en la direccin de memoria numdato". Por ahora no se le dar mucho nfasis al caracter &, hasta el captulo de punteros, por ahora slo es necesario saber que para leer un int, char o float se utiliza dicho caracter. tabla scanf() caracter de conversin d o x u
Profesor: Roberto Uribe P.

tipo Entero decimal Entero Octal Entero Hexadecimal Entero Decimal sin signo
Pg. N 46

Universidad de Magallanes - Departamento de Ingeniera en Computacin

e f c s

n de punto flotante equivalente a e caracter cadena de caracteres (string)

Ejercicio N 2.1: Escribir un programa que lea 2 datos numricos y que realice las siguientes operaciones: suma, resta, multiplicacin y divisin. Para desarrollar este problema, tenemos que tomar en cuenta que se pide?, luego, que necesitamos para hacer esto?. Entonces, sabemos que se nos pide leer dos datos de teclado e imprimirlos en pantalla, es decir, necesitamos las funciones de entrada/salida scanf y printf. Como sabemos, para utilizar dichas funciones debemos llamar a la biblioteca que las contiene, en este caso stdio.h. Por lo tanto la primera lnea del programa debe ser:
# include <stdio.h>

luego de esto necesitamos escribir la funcin principal:


main() {

la llave indica el principio de la funcin main. Ahora, como tenemos que leer 2 datos y hacer cuatro operaciones, podemos crear 6 variables para guardar los datos y los resultados. Como dentro de las operaciones est la divisin, esta puede arrojar un resultado con decimales, para trabajar con decimales se ocupan los nmeros reales que en C estn representados por el tipo float, entonces:
float dato1,dato2,suma,resta,mult,div;

Note que el nombre de las variables es representativo de lo que son o de para que se usan, por ejemplo, la variable mult es para guardar la multiplicacin, la div es para almacenar la divisin, etc.... esa es una idea para hacer entendible un programa. Despus de esto, corresponde leer los datos. Para que el usuario del programa entienda que hace, este debe indicarle que hacer,
printf("Ingrese primer numero:"); scanf("%f",&dato1); printf("\n ingrese segundo numero:"); scanf("%f",&dato2);

Posteriormente se hacen las operaciones indicadas,


suma=dato1+dato2; */ resta=dato1-dato2; mult=dato1*dato2; div=dato1/dato2; /* en la variable suma se almacena la suma de a y b

y finalmente la salida a pantalla.


printf("\n LA SUMA ES: %f", suma); printf("\n LA RESTA ES: %f", resta); printf("\n LA MULTIPLICACION ES: %f", mult);
Profesor: Roberto Uribe P. Pg. N 47

Programacin de Computadores y el Lenguaje C

(versin 2003)

printf("\n LA DIVISION ES: %f", div); }

Lo importante por ahora es notar que todas la variables se declararon de tipo flotante (float), esto para realizar la divisin con los mismos nmeros ingresados. Sin embargo los datos podran haber sido int, en este caso se podra haber utilizado una conversin en el momento de hacer la operacin (cast) y convertir los datos enteros de entrada a flotante, por ejemplo.
int A=10,B=4; float f; f=(float)A/(float)B;

Es decir, A y B se convierten a flotante para hacer la divisin entre flotantes y asignarla a f. Esto es conocido como cast o conversin explcita. La construccin de un programa debe estar pensada en usuarios no expertos, y por lo tanto evitar cualquier ingreso errneo, o estar preparados para ello. En nuestro programa, si la variable dato2 es cero, la divisin se indetermina y ocurrira un error en tiempo de ejecucin, esto arrojara un error como:
Arithmetic Execption

o
Devide Cero - Error

Lo adecuado sera preguntar ..... Es dato2 distinto de Cero??...., para ello se utilizan las estructuras de control. En nuestro programa podramos hacer dicha pregunta antes de calcular la divisin, se hara con un if. Esto quedara de la siguiente forma:
if (dato2==0) /* Se pregunta "es dato2 igual a cero" */ printf("\n LA DIVISION ES INDETERMINADA"); else { div=dato1/dato2; /*el calculo de la division se hace aca y no antes*/ printf("\n LA DIVISION ES: %f", div); }

El programa final sera:


# include <stdio.h> main() { float dato1,dato2,suma,resta,mult,div; printf("Ingrese primer numero:"); scanf("%f",&dato1); printf("\n ingrese segundo numero:"); scanf("%f",&dato2); suma=dato1+dato2; /* en la variable suma se almacena la suma de a y b */ resta=dato1-dato2; mult=dato1*dato2; printf("\n LA SUMA ES: %f", suma); printf("\n LA RESTA ES: %f", resta); printf("\n LA MULTIPLICACION ES: %f", mult); if (dato2==0) /* Se pregunta "es dato2 igual a cero" */ printf("\n LA DIVISION ES INDETERMINADA"); else /* "de lo contrario" */
Profesor: Roberto Uribe P. Pg. N 48

Universidad de Magallanes - Departamento de Ingeniera en Computacin

{ div=dato1/dato2; /*el calculo de la division se hace aca y no antes*/ printf("\n LA DIVISION ES: %f", div); } return 0; }

La sentencia if se ver en la siguiente seccin.

El lenguaje C permite en la salida realizar la operacin, es decir, en los mismos printf podramos haber realizados las operaciones, con esto nos evitamos declarar las variables que almacenan los resultados de las operaciones. Por ejemplo, se pueden reemplazar los printf anteriores por:
: printf("\n LA printf("\n LA printf("\n LA : : printf("\n : SUMA ES: %f", dato1+dato2); RESTA ES: %f", dato1-dato2); MULTIPLICACION ES: %f", dato1*dato2); LA DIVISION ES: %f", dato1/dato2);

Note que para los printf y scanf se utiliz el formato para flotantes %f.

Profesor: Roberto Uribe P.

Pg. N 49

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Resueltos y Propuestos Acorde con lo introductorio del captulo, los siguientes ejercicios permiten ejercitar la sintaxis y notacin del lenguaje C ms que programar. Resueltos: 1.Escriba un programa en C que permita realizar el clculo del rea de un tringulo, para ello se deben ingresar los valores para la base y la altura. 2.Haga un programa que obtenga la raz cuadrada de un nmero ingresado por teclado.

3.Cree un programa que calcule la derivada de un polinomio de mximo grado 4, asuma que los exponentes son positivos. Recuerde que para obtener la derivada de : Cxn es Cnxn-1

Ejemplo : Para obtener la derivada de 2 x4 + x3 + 2 x el programa debera hacer:


Programa que calcula la derivada de un polinomio ingrese ingrese ingrese ingrese ingrese constante constante constante constante constante de de de de de x4 x3 x2 x1 x0 : : : : : 2 1 0 2 0

La derivada es : 8x3 + 3x2 + 0x + 2

4.Suponga un vehculo a una velocidad constante de 1.6 km./min. Haga un programa que exprese la velocidad en km./hora y en m/seg.

Propuestos: 5.Escriba un programa al cual se le ingrese una temperatura en grados Celcius y haga la conversin a grados Farenheit y Kelvin. F = (1.8 * C) + 32 K = C + 273.2

Profesor: Roberto Uribe P.

Pg. N 50

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Soluciones: 1.Como resulta obvio para este ejercicio, debemos utilizar la librera de entrada y salida estndar, adems, declarar dos variables que almacenen la base y la altura del tringulo. Recordando que la frmula para el clculo del rea es: (base * altura) / 2; el programa sera:
#include <stdio.h> main() { float base, altura; printf("\nPrograma que calcula el area de un triangulo\n"); printf("Ingrese base del triangulo : "); scanf("%f",&base); printf("Ingrese altura del triangulo : "); scanf("%f",&altura); printf("El area del triangulo es : %f",(base*altura)/2); return 0; }

Note que las variables fueron declaradas como flotantes (reales), esto para permitir el uso de valores con decimales.

2.En este problema nos encontramos con algo nuevo, el clculo de la raz cuadrada. La idea es utilizar todas la herramientas que nos provee el lenguaje, entonces, para este caso no se pretende realizar el clculo manual de la raz, sino utilizar la funcin raz cuadrada que viene en la librera matemtica de C. La funcin llamada sqrt (de square root), permite calcular la raz cuadrada de un nmero, para ello recibe como parmetro un dato de tipo flotante o double. Adems, hay que incluir la librera matemtica math.h. Entonces:
#include <stdio.h> #include <math.h> main() { double dato; printf("\nPrograma que calcula la Raiz Cuadrada de un numero\n"); printf("Ingrese un numero : "); scanf("%lf",&dato); printf("La raiz cuadrada de %lf es %lf ",dato,sqrt(dato)); return 0; }

La instruccin sqrt(dato), retorna la raz cuadrada de dato, es decir, un valor numrico (float) que reemplaza la llamada a la funcin en la posicin donde esta est. Y que ocurre si el dato ingresado es negativo?. En este caso la funcin sqrt enva un error a pantalla y retorna un 0. Por ejemplo, si el valor ingresado fuera -4, el programa se comportara de la siguiente manera:
Programa que calcula la Raiz Cuadrada de un numero
Profesor: Roberto Uribe P. Pg. N 51

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ingrese un numero : -4 sqrt: DOMAIN error La raiz cuadrada de -4.000000 es 0.000000

sin embargo, habra que determinar antes si es que el dato es negativo, pero esto se puede resolver con las herramientas entregadas en el proximo captulo (estructura if). Nota: En el caso de utilizar el compilador cc de unix, debe utilizarse un parmetro adicional para utilizar la librera matemtica, si el programa fuente es raiz.c, el comando para compilar sera:
cc raiz.c -lm

en el caso de los actuales compiladores para computadores personales, como ser Turbo C de la Borland, no es necesario hacer esto.

3.Este problema podra parecernos difcil, sin embargo, est bastante acotado y por el contrario, es sumamente sencillo. Existen dos formas de hacerlo, una es utilizando un ciclo que nos permita leer las cinco constantes, otra es simplemente no utilizando ciclos, en ese caso debemos declarar todas las variables (una por cada constante que se lea).
#include <stdio.h> main() { int c4,c3,c2,c1,c0; printf("\nPrograma que calcula la derivada de un polinomio de grado4.\n"); printf("ingrese constante de x4 :"); scanf("%d",&c4); printf("ingrese constante de x3 :"); scanf("%d",&c3); printf("ingrese constante de x2 :"); scanf("%d",&c2); printf("ingrese constante de x1 :"); scanf("%d",&c1); printf("ingrese constante de x0 :"); scanf("%d",&c0); printf("\nLa derivada es :"); printf("%dx3 + %dx2 + %dx + %d",c4*4,c3*3,c2*2,c1); return 0; }

4.Para este problema, sabiendo que: 1 Kilmetro es igual a 1000 metros, 1 hora son 60 minutos y un minuto son 60 segundos, la operacin es: 1.6 Km./min. = 1.6 * 60 Km./Hora 1.6 Km./min. = 1.6 *1000 m/min. = (1.6 * 1000) / 60 m/seg. Podramos hacer el programa para que funciones en forma general, es decir, que se ingrese cualquier valor en Km./min. y convertirlo a lo solicitado:

Profesor: Roberto Uribe P.

Pg. N 52

Universidad de Magallanes - Departamento de Ingeniera en Computacin

#include <stdio.h> main() { float dato; printf("\nConversion de Km./min. a Km./Hora y a m/seg. \n"); printf("Ingrese un valor (en Km./min.) : "); scanf("%f",&dato); printf("Convertido a Km./Hora es : %f \n", dato*60); printf("Convertido a m/seg. es : %f \n",(dato*1000)/60); return 0; }

Profesor: Roberto Uribe P.

Pg. N 53

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N 3: Estructuras de Control Las estructuras de control permiten cambiar la secuencia de las instrucciones, es decir tomar una alternativa o ruta diferente dentro de un programa. En un programa, el control fluye secuencialmente, es decir, toma una instruccin, la ejecuta y luego continua con la siguiente; esto siempre y cuando no exista un cambio explcito del control. En el ltimo ejemplo del captulo anterior, se vio como cambia el flujo de control por el uso de una proposicin if. En este captulo se mostrar tambin el modo de empleo de los operadores de relacin y lgicos y su uso dentro de las proposiciones de control.

Estructura if Esta estructura es de la siguiente forma:


if (expresin) sentencia_1 sentencia_siguiente

Si la expresin es verdadera entonces se ejecuta la sentencia_1, luego se ejecuta la sentencia_siguiente. Si la expresin resulta ser falsa se ejecuta inmediatamente la sentencia_siguiente. Recuerde: Una sentencia puede contener una sola lnea, si tiene ms de una se utiliza { y }, las llaves indican que lo que est dentro de estas es parte de la sentencia.

Proposicin if - else
No expresin Si

if (expresin) sentencia_1 else sentencia_2 sentencia_siguiente

Es equivalente a

sentencia_2

sentencia_1

sentencia_siguiente

Si la expresin es verdadera se ejecuta la sentencia_1, de lo contrario se ejecuta la sentencia_2, luego se ejecuta la sentencia_siguiente (independiente cual de las dos sentencias se ejecute, siempre se ejecuta la sentencia_siguiente). Recuerde: una expresin dentro de una estructura de control puede contener operadores de relacin, lgicos o matemticos.
expresin::= expresin operador_de_relacin expresin expresin::= expresin operador_lgico expresin expresin::= expresin operador_matemtico expresin expresin::= variable|constante

La idea de lo anterior es indicar que dentro de la expresin pueden haber preguntas compuestas, observe los siguientes ejemplos.
Profesor: Roberto Uribe P. Pg. N 54

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ej.:
if (dato>=50) printf("\n APROBADO CON NOTA: %d", dato); else printf("\n REPROBADO"); printf("\n programa finalizado");

Ej.:
result=dato % 2; /*se asigna el valor obtenido a result*/ if (result==0) /*luego se compara*/ printf("\n resultado par");

Otra forma sera:


if ((dato%2)!= 0) /*se hace dentro del if */ printf("\n dato impar");

Aqu la expresin fue:


(variable operador_matematico constante) operador_relacion constante

Ej.:
if (promedio>=30 && promedio<50) /*condicion con dos preguntas*/ printf("\n debe dar examen"); else if (promedio>=50) printf("\n Eximido"); else printf("\n Reprobado sin derecho a Examen"); printf("\n Fin programa");

Para este ejemplo, si el promedio es menor que 50 y el promedio es mayor o igual a 30, entonces, se imprimen el mensaje en pantalla debe dar examen. De lo contrario (quedan dos alternativas que sea menor que 30 o mayor o igual a 50), vuelve a preguntar en otro if si promedio es mayor o igual a 50, de lo contrario, y la nica alternativa que resta es que sea menor que 30. En este caso un if estaba dentro del else de otro if. Ej.:
scanf("%d",&x); if (x>=20 && x<=50 && x!=30) /*se uso el oper. logico y */ { printf("\n x=%d", x); printf("\n x esta entre 20 y 50, pero no es 30\n"); }

Observemos el comportamiento del if de este ejemplo, suponiendo que el dato ingresado es 25.
x>=20 Verdadero && && x<=50 Verdadero && && x!=30 Verdadero

Es decir, el resultado sera verdadero y por lo tanto el control se mete dentro del if. En C, un if entrega un valor distinto de 0 para verdadero e igual a cero para falso. Por ejemplo, el siguiente if esta correcto, y siempre va a ser verdadero:
Profesor: Roberto Uribe P. Pg. N 55

Programacin de Computadores y el Lenguaje C

(versin 2003)

opcion=1; if (opcion) printf("\nEste if es verdadero");

Como la variable opcion es 1, entonces el if va a ser verdadero, es como preguntar:


if (opcion!=0)

Igualmente correcto es preguntar:


if (dato%2) printf("\nEl dato es impar\n");

Es decir, si el resultado de dato%2 es distinto de 0, entonces el if es verdadero, lo que indicara que la variable dato es impar. Note que % es un operador matemtico.

Estructura while (Mientras) La estructura while o ciclo while nos permite repetir un proceso una cantidad determinada de veces (mientras la expresin sea verdadera). Se escribe de la siguiente manera:
while (expresin) sentencia_1 sentencia_siguiente

La sentencia_1 se repite tantas veces como la condicin (expresin) sea verdadera. Ejercicios: Los siguientes problemas son clsicos en programacin, para resolverlos recuerde el modo de desarrollo de los ejercicios resueltos en el captulo anterior. Ejercicio N 3.1: Escriba un programa en C para el clculo de xy, con x e y datos conocidos. Resolucin: La idea entonces es multiplicar x y veces, como no sabemos el valor de y no podemos hacer la operacin en una sola instruccin. La solucin a esto es usar un ciclo repetitivo (hasta ahora el nico conocido es el while), de tal manera que se ejecute y veces.

Profesor: Roberto Uribe P.

Pg. N 56

Universidad de Magallanes - Departamento de Ingeniera en Computacin

# include <stdio.h> main() { int cont=1,producto=1,x,y; printf("Este programa calcula x elevado a y (con y entero positivo)"); printf("\n\nIngrese x (entero): "); scanf("%d",&x); printf("\n\nIngrese y mayor o igual a 0 : "); scanf("%d",&y); if (y<0) printf("y es menor que 0 (aun no implementado)\n"); else if (y==0) printf("\n El resultado es: %d",producto); /* osea 1*/ else { while (cont<=y) { producto=producto*x; /* se multiplica el valor anterior de producto por x */ cont=cont+1; } printf ("/n El resultado es: %d",producto); } return 0; }

En este programa se utilizan todos los conocimientos adquiridos hasta ahora. Para simplificar el problema, por ahora el clculo se hace para exponentes positivos, sin embargo, modificarlo para exponentes negativos no requiere mucho esfuerzo, al igual que para x real. Para entender la solucin hay que tener en cuenta varias consideraciones. La primera es el uso de una variable auxiliar producto, la que mantendr los valores acumulados de las multiplicaciones sucesivas. Este se inicializa en 1. Como norma general para aplicaciones matemticas las variables que mantienen valores acumulados se inicializan, en el caso se multiplicatorias con el elemento neutro multiplicativo, es decir, 1; para el caso de sumatorias, el elemento neutro de la suma, osea, 0. El uso de la variable auxiliar permite que el valor de la variable x no se modifique, si esta se llegase a modificar, entonces el resultado del programa sera errado. El contador cont, es para llevar la cuenta y terminar el ciclo cuando el nmero de veces que se hizo la multiplicacin sea y. Como ltima acotacin, note el indentado aplicado al programa, recuerde que esto hace que el cdigo fuente se vea ordenado y ms fcil de entender (sobre todo los ciclos). Ejercicio N 3.2: Realizar un programa que calcule el factorial de un nmero ingresado por teclado. Recuerde que:
0! = 1 1! = 1 n! = n*(n-1)! = n*(n-1)*(n-2)* ....... *(n-n)!

Profesor: Roberto Uribe P.

Pg. N 57

Programacin de Computadores y el Lenguaje C

(versin 2003)

Resolucin: Como primera cosa a recordar es incluir la biblioteca de entrada y salida estndar (ya que debemos ingresar y mostrar datos en pantalla), luego incluir la funcin main(). Otra cosa que debemos comenzar a mejorar es la interfaz con el usuario, es decir, que los mensajes arrojados a pantalla sean adecuados y claros, adems, en este caso prepararnos para un ingreso errneo, como ser, que el dato ingresado sea menor que 0. Una solucin podra ser:
# include <stdio.h> main() { int cont=1,fact=1,num; printf("Este programa calcula el factorial de un numero,"); printf("\n\nIngrese un numero entero mayor que cero :"); scanf("%d",&num); if (num<0) printf("ERROR, no se puede calcular el factorial de %d\n",num); else if (num==0) printf("\n El Factorial de %d es: %d",num,fact); else { while (cont<=num) { fact=fact*cont; cont=cont+1; } printf("\n El factorial de %d es: %d",num,fact); } return 0; }

Este programa podra fallar si el dato ingresado es muy grande, esto debido a que el resultado puede ser superior al mximo nmero representable por un entero (en PC, 2 bytes). Para ampliar el mximo valor se debe declarar la variable fact como long int o long. Si se comparan los ejercicios anteriores (2 y 3) debemos notar que las soluciones son similares, esto debido a que ambos clculos se realizan de la misma forma. En el ejercicio 2 la multiplicacin se va haciendo con el valor original (x) y en el 3 con el contador(cont). Muchos ejercicios matemticos se resuelven de manera similar, sobre todo aquellos que involucran series y sucesiones. Revisemos el siguiente ejercicio. Ejercicio N 3.3: Escribir un programa que calcule ex. Recuerde que:
ex = 1 + x1 + x2 + x3 + ...... + xn 1! 2! 3! n! x : valor conocido. Asuma n=10. /* Programa que calcula e elevado a x */ # include <stdio.h> main()
Profesor: Roberto Uribe P. Pg. N 58

Universidad de Magallanes - Departamento de Ingeniera en Computacin

{ float cont=1,fact=1,pot=1,exp=1,div; /* exp fue inicializado en 1 para obtener el primer valor de la sumatoria*/ float n=10,x; printf("Calculo de e elevado a x"); printf("Ingrese un numero:"); scanf("%f",&x); if (x<0) printf("Aun no implementado"); else { while(cont<=n) { fact=fact*cont; pot=pot*x; div=pot/fact; exp=exp+div; cont=cont+1; } printf("\n El exponencial es: %f \n",exp); } return 0; }

Este ejercicio se resolvi segn el diagrama de flujo del captulo N 1. Recuerde que para verificar el comportamiento de un programa se puede ejecutar en papel, esto siempre y cuando el programa no sea extenso. Algo ms del if Observe los siguientes ejemplos, ambos estn correctos, 1)
if (x==0) if (y==0) printf("\n ERROR"); else printf("\n NO HAY ERROR"); if (x==0) if (y==0) printf("\n ERROR"); else printf("\n NO HAY ERROR");

2)

Ambos funcionan y compilan correctamente, sin embargo, lo que hay que determinar es a que if pertenece el else . Este es un problema de tipo semntico que se resuelve con la siguiente regla: "un else se asocia con el if ms cercano". Por lo tanto, el indentado del caso 1 es el ms adecuado (el indentado es slo una norma, no es obligatorio).

Existe una combinacin para la estructura if, y es la siguiente:


if (expresin_1) sentencia_1 else if (expresin_2) sentencia_2
Profesor: Roberto Uribe P. Pg. N 59

Programacin de Computadores y el Lenguaje C

(versin 2003)

else if (expresin_3) sentencia_3 . . . . else if (expresin_n) sentencia_n else sentencia_por_defecto sentencia_siguiente

En este caso slo se ejecuta la proposicin que sea verdadera, ninguna otra. En caso que todas sean falsas, entonces se ejecuta la sentencia por defecto del else. Algo ms del while Siendo C muy permisivo en algunas situaciones (por lo que muchas veces es o fue criticado por sus detractores), tome en cuenta lo siguiente para la estructura while: La funcin getchar() lee un caracter desde stdin (teclado). Ej.:
char c; c=getchar(); /* getchar()-->lee un caracter y luego es asignado a c */

Entonces un ciclo while puede ser de la siguiente manera:


while ((c=getchar())==' ' ) ; /* sentencia nula */

Esto es lo mismo que:


while ((c=getchar( ))==' ');

En este caso primero se lee un caracter por teclado, luego este caracter se asigna a la variable c y finalmente c se compara con el espacio, si es igual (es verdadero) entonces se repite el ciclo, es decir, el while no termina hasta que encuentre un caracter distinto de espacio en blanco. Note que lo interesante es que la asignacin se realiz en el while. Otra manera de escribirlo es:
c=' '; while (c==' ') { c=getchar(); }

Para el siguiente caso vea que es lo que sucede:


while (c=getchar()==' ');

Profesor: Roberto Uribe P.

Pg. N 60

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Nota: Como no existen los parntesis, primero se hace la comparacin y luego la asignacin, es decir a c se le asigna 0 distinto de 0, segn el resultado de la comparacin. Esto ocurre debido a la prioridad de los operadores. La opcin inversa de getchar() es:
putchar(c); /*envia a pantalla la variable que es de tipo caracter */

Para el caso de getchar y putchar, si c es declarado como int, tambin es vlido, esto porque se hace la conversin del dato char a su representacin entera. Por ejemplo, las siguientes sentencias estn correctas:
putchar(m);

Esta imprime el caracter m,


putchar(56);

imprimira el caracter nmero 56 de la tabla o conjunto de caracteres en uso.

Estructura for Cuando se conoce a priori la cantidad de veces que se tiene que repetir un proceso, entonces, el ciclo while puede ser reemplazado por un ciclo for. Este se denota por:
for (expresin_1; expresin_2; expresin_3) sentencia sentencia_siguiente

La primera expresin es la inicializacin de algn contador, la segunda es la condicin, es decir, mientras sea verdadera se ejecuta la sentencia que esta dentro del for, de lo contrario se ejecuta la sentencia siguiente. La tercera corresponde al incremento del contador. Por ejemplo:
for (i=1;i<=10;i=i+1) printf("hola "); printf("\nfueron muchos holas");

En este caso se imprime 10 veces hola, y al final fueron muchos holas. La estructura for se basa en la estructura while, y lo anterior es equivalente a:
expresin_1; while (expresin_2) { sentencia; expresin_3; } sentencia_siguiente;

Profesor: Roberto Uribe P.

Pg. N 61

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejercicio N 3.4: Escriba un programa que calcule la siguiente sumatoria, utilizando el ciclo for:
x = i
i =1 n

n : valor conocido

#include <stdio.h> main() { int sumatoria=0,i,n; printf ("\n Este programa calcula la sumatoria i de 1 a n"); printf ("\n\n Ingrese n: "); scanf ("%d",&n); for (i=1;i<=n;i=i+1) sumatoria=sumatoria+i; printf ("\n la sumatoria es: %d \n", sumatoria); return 0; }

El for puede haber sido hecho como:


i=1; while (i<=n) { sumatoria=sumatoria+i; i=i+1; }

/* es lo mismo que sumatoria+=i; */ /* es lo mismo que i++; */

Para los incrementos y decrementos se pueden utilizar los operadores ++ y --. Es igual escribir: i=i+1 que i++ Ejemplo del clculo del factorial de n utilizando ciclo for.
for (cont=1;cont<=n;cont++) fact=fact*cont; /* fact*=cont; */ printf("\n El Factorial es: %d",fact);

Ciclo do-while Con los ciclos vistos hasta ahora (for y while), la condicin se analiza al comienzo del bucle (otra forma de nombrar a un ciclo), para el caso del do-while, la condicin se analiza al final del bucle. Esto implica, que el ciclo se ejecutar por lo menos una vez. La forma general de un ciclo do-while es
do sentencia while (condicion);

El ciclo do-while itera mientras la condicin sea verdadera. En el siguiente ejemplo se leen caracteres de teclado mientras sean distinto de a, b y c.

Profesor: Roberto Uribe P.

Pg. N 62

Universidad de Magallanes - Departamento de Ingeniera en Computacin

do { car=getchar(); printf("%d",car); /*imprimiria los valores ascii de los caracteres leidos */ } while (car!='a' && car!='b' && car!='c');

Proposicin break Esta proposicin rompe el flujo normal de control. Break termina un ciclo o una proposicin switch.
while (1) { scanf("%d",&num); if ((num%2)==0) { printf("\n este era par"); break; } } /* break envia el control hasta esta linea */

En este ejemplo el while resulta ser siempre verdadero. Se va leyendo un nmero y se termina el ciclo cuando el dato ledo es par, esto por causa de la sentencia break.

Proposicin Continue La palabra reservada continue se usa de manera similar al break en un ciclo, es decir, ignora todas las sentencias que siguen a la sentencia continue, sin embargo, no termina el ciclo, no evtale incremento del contador o que la condicin sea evaluada. Si la condicin sigue siendo verdadera, entonces el ciclo sigue iterando. Proposicin switch La proposicin switch tiene la funcin de un if anidado, esta es una sentencia de seleccin mltiple (es como la proposicin case en Pascal). En el switch se va comparando el valor de la expresin con cada una de las constantes enteras que aparecen en las sentencias case. La forma de esta es:
switch(expresin_entera) { case constante_entera1: sentencia; [break;] case constante_entera2: sentencia; [break;] case constante_entera3: sentencia; [break;] : : : [default: sentencia] /* optativo */ }
Profesor: Roberto Uribe P. Pg. N 63

Programacin de Computadores y el Lenguaje C

(versin 2003)

Cuando la expresin resulta ser igual a una de las constantes, entonces se ejecuta la sentencia correspondiente hasta el break o hasta el final del switch. En caso contrario se ejecuta la sentencia default, que es opcional. Si existen ms de una lnea en la sentencia case no es necesario utilizar llaves. Por ltimo la proposicin break tambin es opcional. Revisemos los siguientes ejemplos:
#include <stdio.h> main() /* cuenta cuantas a, e, i, o y u se han ingresado*/ { char letra; int conta=0,conte=0,conti=0,conto=0,contu=0,otros=0; do { letra=getchar(); switch(letra) { case 'a' : conta++; break; case 'e' : conte++; break; case 'i' : conti++; break; case 'o' : conto++; break; case 'u' : contu++; break; default : otros++; /* es optativa */ } } while(letra!=\t); return 0; }

La expresin debe ser entera, sin embargo, si se utilizan constantes o variables de tipo caracter, estas se convierten a sus valores enteros. Al trmino de cada case se usa el break para terminar el switch, que lleva el control hasta la lnea siguiente despus del switch. El programa termina cuando el caracter ledo es un tabulador. Se debe tomar en cuenta que a diferencia del if, en el switch slo se puede comprobar igualdad. Adems, no deben haber dos sentencias case con constantes iguales dentro de un mismo switch.

Ejemplo: Si quisiramos contar las vocales (en general) ledas, el programa podra ser:
#include <stdio.h> main() /* cuenta cuantas vocales se han ingresado*/ { char letra; int contvocal=0,otros=0; while (1) { letra=getchar(); switch(letra) { case 'a' : case 'e' : case 'i' :
Profesor: Roberto Uribe P. Pg. N 64

Universidad de Magallanes - Departamento de Ingeniera en Computacin

case 'o' : case 'u' : default : } } return 0; }

contvocal++; printf("%d",contvocal); break; otros++;

En este ejemplo, si se lee una letra a, como no existe break, no termina el switch, entonces el control pasa al case siguiente, y as hasta que llega a la sentencia donde se incrementa la variable contvocal, y se ejecuta el break.En este ejemplo no fue necesario colocar break en cada case. Es importante notar que el while se ejecuta mientras no sea el final de la entrada EOF (End of File). La entrada tambin podra haber sido un archivo. Por ejemplo, si crearamos un archivo llamado prueba.txt, podramos haber ejecutado el programa de la siguiente manera : a.out < prueba.txt lo que hace que el while procese cada carcter contenido en prueba.txt.

Profesor: Roberto Uribe P.

Pg. N 65

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Resueltos y Propuestos Con los conocimientos adquiridos en este captulo Ud. debe ser capaz de resolver en C todos los ejercicios resueltos y propuestos del captulo anterior. Resueltos: 1.- Escriba un programa en lenguaje C que verifique si un nmero ingresado por teclado es o no primo. Recuerde que un nmero primo es aquel que slo es divisible por 1 y por el mismo. 2.- Escriba un programa en C que realice lo siguiente : - lea un nmero entero - lea un operador matemtico - lea otro nmero entero. luego debe realizar la operacin indicada y arrojar el resultado por pantalla. Los operadores matemticos pueden ser de suma, resta, multiplicacin y divisin. Ej.:
ingrese un nmero entero ingrese operador ingrese el segundo nmero El resultado de 5 * 10 es : 50 : 5 : * :10

3.Opinin personal: Con los conocimientos (herramientas) que Ud. tiene hasta ahora, hacer el siguiente programa lo considera: fcil, complicado, realmente difcil. Porqu? - leer cuatro nmeros enteros - imprimirlos en orden ascendente (de menor a mayor). 4.- Realizar un programa que lea un nmero hexadecimal y lo convierta a su representacin en base 10. - Restricciones : No usar ninguna funcin conocida para la conversin, slo la supuesta ms adelante. El dgito que se leer tiene que ser de tipo char. - Recuerde que : 13C(16) ----> 316(10) - ya que : 1*162+3*161+12*160 256 + 48 + 12 316
Profesor: Roberto Uribe P. Pg. N 66

Universidad de Magallanes - Departamento de Ingeniera en Computacin

- Para facilitar la solucin: lea la cantidad de dgitos que posee el nmero. Luego lea los dgitos uno a uno. Ejemplo :
ingrese cantidad de dgitos: 3 ingrese dgito 1 : 1 ingrese dgito 2 : 3 ingrese dgito 3 : C El nmero en base 10 es : 316

- Supuesto : Existe una funcin llamada convcharaint(dato) que transforma un dato tipo char a int, ejemplo:
datochar='1'; datoint=0; datoint=convcharaint(datochar); /* el datoint resulta igual a 1 */

5.En C la entrada y salida estndar puede ser dirigida a archivo, esto simplemente usando los caracteres < o >. Por ejemplo, supongamos que se tiene un programa que lee 3 caracteres y los va imprimiendo en pantalla. El ingreso de los caracteres puede haber sido hecha con getchar() o scanf(). Si en vez de hacer la entrada por teclado, se crea un archivo de texto que contiene los tres caracteres (suponga abc) y luego el programa se ejecuta de la siguiente manera:
$a.out<arch a b c $

Cree un programa que lea caracteres desde stdin e imprima el nmero de vocales ledas y el nmero de lneas que tena el archivo. Un archivo termina cuando el caracter ledo es la constante EOF. Propuestos: 6.Durante la ltima Gran Guerra, un grupo de ingenieros del rea informtica fue contratado por una de las partes en conflicto para investigar y decodificar los mensajes en clave que se enviaba el enemigo. Dichos mensajes, eran una serie de caracteres entre letras y nmeros. Durante un periodo considerable de tiempo, estos investigaron la posible solucin. Una vez que llegaron a ella, se dieron cuenta que los dgitos que contena el mensaje correspondan a letras del mensaje real, esto ltimo segn la siguiente tabla: M 0 U 1 R 2 C 3 I 4 E 5 L A 6 7 G 8 O 9

Profesor: Roberto Uribe P.

Pg. N 67

Programacin de Computadores y el Lenguaje C

(versin 2003)

Es decir, para la siguiente frase en clave: H9Y S5 39N934529N 69S P240529S 5X404D9S D56 2709 Su traduccin es: Hoy se conocieron los primeros eximidos del ramo Entonces, se decidi crear un programa para hacer mas rpido el proceso de decodificacin. Asuma que el ingreso es caracter a caracter, es decir, considerando lo explicado en el ejercicio anterior es posible leer los datos desde un archivo y direccionar la entrada con el smbolo menor. 7.- Para el siguiente programa:
# include <stdio.h> main() { int i=1; int n; float S=0.0,x; printf("\nIngrese n :"); scanf("%d",&n); printf("\nIngrese x :"); scanf("%f",&x); while(i<=n) { S=S+x/(float)i; i=i+1; } printf("\n\nS es : %f",S); return 0; }

a.- Indique lnea a lnea, que proceso se va realizando, esto en forma clara. b.- Para n=10 y x=100, obtenga el valor final para S y i en cada ciclo (el valor puede quedar expresado). c.- Obtenga la frmula matemtica. 8.Haga un programa que obtenga los 5 primeros nmeros perfectos. Un nmero perfecto es aquel nmero positivo que es igual a la suma de los enteros positivos (excluyendo el mismo) que son divisores del nmero. Ejemplo : El primer nmero perfecto es el 6 ya que sus divisores son el 1, 2 y 3 y la suma de estos 1 + 2 + 3 = 6.

Soluciones: 1.Lo primero es recordar que un nmero primo es aquel que slo es divisible por 1 y por el mismo. Entonces, una de las formas de resolver este problema, luego de ingresado el dato, es
Profesor: Roberto Uribe P. Pg. N 68

Universidad de Magallanes - Departamento de Ingeniera en Computacin

recorrer con un contador desde 2 hasta el dato-1 y tener un otro contador que se vaya incrementando cada vez que la divisin de dato por el primer contador sea entera..
#include <stdio.h> main() { int num,i=2,cont=0; printf("\nPrograma que verifica si un numero es o no primo.\n"); printf("Ingrese un numero : "); scanf("%d",&num); if (num<=0) printf("Error, el numero debe ser mayor que cero.\n"); else if (num==1) printf("El numero %d es primo.",num); else if (num==2) printf("El numero %d es primo.",num); else { for(i=2;i<num;i++) if ((num%i)==0) cont++; if (cont>0) printf("El numero %d no es primo.",num); else printf("El numero %d es primo.",num); } return 0; }

Observe que el for va de 2 a num-1, esto ya que de otro modo cont se incrementara al hacer el mdulo por 1 y num. 2.#include <stdio.h> main() { int num1,num2,oper; printf("\nPrograma que realiza las 4 operaciones basicas.\n"); printf("ingrese un nmero entero :"); scanf("%d",&num1); printf("ingrese operador :"); scanf("%c",&oper); printf("ingrese el segundo nmero :"); scanf("%d",&num2); printf("\nEl resultado de %d %c %d es :",num1,oper,num2); if (oper=='+') printf("%d",num1+num2); else if (oper=='-') printf("%d",num1-num2); else if (oper=='*') printf("%d",num1*num2); else /* solo falta la division*/ if (num2!=0) printf("%d",num1/num2); else printf("La division se indetermina); return 0; }
Profesor: Roberto Uribe P. Pg. N 69

Programacin de Computadores y el Lenguaje C

(versin 2003)

Una forma ms sencilla de construir este programa es usando la instruccin switch, la parte principal del programa quedara:
switch(oper) { case '+': printf("%d",num1+num2); break; case '-': printf("%d",num1-num2); break; case '*': printf("%d",num1*num2); break; case '/': if (num2!=0) printf("%d",num1/num2); else printf("La division se indetermina); break; default: printf("operacion no reconocida"); /* en caso de no ser ninguna de las anteriores*/ } /*fin switch*/

3.A simple vista podra parecer fcil ordenar 4 nmeros, sin embargo, no es tan sencillo. La dificultad radica principalmente en que la cantidad de comparaciones que se tienen que hacer son un mnimo de 4!, es decir, 24. Esto, ya que tendramos que crear 4 variables e ir comparndolas entre ellas. En si, el problema resulta mas engorroso que difcil. En captulos posteriores cuando se aprenda el concepto de arreglos podremos aprender como resolver este tipo de problemas sin tanta complicacin. 4.Los programas para cambio de base de un nmero son clsicos en programacin, en este caso, como los nmeros hexadecimales usan caracteres es necesario declarar de tipo char los dgitos que se ingresarn. Tambin se indica que existe una funcin que permite convertir un char a int. Como an no manejamos funciones slo debemos recordar que un funcin va a retornar un valor, que se puede utilizar como un dato cualquiera (en este caso un dato int). Si el dato ingresado a la funcin es A, retorna 10, si es B, 11, etc. Otra cosa a tomar en cuenta, es que la cantidad de dgitos es variable, entonces, debemos utilizar un ciclo que nos permita leer todos los dgitos.
#include <stdio.h> main() { int i=0,numdig=0,valor=0,digint; char digchar; printf("\nPrograma que transforma un numero Hexadecimal a Decimal.\n"); printf("Ingrese cantidad de digitos : "); scanf("%d",&numdig); if (numdig<=0) printf("Error, el numero debe ser mayor que cero.\n"); else for(i=1;i<=numdig;i++) { printf("Ingrese digito %d :",i); scanf("%c",&digchar); /*se lee un char*/ digint=convcharaint(digchar); /*convierte el char a int*/ pot=1; /* Es necesario que pot se inicialice cada vez en 1*/ for(j=1;j<=numdig-i;j++) /*calculo de la potencia de 16*/ pot=pot*16; valor=valor+digint*pot; }
Profesor: Roberto Uribe P. Pg. N 70

Universidad de Magallanes - Departamento de Ingeniera en Computacin

printf("El numero en base 10 es : %d.",valor); return 0; }

Observe que en el clculo de la potencia, el for llega hasta numdig-1, esto ya que si son n dgitos, entonces el primero se multiplica por 16n-1 y el ltimo por 160. Algunos cambios que se pueden hacer son:
for(i=1;i<=numdig;i++) { printf("Ingrese digito %d :",i); scanf("%c",&digchar); /*se lee un char*/ for(j=1,pot=1;j<=numdig-i;j++) pot=pot*16; valor=valor+convcharaint(digchar)*pot; }

En este caso dentro del for se inicializaron ambas variables. Adems, la funcin se llamo en la misma operacin, de esta manera se evita usar una variable (digint). Lo ltimo que se tiene que considerar, es que este programa no compilara dado que la funcin convcharaint no existe, en el prximo captulo estaremos en condiciones de poder implementar dicha funcin. 5.Como se mencion en el encabezado de la pregunta, es posible que la entrada pueda ser a travs de teclado o bien un archivo, para ello slo hay que usar el smbolo menor al momento de ejecutar el programa. Para este ejercicio supongamos que creamos un archivo en un editor de texto cualquiera, en Unix podra ser el conocido vi, en DOS el edit o el mismo editor que trae el compilador de C con el que se esta trabajando (por ejemplo el Turbo C de la Borland trae su propio editor).
#include <stdio.h> main() { int car,cuentavoc=0,cuantalin=0,cuentatab=0; car=getchar(); while (car!=EOF) { switch(car) { case 'a': case 'e': case 'i': case 'o': case 'u': cuentavoc++; break; case '\t': cuentatab++; break; case '\n': cuentalin++; break; } /*fin switch*/ car=getchar(); } printf("\nNumero de Vocales : %d",cuentavoc); printf("\nNumero de Tabuladores : %d",cuentatab); printf("\nNumero de Lineas : %d",cuentalin); return 0; }

Profesor: Roberto Uribe P.

Pg. N 71

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N 4 : Funciones en C El lenguaje "C" esta creado a partir de funciones y su programacin se hace a travs de ellas, estas facilitan la estructuracin y el entendimiento de los programas, "dividir para reinar". Una funcin puede realizar un proceso simple o complejo, como ser el clculo de factorial, raz cuadrada, determinante de una matriz, lectura de datos, procesos con punteros, etc... Una funcin consta de un encabezado y un cuerpo. Todas las funciones devuelven un valor o un valor vaco (void), este valor especifica el tipo de dato de la funcin, el cual se tiene que especificar, si no es as se asume entero. Ej.:
mi_primera_func() { printf("\n\n esta sera una de las muchas"); printf("\n pero muchas, funciones que se"); printf("\n haran en este entretenido"); printf("\n ramo"); /* la ausencia de acentos es porque la funcion esta hecha para correr en Unix*/ }

Para la funcin anterior el tipo de dato no se especific por lo tanto es int, es decir el encabezado podra haber sido:
int mi_primera_func() { }

El cuerpo de la funcin va entre llaves. La funcin anterior no devuelve un valor slo realiza un proceso. Una funcin puede ser llamada desde la funcin principal main() o de cualquier otra. La llamada se realiza colocando el nombre en el lugar donde, se desea que se ejecute la funcin. La funcin tiene que ir declarada antes del main y se puede escribir despus de la funcin principal, esto ltimo no es obligatorio, pero es una buena norma para programar. Ejemplo:
# include <stdio.h> int mi_segunda_func(); Declaracin de la funcin main() { printf("\n esto fue escrito antes de la funcion..."); mi_segunda_func(); printf (" \n la funcin ya se ejecuto"); return 0; } int mi_segunda_func() Definicin de la funcin { printf("\n\n Estoy dentro de la funcion"); }

La salida de este programa sera:


Profesor: Roberto Uribe P. Pg. N 72

Universidad de Magallanes - Departamento de Ingeniera en Computacin

esto fue escrito antes de la funcin... Estoy dentro de la funcion la funcin ya se ejecuto

A diferencia de otros lenguajes no existen procedimientos propiamente tal (procedure en Pascal o subroutine en Fortran). Sin embargo las funciones en C pueden cumplir este papel. Adems existen funciones de tipo void (vaco) que no devuelven valores. Para el caso anterior la funcin podra haber sido void o sea:
void mi_segunda_func()

Instruccin return Esta es la expresin que permite devolver el valor de la funcin hacia donde es llamada, adems de terminar la ejecucin de dicha funcin. Ejemplo:
int suma() { int A, B; int sum; A=5; B=8; sum=A+B; return(sum); }

/* declaraciones de variables locales */

Esta funcin nos permite ver el funcionamiento del return. El valor que retorna la funcin debe ser del mismo tipo con que fue declarada la funcin. El resto del programa sera:
#include <stdio.h> int suma(); /* Global */ main() { int result; result=suma(); printf("\n suma es: %d",result) return 0; } /* aqui deberia ir escrita la funcion */

/*imprimiria 13*/

En la sentencia result=suma(); a la variable result se le asigna el valor retornado de la funcin suma(). El nombre de la funcin es reemplazada por el valor que ella retorna, entonces tambin es vlido hacer:
result=10+suma();

Lo que implicara que result tendra el valor 23. Consideraciones :


Profesor: Roberto Uribe P. Pg. N 73

Programacin de Computadores y el Lenguaje C

(versin 2003)

-Las dos primeras funciones (mi_primera_func y mi_segunda_func) no contenan la intruccin return, esto no ocasiona problemas debido a que no retornan valor. Sin embargo, se acostumbra a colocar return. Algunos compiladores podran enviar una advertencia al no encontrar return en una funcin. -La funcin principal main() tiene forma de funcin, sin embargo, tcnicamente no lo es, por lo tanto es ilegal hacer llamadas a ella. Los programas que invocan a main() funcionan a veces, esto dependiendo de la implementacin ya que algunas si tienen a main() como funcin normal.

Variables Globales y Locales Variables Globales: Estas se declaran fuera de las funciones, antes del main o en otros archivos y pueden utilizarse durante todo el programa y en cualquier parte de este, incluso en las funciones. Variables Locales: Estas se declaran dentro de bloques o funciones y permanecen activas solamente en ese mbito. Ejemplo de variables locales:
float raizcua() { int i, j, float raizfi; : : } /*funcion que retorna un valor flotante*/ /*variables locales*/

Para este ejemplo, las variables i, j y raizfi son locales a la funcin raizcua, es decir, dichas variables comienzan a existir cuando se llama a la funcin y desaparecen cuando esta termina. Estas variables no pueden ser accesadas directamente desde otras funciones, as como desde la funcin raizcua no se puede tener acceso a variables declaradas en otras funciones. Adems, es importante saber que dichas variables no conservan su valor, o sea, si la funcin es nuevamente llamada, entonces son de nuevo creada, y por lo tanto inicialmente contienen un valor basura. A estas variables se les llama automticas. Tome en cuenta el siguiente ejemplo:
#include <stdio.h> int func1(); float func2(); int var1=0; /*variable global*/ main() { int i=0; : : }
Profesor: Roberto Uribe P.

/*variable local a main*/

Pg. N 74

Universidad de Magallanes - Departamento de Ingeniera en Computacin

int func1() { int i=0; : } float func2() { int var1=0; : }

/*variable local a func1*/

/*variable local a func2*/

Quizs con lo anterior podramos tener alguna confusin, esto provocado porque tanto en la funcin main como en func1 existe una variable del mismo nombre, es ms, existe una variable global llamada var1 que tambin esta declarada en func2. Como se dijo anteriormente las variables locales no pueden ser accesadas directamente desde otras funciones, por lo tanto, las variables i del main e i de func1 son distintas, si se llama a func1 desde el main se crea la variable i de func1 y la otra variable (la del main) no existe dentro de esta funcin. Un caso similar es con var1, como es global puede ser llamada de cualquier parte, por ejemplo desde func1 o main. Sin embargo, dentro de func2 la variable activa es la local, por lo tanto var1 global se desactiva dentro de esta funcin. Sin embargo, var1 global no pierde su valor, slo se desactiva momentneamente (por el periodo que dura func2). Es posible tambin encontrar declaraciones de variables locales en bloques internos dentro de alguna funcin, por ejemplo :
: main() { int cont=0, suma=0; : { float mult=1, div=0; : : } : }

Para estos casos, el bloque interno se crea con { y se termina con }, las variables anteriores mult y div slo existen dentro del bloque.

Llamadas a Funciones Debemos recordar que una funcin puede ser llamada una o ms veces y desde cualquier otra funcin, as como tambin se pueden llamar a muchas funciones dentro de una misma funcin.

Una manera de ejemplificar esto, es a travs del siguiente esquema:


Profesor: Roberto Uribe P. Pg. N 75

Programacin de Computadores y el Lenguaje C

(versin 2003)

int multinum()

# include <stdio.h> double eelevx(); long factorial(); long potencia(); int multinum(); main() { : : : }

long factorial()

double eelevx()

long potencia()

Se asume que el programa posee cuatro funciones, una que calcula ex, otra el factorial de un nmero, otra un nmero cualquiera elevado a otro y otra (multinum) que realiza cualquier otra operacin. Entonces, vemos que desde el programa principal (main) se llama a multinum, a factorial y a eelevx, sin embargo desde esta ltima tambin se llama a factorial, adems de potencia.. La idea de las funciones es desarrollar programas aplicando el Modelo Top-Down, es decir, ir dividiendo el problema en partes ms pequeas y estas a su vez en otras ms chicas, esto hasta que se encuentren subproblemas posibles de resolver, luego ir uniendo las soluciones a estos subproblemas, hasta permitir resolver el problema completo (problema original). Es por ello que se habla de dividir para reinar o dividir para conquistar, es ms fcil resolver cualquier problema si este se divide en pequeas partes que puedan ser manejables. Se debe tener cierto cuidado con las llamadas a funciones, ya que podran ocurrir problemas tales como ciclos o loops infinitos, estos provocados porque no existe un adecuado trmino de la funcin. Observe el siguiente ejemplo:
func1()

main() func2()

func3()

Profesor: Roberto Uribe P.

Pg. N 76

Universidad de Magallanes - Departamento de Ingeniera en Computacin

El esquema anterior podra provocar un loop infinito si no se determina correctamente el final de alguna de las funciones. Esto tambin podra ocurrir en las llamadas recursivas.
func1()

main()

Las funciones recursivas son aquellas donde existe una llamada a si misma. Las llamadas recursivas a funciones son muy utilizadas en programacin y dan un aspecto mas entendible a esta. El siguiente ejemplo muestra una funcin que se llama a si misma,
int funrec() { funrec(); return 0; }

sin embargo para este ejemplo, como antes del return se llama a si misma, nunca alcanza la instruccin de trmino, por lo tanto queda en un ciclo infinito.

Paso de Parmetros a funciones Una variable global permanece activa durante todo el periodo de ejecucin de un programa, por lo tanto, el espacio de memoria que ocupa dicha variable permanece ocupada hasta que no termina el programa. Si se ocupan demasiadas variables de este tipo es posible que en algn momento se acabe la memoria RAM, sobre todo en computadores personales (a pesar que ahora estos traen la suficiente). El uso excesivo de variables globales atenta contra la modularidad del programa y lo hace ms difcil de entender, esto ltimo, ya que las funciones terminan amarradas a las variables del caso, lo que limita su reusabilidad. Una manera de evitar el exceso de variables globales es pasando parmetros a las funciones. Ejemplo: El siguiente programa incluye una funcin calcula el factorial de un nmero cualquiera:

Profesor: Roberto Uribe P.

Pg. N 77

Programacin de Computadores y el Lenguaje C

(versin 2003)

#include <stdio.h> long int factorial(int n); main() { int datoin; long result; printf("\n ingrese nmero: "); scanf("%ld",&datoin); result=factorial(datoin); printf("\n el factorial es: %ld", result); } long int factorial(int n ) { long fact=1 ; int cont=1; for (cont=1;cont<=n;cont++) fact=fact*(long)cont; return(fact); }

Parmetro ingresado a la funcin en la llamada

Parmetro de la funcin Declaracin del parmetro ingresado

En la definicin de la funcin se incluy un parmetro, entonces, este debe ser declarado, esto se puede hacer en la lnea siguiente antes de la llave que indica el comienzo de la funcin. Como a la funcin se le pasa un parmetro, entonces, al llamarla tambin se debe incluir un parmetro. Lo que ocurre en el ejemplo es: desde el main se llama a la funcin factorial, a la cual se le pasa el parmetro datoin. En trminos formales, se le pasa el valor (o contenido) de la variable datoin. La variable n de la funcin factorial asume el valor que fue ingresado a la funcin. Una vez que se realiza el proceso de clculo del factorial, este retorna el resultado almacenado en fact hacia donde es llamada la funcin. En el main el valor retornado por la funcin es asignado a la variable result. La parte esencial del programa, el calculo del factorial, es igual a los ejemplos anteriores, sin embargo, ahora esta incluido dentro de una funcin, lo que le otorga una mayor modularidad al programa. De esta manera para calcular el factorial de otro nmero no se tiene que modificar la funcin. En el ejemplo, no es necesario asignar a una variable el resultado arrojado por la funcin, de esta manera nos ahorraramos una variable,
printf("\n el factorial es: %ld",factorial(datoin));

Si se pasa ms de un parmetro a la funcin se deben separar por coma y dentro de esta deben estar todos declarados. Existen dos formas de pasar parmetros a funciones, por valor (ejemplo anterior) o por referencia, esta ltima se ver ms adelante en el captulo de punteros.

Paso de variables por valor Cuando se dice que una variable ha sido pasada por valor, quiere decir, que su contenido no se modifica dentro de la funcin. Para entender esto, estudiemos el siguiente ejemplo:
Profesor: Roberto Uribe P. Pg. N 78

Universidad de Magallanes - Departamento de Ingeniera en Computacin

#include <stdio.h> xxfun(int bli); main() { int i; i=5; printf("\nAntes de la funcion i es igual a: %d",i); xxfun(i); printf("\nDespues de la funcion i es igual a: %d",i); } xxfun(int bli) /* la variable bli asume el valor con */ { /*la cual es llamada la funcin */ bli=bli+10; printf("\nDentro de la funcion bli es: %d",bli); } /* funcin xxfun() no retorna valores */

La salida de este programa es:


Antes de la funcion i es igual a: 5 Dentro de la funcion bli es: 15 Despues de la funcion i es igual a: 5

La funcin xxfun() no logra modificar la variable de entrada i. El parmetro bli toma el valor de entrada (es decir 5), se incrementa en 10, pero es la variable bli la que se modifica y no i del main. Una vez que termina la funcin la variable bli deja de existir, si se llamara de nuevo, tomara el nuevo valor de entrada a la funcin, cualquiera sea este. Para complicar un poco ms el asunto, supongamos el siguiente ejemplo:
#include<stdio.h> int prueba(int dato); main() { int dato=5,i=6,resultado=0; printf("\n dato=%d, i=%d, resultado=%d",dato,i,resultado); resultado=prueba(dato); printf("\n dato=%d, i=%d, resultado=%d",dato,i,resultado); } int prueba(int dato) { int i=1; dato++; printf("\n dato=%d, i=%d",dato,i); return(dato); }

La salida al programa es:


dato=5, i=6, resultado=0 dato=6, i=1 dato=5, i=6, resultado=6

Porqu?. En la primera lnea no hay problema, son los valores iniciales de las variables declaradas en la funcin principal. En el segundo printf (el de la funcin), i es una variable local de la funcin prueba, que es distinta a el i de main. La variable dato de la
Profesor: Roberto Uribe P. Pg. N 79

Programacin de Computadores y el Lenguaje C

(versin 2003)

funcin prueba tambin es local (y por lo tanto distinta a dato de main), y en este caso no importa que tenga el mismo nombre del parmetro ingresado a la funcin, por lo tanto esta recibe el valor 5 y se incrementa en 1 (osea 6). Para el ltimo printf las variables dato e i no se modifican, la variable resultado cambia su contenido ya que se le asigna el valor retornado de la funcin (6). Por ltimo, dentro de la funcin prueba no se puede imprimir la variable resultado, ya que esta no esta declarada y tendramos un error de compilacin. Ejercicio N 4.1: Hacer una funcin que calcule el mximo entre 2 nmeros enteros: La idea es que se le ingrese dos parmetros y la funcin retorne el mayor, por lo tanto no debemos ni leer de teclado ni imprimir en pantalla. Para saber cual de dos nmeros es mayor, slo debemos compararlos, entonces la parte principal del programa podra ser: declarar una variable que guarde el mayor
int num_max;

luego hacer la comparacin entre los dos datos ingresados, supongamos dato1 y dato2, es decir,
if (dato1>dato2) num_max=dato1; else num_max=dato2;

y listo!. Entonces, la funcin completa sera:


int maxnum(int dato1,int dato2) { int num_max; if (dato1>dato2) num_max=dato1; else num_max=dato2; return(num_max); }

Para hacer ms eficiente nuestra funcin, podemos ahorrarnos la variable num_max y haber hecho:

int maxnum(int dato1,int dato2) { if (dato1>dato2) return(dato1); else return(dato2); }

Es importante indicar en este punto, que el objetivo de crear funciones es para que ellas realicen slo lo necesario (ojal una sola cosa), de esta manera se simplifican los problemas y se facilita la reutilizacin de dichas funciones.

Profesor: Roberto Uribe P.

Pg. N 80

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ejercicio N 4.2: Crear un programa que lea nmeros enteros y que se obtenga el mayor de la lista ocupando la funcin maxnum del ejemplo anterior. El programa debe terminar cuando la suma de los valores absolutos de los datos ledos sea superior a 1000. Entonces, como ya es sabido debemos incluir la biblioteca de entrada y salida, declarar la funcin maxnum y comenzar con la funcin principal. Luego, debemos declarar una variable que mantenga el mximo, la suma, y una variable que contenga los datos que vamos a ir leyendo desde teclado. Como no sabemos la cantidad de datos a leer podemos utilizar un ciclo while e ir leyendo cada dato dentro de este. Para la suma, sabemos que debemos hacer suma igual a suma ms el dato que leamos, pero si el dato es negativo, entonces, suma debe ser igual a suma menos el dato.
#include <stdio.h> int maxnum(); main() { int suma=0,num,max; printf("\nIngrese un dato: "); scanf("%d",&num); max=num; if (num<0) /*para el valor absoluto*/ suma=suma-num; else suma=suma+num; while (suma<=1000) { scanf("%d",&num) max=maxnum(max,num); if (num<0) suma=suma-num; else suma=suma+num; } printf ("\nEl maximo numero leido fue: %d",max); }

Tomar en cuenta que el primer nmero que leemos va a ser asignado al mximo, esto resulta ser lgico, ya que es el nico ledo. Posteriormente, a la funcin se le pasa como parmetros el dato que leemos y el anterior valor mximo y el mayor de ambos ser asignado a max. Finalmente debemos incluir el cdigo fuente de la funcin que calcula el mximo al final de programa. Como podemos hacer mas eficiente el programa?, una forma sera que el calculo del valor absoluto de un nmero sea una funcin, esto sera: crear una funcin a la cual se le pase como parmetro un nmero y retorne el valor absoluto de este. Entonces nuestro programa completo quedara:
#include <stdio.h> int maxnum(int abs); int abs(int dato); main() { int suma=0,num,max; printf("\nIngrese un dato: "); scanf("%d",&num); max=num;
Profesor: Roberto Uribe P. Pg. N 81

Programacin de Computadores y el Lenguaje C

(versin 2003)

suma=suma+abs(num); while (suma<=1000) { scanf("%d",&num) max=maxnum(max,num); suma=suma+abs(num); } printf ("\nEl maximo numero leido fue: %d",max); return 0; } int maxnum(int dato1,int dato2) { if (dato1>dato2) return(dato1); else return(dato2); } int abs(int dato) { if (dato<0) return(-dato); else return(dato); } /*funcion que calcula el mayor */

/*funcion que calcula el valor absoluto */

Por ltimo, debemos saber que la notacin usada hasta ahora para el paso de parmetros es conocida como Notacin Moderna. En la Notacin Clsica o Kernighan & Ritchie, los tipos de los parmetros se especifican fuera de los parntesis de la cabecera de la funcin y antes del cuerpo de la funcin. Por ejemplo, la cabecera de las funciones anteriores seran:
int maxnum(dato1,dato2) /*funcion que calcula el mayor */ int dato1,dato2; { : : } int abs(dato) int dato; { : : } /*funcion que calcula el valor absoluto */

Esta notacin es an frecuente encontrarla, sobre todo en textos y cdigo antiguo. En el estndar ANSI se mantiene nicamente por compatibilidad.

Profesor: Roberto Uribe P.

Pg. N 82

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Problemas Resueltos y Propuestos Resueltos: 1.Implemente la funcin potencia (xy).

2.Escriba la funcin convcharaint() del captulo anterior, recuerde que la cabecera de la funcin debe ser:
int convcharaint(char dato)

3.Escriba un programa en el cual el usuario ingrese un nmero y este arroje una lista de todos los nmeros primos menores o iguales a el nmero ingresado. Para lo anterior, haga una funcin que determine si el nmero es primo o no, el parmetro de entrada es el nmero y la funcin slo debe retornar 0 si el nmero no es primo y distinto de 0 si lo es. Propuestos : 4.Calcular la raz cuadrada de un nmero utilizando la frmula de Newton. Gn=(G0 + N/G0 )/2 N es el nmero para el cual se quiere obtener la raz; G0 es la aproximacin anterior (la cual se inicializa en N/2 ); Gn es la nueva aproximacin. El clculo se realiza hasta que el valor absoluto de la diferencia entre la aproximacin anterior y la nueva sea menor que cierto valor. Por ejemplo : |Gn-G0| < 10-6 (0.000001)

Soluciones: 1.El algoritmo para este problema esta resuelto, por lo tanto, al implementar la funcin debemos eliminar las salidas a pantalla, ya que lo nico que deseamos es el resultado.
float potencia(float x, int y) { float pot=1; int i=0; if (x==0) return(0); for(i=1;i<=abs(y);i++) pot=pot*x; if (y<0) return(1/pot); /*exponente negativo*/ else return(pot); /*exponente positivo*/ }
Profesor: Roberto Uribe P. Pg. N 83

Programacin de Computadores y el Lenguaje C

(versin 2003)

En la funcin, x puede ser cualquier nmero real, adems, se implement el caso de que el exponente fuese negativo, para ello en el for hay una llamada a la funcin abs, implementada anteriormente.

2.En este caso se puede utilizar algunas de las caractersticas permisivas de C, como por ejemplo: hacer la resta entre caracteres. Suponiendo que la mquina donde se ejecuta el programa use la tabla de cdigos ascii, lo que implica que los dgitos estn en orden correlativo de '0' a '9', C nos permite hacer la operacin '1' - '0' lo que nos entregara como resultado 1 (int), ya que el caracter '1' se encuentra una posicin mas all del '0'. Por lo tanto, para obtener el valor numrico de una variable caracter que contenga un dgito sera: variable_char - '0'. Entonces:
int convcharaint(char dato) { if (dato>='0' && dato<='9') /* es digito*/ return(dato-'0'); else switch(dato) { case 'A' : return(10); case 'B' : return(11); case 'C' : return(12); case 'D' : return(13); case 'E' : return(14); case 'F' : return(15); default : return(-1); /*para indicar error*/ } }

Note que no se uso el break, esto ya que cualquier case que sea verdadero termina la funcin. Adems, se retorna un -1 en caso de ingresar un caracter que no corresponde, suponiendo que el valor resultado va a ser mayor que 0. Una modificacin interesante es, reemplazar el switch por :
if (dato>=A && dato<=F) return dato-A+10; /* es dgito */

3.Para esta pregunta ya sabemos como determinar si un nmero es o no primo, lo que resta es ajustar el procedimiento para que haga lo que se nos pidi en el encabezado.
#include <stdio.h> int esprimo(int dato); main() { int num,i=2; printf("\nPrograma para primos.\n"); printf("Ingrese un numero mayor que 0 : ");
Profesor: Roberto Uribe P. Pg. N 84

Universidad de Magallanes - Departamento de Ingeniera en Computacin

scanf("%d",&num); if (num<=0) printf("Error, el numero debe ser mayor que cero.\n"); else { printf("\nTodos los numeros primos hasta el %d son :\n",num); for (i=1;i<=num;i++) if (esprimo(i)) printf("%d\t",i); } return 0; } int esprimo(int dato) { int cont=0; if (dato==1) return 0; /*el 1 no es primo */ if (dato==2) return 1; else for(i=2;i<dato;i++) if ((dato%i)==0) cont++; if (cont>0) return 0; else return 1; }

La funcin clcula si es primo de la misma manera que en el captulo anterior, generalmente las funciones de este tipo no tienen salidas a pantalla y slo hacen el proceso. Otra forma de construir la funcin es:
int esprimo(int dato) { int i=0; if (dato==1) return 0; if (dato==2) return 1; else for(i=2;i<dato;i++) if ((dato%i)==0) return 0; return 1; }

En este caso, la funcin termina a la primera ocurrencia de un mdulo igual a 0, esto resulta lgico dado que no es necesario continuar con el for porque ya se sabe que el nmero no es primo. Esta modificacin le otorga una mayor eficiencia y rapidez al algoritmo. Otra modificacin que implicara ms eficiencia, sera que el for llegara slo hasta la raz cuadrada de dato. Un algoritmo ms eficiente sera :

Profesor: Roberto Uribe P.

Pg. N 85

Programacin de Computadores y el Lenguaje C

(versin 2003)

: else for(i=sqrt(dato);i>=2;i--) if ((dato%i)==0) return 0; return 1; :

Partir desde la raz y decrementa el contador hasta 2, es muy diferente de partir de 2 y llegar hasta la raz. Esto dado que en la primera alternativa la raz se calcula una sola vez, en la inicializacin. En el segundo caso, la raz se evala en la condicin, es decir, se calcula la raz en cada ciclo, lo que involucra un costo adicional en tiempo. Note que sqrt(dato) es un valor double, sin embargo, se convierte en forma automtica a int al asignrselo a y. Al usar la funcin raz cuadrada debe agregar el archivo de cabecera math.h..

Profesor: Roberto Uribe P.

Pg. N 86

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Captulo N 5 : Arreglos o matrices Una matriz o arreglo es un conjunto de elementos (variables) todos del mismo tipo y que agrupados dan lugar a un rea de memoria que puede ser tratada como una variable independiente y de una forma especial. Los elementos que componen el arreglo se encuentran ordenados por su posicin relativa dentro de este. Las matrices pueden ser unidimensionales (vectores) o multidimensionales. Estos poseen un ndice o subndice asociado que va a indicar un componente especfico, este ndice es de tipo entero. La declaracin de un arreglo unidimensional es:
tipo nombre_arreglo[tamao];

donde tamao es el largo del arreglo y tipo el tipo de dato del arreglo y por lo tanto de cada uno de sus componentes. En un arreglo sus componentes pueden ser de cualquier tipo, bsico o creado por el usuario, pero todos del mismo tipo. Para identificar a un elemento se hace de la siguiente manera:
nombre_arreglo[posicin]

donde posicin es la ubicacin del elemento dentro del arreglo. La posicin va de 0 a


tamao-1.

Ejemplo:
int numeros[10];

En trminos reales, cuando se declara un arreglo se reservan espacios contiguos en memoria. En el ejemplo se declar un arreglo de enteros de tamao 10, es decir, los 10 elementos del arreglo son int. Entonces, grficamente podramos suponer que un arreglo es:
0 1 2 3 4 5 6 7 8 9

Si escribimos
numeros[6]

nos estamos refiriendo al sptimo elemento de la matriz, si hubiramos elegido el sexto lo correcto sera: numeros[5]. Para asignar valores a un arreglo se debe hacer componente a componente:
numeros[6]=20; numeros[9]=10;

entonces, el arreglo quedara:


Profesor: Roberto Uribe P. Pg. N 87

Programacin de Computadores y el Lenguaje C

(versin 2003)

20

10

Otra forma es inicializarlo en la declaracin, de la siguiente manera:.


float numreal[4]={0.0,0.0,0.0,0.0}; char frase[5]={'a','b','c','d','e'};

En este ejemplo declaramos un arreglo frase de tipo char, estos se conocen como cadenas de caracteres o string. La forma de imprimir una componente:
printf("\nLa componente 3 es %d",numeros[2]);

No se puede imprimir de una sola vez un arreglo de tipo distinto a char. Para el caso anterior no se puede hacer
printf("...%d %d %d %d...",numeros);

diez %d y luego el nombre del arreglo, si se puede diez %d y luego las diez componentes en la lista de argumentos. Para el caso de los string se puede utilizar el formato %s
printf("\n arreglo de caracteres es: %s",frase); /* imprime abcde */

Igualmente, para ingresar datos se debe hacer de a una componente a la vez:


scanf("%d",&numeros[0]); /*lee el dato de la primera componente*/

Para el caso de un arreglo de tipo caracter se puede hacer la lectura de todo el string, no debe llevar & porque el nombre del arreglo es un puntero al primer elemento de este.
scanf("%s",frase); /*no lleva & */

scanf("%c",&frase[0]); /*Lee solo una componente del string*/

Nos podemos dar cuenta lo engorroso que resulta leer componente a componente un arreglo (distinto de char), sobre todo si este es de tamao grande (por ejemplo, 50). Sin embargo, para ello utilizamos el ciclo for. Por ejemplo, para crear un arreglo de tipo flotante de tamao 50, ingresar los datos e imprimirlos en pantalla, el programa sera:
#include <stdio.h> main() { float reales[50]; int i=0; printf("Ingrese 50 numeros reales\n"); for(i=0;i<50;i++) reales[i]=0.0; /*inicializacion del arreglo (no es necesario)*/ for(i=0;i<50;i++) scanf("%f",&reales[i]); /*Lee todas las componentes del arreglo.*/
Profesor: Roberto Uribe P. Pg. N 88

Universidad de Magallanes - Departamento de Ingeniera en Computacin

printf("\El arreglo es\n"); for(i=0;i<50;i++) printf("%f\t",reales[i]); /*imprime las componentes del arreglo*/ return 0; }

Arreglos de n-dimensiones Para declarar arreglos de dos dimensiones se hace de la siguiente manera:
tipo nombre_arreglo[tamao1][tamao2];

Donde tamao1 es la cantidad de filas y tamao2 es la cantidad de columnas de la matriz. En general, para manipular vectores o matrices se hace de manera similar que en matemticas, es decir, uno se refiere a una matriz a travs de su nombre y a una componente especfica por sus ndices. Ejemplo:
int A[6][4];

Es decir, la matriz A es de 6x4, y para referirnos a A23, se hace A[1][2], tomando en cuenta que usualmente en matemticas los subndices van de 1 a n. La matriz anterior podramos representarla como
0 0 1 2 3 4 5 1 2 3 A[1][2]

A[3][1]

Entonces, para inicializar una matriz de dos dimensiones con cero, la parte principal constara de dos for (uno por cada dimensin) con dos ndices. Para la matriz anterior
for (i=0;i<6;i++) for (j=0;j<4;j++) A[i][j]=0;

Ejercicio N 5.1 : Hacer un programa que calcule la matriz resultado de la multiplicacin de una constante por una matriz de nxn. Solucin: Como la matriz va a ser de n por n, se asume que el usuario ingresar el tamao de la matriz, entonces, podemos definir una matriz de tamao mximo, por ejemplo 100, esto se debe hacer ya que necesariamente debemos definir el tamao. Sabemos que para multiplicar una constante por una matriz debemos multiplicar cada componente de la matriz por la constante. Por lo tanto, en nuestro programa debemos ingresar la cantidad de filas y
Profesor: Roberto Uribe P. Pg. N 89

Programacin de Computadores y el Lenguaje C

(versin 2003)

columnas de la matriz, los datos que esta contendr y el valor de la constante. Una solucin posible es:
#include <stdio.h> main() { int matriz[100][100],resul[100][100],const,i,j,fil,col; printf("Programa que calcula la multiplicacion de una matriz\n"); printf("por una constante.\n"); for (i=0;i<100;i++) /*se llena la matriz completa de ceros*/ for (j=0;j<100;j++) matriz[i][j]=0; /*lectura de datos*/ printf("Ingrese filas de la matriz"); scanf("%d",&fil); printf("Ingrese Columnas de la matriz"); scanf("%d",&col); printf("Ingrese datos de la Matriz\n"); for (i=0;i<fil;i++) /* el rango ahora es fil x col*/ for (j=0;j<col;j++) { printf("(%d,%d)=",i,j); /*para que se vea una buena salida*/ scanf("%d",&matriz[i][j]); } printf("Ingrese Constante"); scanf("%d",&const); /* proceso de multiplicacion*/ for (i=0;i<fil;i++) /* el rango ahora es fil x col*/ for (j=0;j<col;j++) result[i][j]=matriz[i][j]*const; /* impresion de resultados*/ printf("La matriz resultante es:"); for (i=0;i<fil;i++) { for (j=0;j<col;j++) printf("%d",result[i][j]); printf("\n"); /*para que cada fila salga en una linea*/ } return 0; }

Como se ve en este ejercicio, hay bastantes mensajes a pantalla, de esta manera se logra que el usuario final entienda de que se trata el programa, adems de saber cuando ingresar los datos. Como antes se ha dicho, la inicializacin no es necesaria, pero es una buena costumbre hacerlo. Los elementos de la matriz que estn fuera del rango fil x col no se accesan, esto ya que los for no lo permiten. Constantes Simblicas En nuestro ejemplo, si tuviramos que modificar el tamao mximo por cualquier motivo, tendramos que rectificar algunas lneas de cdigo, si el programa fuera mucho mas extenso, esto se complicara. En C existe las llamadas constantes simblicas, que son valores que se asignan a identificadores, los cuales no se pueden modificar. Esto se hace a travs de la directiva #define. Por ejemplo:
# define MAX 100

Profesor: Roberto Uribe P.

Pg. N 90

Universidad de Magallanes - Departamento de Ingeniera en Computacin

nos permitira tener una constante llamada MAX con un valor de 100. La idea de esto es usar MAX en vez de 100, de esa manera, si se tiene que cambiar el valor 100 por otro, slo se cambia MAX, de esa manera se modifica una sola lnea del programa, esto nos simplifica el trabajo al momento de hacer mantenciones o depuraciones de nuestros programas.

Los arreglos tienen mltiples aplicaciones, sobre todo en el arrea de las matemticas, pero su espectro cubre mucho ms que eso. Por ejemplo, un arreglo de dos dimensiones nos permitira almacenar una lista con nombres, y si a esto agregramos un arreglo de enteros, podramos tener la lista de un curso y el promedio de cada alumno, o podra ser la lista de clientes y la deuda que poseen:
char NombresALum[20][30]; int Notas[20]; /* dos arreglos que nos permiten guardar 20 nombres y 20 notas*/ NombresAlum .......... i a i i o l a z Notas 0 0 60 1 51 2 45 3 48 : : : : : : :

0 1 2 3 4 : : : :

0 B C M P : : : : :

1 a e a e

2 r c n r

3 r h d e

29

19

...............

19

Para leer el arreglo Notas se hace de la manera ya vista, para NombresAlum se puede hacer con dos ciclos for o bien con un ciclo for y utilizando el formato %s para string. Por ejemplo:
for (i=0,i<20; i++) /* filas */ scanf("%s",NombresAlum[i]);

Esto leera las 20 filas, donde cada scanf estara leyendo una cadena. Para que nuestro diseo funcione, se asume que cada alumno tiene su nota en la misma posicin donde va su nombre, es decir, el alumno NombresAlum[11] tiene su nota en Notas[11]. Para el ejemplo anterior siempre es mejor usar estructuras (concepto nuevo), sin embargo, es una buena idea dado los conocimientos hasta ahora vistos.

Profesor: Roberto Uribe P.

Pg. N 91

Programacin de Computadores y el Lenguaje C

(versin 2003)

Una de las precauciones que debemos tener con los arreglos es con sus rangos, ello porque C no comprueba los lmites de los arreglos, por lo tanto queda en manos del programador comprobar que estos se respeten. Por ejemplo, en C lo siguiente es permitido:
int A[20],i; for (i=0;i<30;i++) scanf("%d",&A[i]);

No hay error de compilacin, sin embargo, esto podra provocar problemas, ya que alguna variable declarada con anterioridad puede ocupar los espacios de memoria posteriores al arreglo y por lo tanto ser sobrescrita. En general, para declarar arreglos de n-dimensiones, el formato es el siguiente:
tipo nombre_arreglo[tamao1][tamao2]....[tamaoN];

Ejercicio N 5.2: Una de las aplicaciones usuales de arreglos en programacin es el ordenamiento de datos. Entonces, crear un programa al cual se le ingresen 5 nmeros enteros y los imprima en orden ascendente. Solucin: Una forma de resolver este problema es usando un arreglo que contenga los datos, luego ordenarlos dentro del arreglo e imprimirlos. La parte fundamental del problema es ordenar dichos datos. Hay variadas formas de hacerlo, una es ir comparando cada componente con la siguiente de tal manera de ir moviendo el menor hacia el extremo izquierdo del arreglo. Por ejemplo, supongamos los siguientes datos, 100,20,50,8,0. Entonces, tomamos la componente 0 (100) y lo comparamos con la componente 1 (20), luego si es mayor cambiamos el contenido, luego volvemos a comparar la componente 0 (que ahora sera 20) con la componente 2, y si es mayor lo intercambiamos, etc. El proceso sera: Ingresar los datos al arreglo, y luego
100 20 50 8 0 20 100 50 8 0

Como 100 es mayor que 20, se cambian

Como 20 no es mayor que 50, no se cambian

20 100 50

8 100 50

20

20 es mayor que 8, se cambian

8 es mayor que 0, se cambian

El arreglo finalmente quedara

0 100 50

20

Profesor: Roberto Uribe P.

Pg. N 92

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Hay que reconocer que en realidad lo que se compara son los contenidos de las componentes, ya que estas segn los resultados de las comparaciones van a ir variando. Ahora, una vez que se recorri el arreglo para la primera componente, se vuelve a hacer el mismo proceso para la segunda componente y con las restantes. Es suficiente llegar hasta la penltima componente, ya que esta se compara con la siguiente. Cual sera el algoritmo para esto?. Como es un arreglo, inmediatamente pensamos en un ciclo for para recorrer todo el vector. Ahora, el arreglo no se recorre una vez, sino, una por cada componente, es decir, se toma el componente 0 y se va comparando con las componentes 0+1 hasta n. Entonces una aproximacin sera:
for(i=0;i<..... for(j=i+1;j<n;j++)

Como el for interno (j) recorre hasta el final y comienza en 1 mas que el externo, entonces i tiene que llegar hasta n-1. Osea:
for(i=0;i<(n-1);i++) for(j=i+1;j<n;j++)

Otra cosa importante que debemos saber, es como hacer el intercambio de datos entre dos variables. Para ello se utiliza una variable auxiliar, ejemplo:
aux=a; a=b; b=aux;

de esa manera no se pierde el contenido de la variable a. Entonces nuestro programa quedara:


#include <stdio.h> #define largo 5 main() { int datos[largo],i=0,j=0,aux; printf("Este programa ordenara los numeros que Ud. ingrese\n\n"); printf("Ingrese %d numeros enteros\n",largo); for(i=0;i<largo;i++) scanf("%d",&datos[i]); printf("\El arreglo sin ordenar es:\n"); for(i=0;i<largo;i++) printf("%d\t",datos[i]); for(i=0;i<(largo-1);i++) /*parte principal*/ for(j=i+1;j<largo;j++) if (datos[i]>datos[j]) /*para el intercambio de los contenidos*/ { aux=datos[i]; datos[i]=datos[j]; datos[j]=aux; } printf("\El arreglo ordenado es:\n"); for(i=0;i<largo;i++) printf("%d\t",datos[i]); return 0; }

Profesor: Roberto Uribe P.

Pg. N 93

Programacin de Computadores y el Lenguaje C

(versin 2003)

La ejecucin de la parte principal de este ejercicio incluyendo ndices y los datos del arreglo es:
i 0 0 0 0 1 1 1 2 2 3 j 1 2 3 4 2 3 4 3 4 4 datos[0] 100 20 20 8 0 0 0 0 0 0 0 datos[1] 20 100 100 100 100 50 20 8 8 8 8 datos[2] 50 50 50 50 50 100 100 100 50 20 20 datos[3] 8 8 8 20 20 20 50 50 100 100 50 datos[4] 0 0 0 0 8 8 8 20 20 50 100 aux 100 100 20 8 100 50 20 100 50 100
Datos ingresados Guard el valor anterior.

Este es uno de los mtodos de ordenamiento ms conocidos y es denominado como Mtodo de la Burbuja, existen otros mtodos como el de Seleccin y el de Mezcla.

Cadenas de Caracteres Los string o cadenas de caracteres se manipulan como un arreglo comn, sin embargo, se pueden manejar de forma especial, como se pudo ver en los ejemplos anteriores de ingreso y salida a pantalla. Para trabajar con cadenas debemos primero tener claro ciertos conceptos respecto de ellas. - Un string es un arreglo de caracteres que termina con el caracter nulo \0. Es por ello que usualmente al declarar un string se le agrega un elemento ms para que contenga dicho caracter. Sin embargo, C permite trabajar con constantes de caracteres, estas estn encerradas entre comillas dobles, en este caso, si no se le incluye el caracter nulo al final, C lo hace de manera automtica. Un ejemplo es:
"Aqui estamos otra vez"

que sera lo mismo que


"Aqui estamos otra vez\0"

Por ejemplo, si se desea copiar un string en otro sin saber el largo del primero, podemos hacer:
for(i=0;str1[i]!=\0;i++) str2[i]=str1[i]; str2[i]=\0;

Con esto se copi str1 en str2, como dentro del for no se copio el caracter nulo, se hizo al final. Para manipular cadenas existe una biblioteca llamada string.h, en la cual se encuentran una serie de funciones que permiten entre otras cosas: comparar dos string, copiar
Profesor: Roberto Uribe P. Pg. N 94

Universidad de Magallanes - Departamento de Ingeniera en Computacin

un string en otro, saber el tamao de una cadena, ver si un caracter esta dentro del string, etc. Algunas de ellas son: Nombre Funcin:
strcpy(str2,str1); strcmp(str1,str2);

strlen(str1); strcat(str1,str2); strchr(str1,car1);

Descripcin Copia str1 en str2. Compara los dos string str1 y str2, devuelve un valor entero que es : menor, mayor o igual a cero, dependiendo si str1 es lexicogrficamente menor, mayor o igual a str2. Devuelve un entero que va a ser el largo de str1. Concatena el string str2 al final de str1. Retorna un puntero a la primera aparicin del caracter car1 en str1.

Ejemplos:
if (strcmp(nombre,string1)>0) printf("El string %s es mayor que %s",nombre,string1); : : strcat(nombre,string1); printf("Ahora %s tiene largo %d",nombre,strlen(nombre)); :

Cadenas sin tamao definido En C se puede hacer la inicializacin de cadenas no delimitadas, para ello se declara el arreglo y se le asigna una constante string:
char normal[50]; /*declaracion tradicional*/ char s1[]="Mensaje de Error"; char s2[]="Ingrese de nuevo el dato";

Con esto nos evitamos saber a priori cuanto espacio debe tener el arreglo para contener todos los caracteres. C automticamente crea un arreglo con el tamao suficiente para contener el string mas el caracter nulo. Existe otra forma de declarar un string sin un tamao especfico, por ejemplo:
#include <stdio.h> #include <string.h> main() { char normal[50]; /*declaracion tradicional*/ char *s1; char *s2="Esto no tiene largo\0"; char *s3="\0"; /*inicializada en nulo*/ printf("El string %s tiene largo %d",s2,strlen(s2)); strcpy(s3,s2);
Profesor: Roberto Uribe P. Pg. N 95

Programacin de Computadores y el Lenguaje C

(versin 2003)

: :

En trminos formales, en el ejemplo se declararon punteros a char, para ello se utiliz el operador *. Para el caso de s2 y s3 es idntico al ejemplo anterior. Sin embargo, es ilegal hacer strcpy(s3,s2) y habra un error en tiempo de ejecucin, de no ser as (depende del sistema operativo), puede ocurrir cualquier cosa. A veces se utilizan los punteros a char como arreglos y se realizan operaciones sobre ellos, como copiar, concatenar, etc. Cuando los programas son cortos no se provoca ningn error, sin embargo, cuando son ms extensos, lo que implica mayor uso de memoria, usualmente ocurren errores de asignacin de esta, esto provocado porque el arreglo no tiene la capacidad de almacenar todos los caracteres. Estos errores provocan la cada del programa o la mala ejecucin de este. Para solucionar este problema, se hace una asignacin dinmica de memoria al arreglo (dado que es un puntero a char). Esto en trminos generales es asignar memoria a una variable en tiempo de ejecucin, para ello se utiliza la funcin malloc(), esta se ver ms adelante. Recuerde: Las variables globales obtienen memoria en tiempo de compilacin. Las variables locales utilizan la pila de memoria.

Como retornar un string En mucha ocasiones es necesario que una funcin retorne un arreglo, en este captulo veremos el caso de retornar una cadena de caracteres. Para ello, hay que declarar la funcin como char y adems agregar el caracter asterisco antes del nombre de la funcin. Para ilustrar lo anterior veamos el siguiente ejemplo:
#include <stdio.h> #include <string.h> char *agregahola(char *nombre); main() { char nombre[50]; printf("Ingresa un nombre :"); scanf("%s",nombre); printf("%s",agregahola(nombre)); } char *agregahola(char *nombre) { char s[50] strcpy(s,"Hola "); strcat(s,nombre); return s; }

Profesor: Roberto Uribe P.

Pg. N 96

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Recuerde que strcat concatena en este caso, el contenido de la variable nombre al final de s. Como lo que se retorna es un string, entonces, el segundo printf de la funcin principal es correcto. Este programa funciona sin problemas, pero lo ideal es declarar s con un tamao capaz de contener el string que se le concatena. Adems, es posible que al compilar aparezca una advertencia respecto de retornar una direccin de una variable local. Esto ltimo se ver en el capitulo de punteros. Por ltimo, el parmetro pasado a la funcin, fue declarado como: char *nombre lo que indica que lo que se pasa es un puntero a char. En este caso no hay error, ya que el string como tal es un puntero, y adems, el tamao de este parmetro es el tamao de la variable que es pasada a la funcin.

Arreglos como parmetros Los arreglos como cualquier otra variable se pueden pasar como parmetros a las funciones y se hace de la misma manera. Supongamos:
#include <stdio.h> #define MAX 50 void muestra(int arr[MAX]); main() { int vector[MAX]; : muestra(vector); : : } void muestra(int arr[MAX]) { int i=0; for(i=0;i<MAX;i++) printf("%d\t",arr[i]); return; }

En si el nombre de un arreglo es un puntero al primer elemento de este, entonces al pasarlo como parmetro a una funcin los valores de sus componentes pueden ser modificados. Por ejemplo, la siguiente funcin logra modificar el arreglo vector:
void modifica(int arr[MAX]) { int i=0; for(i=0;i<MAX;i++) arr[i]=arr[i]*10; return; }

La llamada desde el main debera ser:


modifica(vector);
Profesor: Roberto Uribe P. Pg. N 97

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejercicio N 5.3 : Una de las aplicaciones frecuentes con arreglos es la bsqueda de datos en estos. Supongamos entonces que, se tiene un arreglo con N datos enteros. Cree una funcin que permita la bsqueda de un dato especfico dentro del arreglo. Los datos no estn ordenados dentro del arreglo. Solucin : La primera forma de resolverlo es ir comparando uno a uno los datos del arreglo con el dato ingresado (dato que se busca).Entonces, debemos usar un ciclo que nos permita recorrer el arreglo, y dentro de este hacer la comparacin :
for (i=0;i<N;i++) if(a[i]==dato) printf(dato encontrado); else printf(dato no encontrado);

Este mtodo se conoce jocosamente como el mtodo carretero, ya que es el que podra demorarse ms en buscar. Un ejemplo de programa completo sera :
#include <stdio.h> #define N 15 /* N va a ser el mximo de datos */ int busca(int a[N], int dato); main() { int arr[N], dato, i=0; printf(Ingrese datos para llenar el arreglo (%d),N); for(i=0;i<N;i++) { printf(dato %d: ,i); scanf(%d,&arr[i]); } printf(Ingrese un dato a buscar); scanf(%d,&dato); if (busca(arr,dato)) printf(Dato Encontrado); else printf(Dato no existe en el arreglo); return 0; } int busca (int a[N], int dato) { int i=0; for(i=0;i<N;i++) if (a[i]==dato) return 1; /* encontrado return 0; /* no encontrado */ }

*/

Observe que se pasaron como parmetros tanto el arreglo como el dato que se busca. Esta funcin retorna 1 si el dato existe y despus de recorrer todo el arreglo y comprobar que el dato no se encuentra retorna 0. Por ltimo, si los datos dentro del arreglo se encuentran ordenados, se podra utilizar algn otro mtodo ms eficiente para la bsqueda, un mtodo que se demorara menos.

Profesor: Roberto Uribe P.

Pg. N 98

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ejercicio N 5.4: Suponga que se tienen los dos arreglos mencionados anteriormente, NombresAlum y Notas, los que almacenan los nombres (y apellidos) de un curso y el promedio de cada alumno. En el problema planteado se asume que las notas estn en las mismas posiciones de los nombres (pero en distintos arreglos). Entonces, se debe crear una funcin que permita ingresar un nombre y arroje el promedio de la persona. Solucin: El proceso sera, tomar el nombre ingresado por teclado y compararlo con toda la lista de nombres del arreglo NombresAlum, con esto obtenemos la posicin en que se encuentra dicho nombre. Seguido, tomamos la posicin obtenida y buscamos el promedio ubicado en esa posicin en el arreglo Notas. Entre las cosas a considerar estn: para comparar los nombres de la lista con el ingresado se debe usar la funcin strcmp() para comparar string, por lo tanto hay que incluir en el programa al archivo de cabecera string.h. Los arreglos estn declarados como globales, de esa manera los podemos ocupar en cualquier funcin que tenga el programa. La primera parte del programa es:
# include<stdio.h> # include<string.h> char NombresALum[20][30]; int Notas[20]; /* dos arreglos que nos permiten guardar 20 nombres y 20 notas*/

La funcin sera:
void consulta() { char nombre[30]="\0"; int posicion=-1, promedio=0; printf("Ingrese un nombre :"); scanf("%s",nombre); posicion=buscanombre(nombre); if (posicion==-1) { printf("Error, Nombre no encontrado\n"); return; } else { promedio=buscapromedio(posicion); printf("El promedio de %s es : %d\n",nombre,promedio); } return; }

Entonces, tenemos la funcin que ingresa el nombre, para hacer ms modular el programa creamos dos funciones ms, una que busca el nombre y otra que busca el promedio. La primera funcin pasa como parmetro el nombre, si no es encontrado retorna -1, de esa manera evitamos errores. Una vez encontrada la posicin, pasamos como parmetro a la segunda funcin este dato. Las funciones seran de la siguiente forma:

Profesor: Roberto Uribe P.

Pg. N 99

Programacin de Computadores y el Lenguaje C

(versin 2003)

int buscanombre(char *s) { int i=0; for(i=0;i<20;i++) if (strcmp(s,NombresAlum[i])==0) /*Si los nombres son iguales*/ return(i); /*retorna la posicion*/ return(-1); }

Con esto logramos ubicar la posicin, si no la encuentra el for recorre todo el arreglo y por lo tanto retorna un -1. La funcin que busca el promedio sera:
int buscapromedio(int pos) { return(Notas[pos]) } /*No es necesario recorrer el arreglo ya que tenemos la posicin. */

Profesor: Roberto Uribe P.

Pg. N 100

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Problemas Resueltos y Propuestos Resueltos: 1.Escribauna funcin a la que se ingresa una cadena de caracteres de largo indefinido y arroje como resultado la misma cadena, pero sin los caracteres espacio en blanco (' ') y tabulador ('\t'). Escriba el programa completo. Restriccin: el programa debe hacerse utilizando un solo arreglo de caracteres. Ejemplo:
Ingrese tira de caracteres: Espero que todos terminen La misma cadena es: Esperoquetodosterminenalahora. a la hora.

2.Escriba un programa que lea una matriz de NxM, donde N y M son valores conocidos menores que 40. El programa debe convertir esta matriz en su traspuesta. Se entiende por matriz Traspuesta aquella que sus componentes j,i son iguales a las componentes i,j de la matriz original, es decir: a11 a12 a13 .... a1m a21 a22 a23 .... a2m .................. an1 an2 an3 .... anm
T

A=

A=

a11 a21 a31 .... an1 a12 a22 a32 .... an2 .................... a1m a2m a3m .... anm

Condicin: utilice el mismo arreglo para hacer el ejercicio. 3.Escriba una funcin que realice una bsqueda en texto, para ello a la funcin debe ingresar dos string de tamao indefinido, el primero es el texto en el que se va a buscar una palabra (segundo string). La funcin debe retornar 1 si es encontrada la palabra y 0 de lo contrario. 4.Un grupo de expertos del rea informtica contratado especficamente para resolver los mensajes en clave tiene una nueva tarea. Cada vez que la otra parte en conflicto se da cuenta que sus mensajes son decodificados, esta inventa una nueva forma de codificarlos. Para el siguiente mensaje captado por el grupo de ingenieros:
Ehp o uoy sare se tnonru ee adbtapcss moarmuoft o reoenuu sp t,s ed oee tmri lrsnpouzo
Profesor: Roberto Uribe P. Pg. N 101

Programacin de Computadores y el Lenguaje C

(versin 2003)

u tio co. caedrqh

Finalmente se determin que este texto corresponda a una matriz de caracteres, es decir, para el texto anterior la matriz es:
E s t a m o s h a n d o p r o b a r o e n t r e t e n i d r a m o , p o r u o e e c s o f n u e m r u z c o q h s u p u e s t o y e s t u d i o .

p o e l r s u t c a e

Para obtener el mensaje final, se tienen que leer la matriz columna a columna, es decir, es mensaje decodificado sera: Estamos luchando por aprobar este entretenido ramo, por supuesto que con mucho esfuerzo y estudio. Cree una funcin a la cual se le pasa como parmetro esta matriz (de 11x9) y que retorne un string con el texto decodificado. 5.Disee un programa que simule una Base de Datos, para ello utilice slo arreglos. Imagine que tiene una empresa con 20 trabajadores, a cada uno se le paga en forma diferente la hora de trabajo extra, adems todos realizan horas extras de 0 a N siendo estos valores enteros positivos. El programa debe hacer lo siguiente: - Leer el nombre de cada trabajador. - Leer la cantidad de horas extras realizadas en el mes. - Leer el valor de la hora extra asignado para cada empleado. - Finalmente, debe entregar un resumen con todos los datos del empleado, adems del dinero que recibir de acuerdo a las horas trabajadas y al valor por hora, esto debe ser al finalizar el programa. Ejemplo:
Ingreso de Datos: Nombre : Perico Perez Palotes Horas extra : 43 Valor Hora : 1500 Nombre Horas extra Valor Hora Nombre Horas extra
Profesor: Roberto Uribe P.

: : : : :

Leonardo Da Vince 58 2100 Cleopatra Contreras C. 0


Pg. N 102

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Valor Hora : 1980 . . . . . . . . . . . . . Resumen: Nombre Perico Perez Palotes Leonardo Da Vince Cleopatra Contreras C. . . . . . . . . . . . . Horas 43 58 0 . . . . Valor 1500 2100 1980 Total 64500 121800 0

Propuestos: 6.Escriba una funcin a la que se le ingrese como parmetro un string , dicha funcin debe retornar la cantidad de espacios en blanco, tabuladores, puntos y comas que tiene el arreglo. Condicin: no se conoce el tamao del string ingresado a la funcin. 7.Haga un programa que determine si un palabra o frase ingresada va teclado es o no palndrome. Una palabra palndrome es aquella se lee de la misma manera al derecho y al revs, ejemplo:
ingrese frase: alla la frase es palndrome.

8.Escriba un programa que lea una matriz cuadrada de NxN donde N es valor conocido y menor que 40. El programa debe verificar que la matriz ingresada es simtrica o no. Se entiende por matriz simtrica aquella que el valor de sus componentes i,j es igual a j,i, es decir: a11 a12 a13 ... a1n a21 a22 a23 ... a2n ................ . an1 an2 an3 ... ann

Donde: ai,j = aj,i 9.Ud. pertenece a un equipo de expertos en inteligencia y se le ha encomendado crear un mtodo para codificar mensajes. Despus de pensar un poco en la posible frmula, llego a la genial idea de utilizar el cdigo ascii para hacer la codificacin del mensaje. El mtodo consiste en que a cada letra del mensaje original se le coloca en el mensaje que se enviar la letra siguiente, es decir, a la letra se le suma 1 lo que implicara colocar la siguiente letra de la tabla ascii.
Profesor: Roberto Uribe P. Pg. N 103

Programacin de Computadores y el Lenguaje C

(versin 2003)

Por ejemplo, para el siguiente mensaje:


Oh! maestro, los que van a morir te saludan!!

El mensaje codificado sera:


Pi! nbftusp, mpt rvf wbo b npsjs uf tbmvebo!!

Cree un programa que lea el mensaje a codificar (mensaje real), luego codifquelo utilizando un arreglo de tamao no definido, y finalmente imprima este mensaje en pantalla. Para ello utilice una funcin a la cual se le pasa como parmetro el mensaje original y retorne un string con el mensaje codificado. Nota: si la letra es z, entonces se debe colocar la a en el mensaje codificado. 10.Para el siguiente programa:
# include <stdio.h> main() { int a[20],aux,n=0,y,j; printf("Ingrese el nmero de datos a leer"); scanf("%d",&n); for(i=0;i<n;i++) { printf("\n Ingrese dato a[%d]:",i); scanf("%d",&a[i]); } for(i=0;i<(n-1);i++) for(j=i+1;j<n;j++) { if(a[i]>a[j]) { aux=a[i]; a[i]=a[j]; a[j]=aux; } } }

Suponiendo que los datos ingresados fueron 5 (10,-5,15,5,-20), muestre la ejecucin del ciclo for principal, indicando el comportamiento de las variables y del arreglo. 11.- Implemente la funcin strcat, esta funcin concatena dos string. A dicha funcin se le ingresa como parmetros 2 cadenas de caracteres de tamao no conocido. 12.- Implemente un programa que cuente las palabras que contiene un string: Utilice la funcin gets() para leer el string (esta funcin permite leer un string incluido los espacios en blanco y tabuladores). Las palabras pueden estar separadas por espacios, tabuladores, puntos, comas, punto y comas. Escriba una funcin que tenga como parmetro el string y retorne el nmero de palabras.
Profesor: Roberto Uribe P. Pg. N 104

Universidad de Magallanes - Departamento de Ingeniera en Computacin

13.-

Disee un programa que simule una Base de Datos, para ello utilice slo arreglos. Suponga que se tiene un curso de 40 alumnos y que cada alumno rindi 3 pruebas en el semestre. El programa debe hacer lo siguiente (cada uno de los procesos debe ser una funcin): - Ingresar el Apellido y Nombre de todos los alumnos. - Leer las notas de cada alumno. - Calcular el promedio de cada alumno y dejarlo en un nuevo arreglo. - Finalmente debe entregar un listado con el apellido, nombre, notas y promedio. Al final de la lista debe entregar el promedio general del curso. Restricciones: Todas las operaciones deben ser hechas en funciones. Adems, declare los arreglos en forma local, dentro del main. El programa debe funcionar de la siguiente manera:
Ingrese datos de los alumnos: Nombre: Apellido: Nombre: Apellido: Nombre: Apellido: . . . Miguel Angel Garay Alejandra Cardenas Pamela Zuniga

Ingrese Notas: Miguel Angel Garay: Nota 1: 65 Nota 2: 88 Nota 3: 44 Alejandra Cardenas: Nota 1: 50 Nota 2: 29 Nota 3: 60 Pamela Zuniga: Nota 1: 58 Nota 2: 100 Nota 3: 15 . . . Resumen: Nombre Miguel Angel Garay Alejandra Cardenas Pamela Zuniga ......... Promedio General: 1 65 50 58 2 88 29 100 3 44 60 15 XX Promedio 66 46 58

Nota: Los nombre fueron cambiados para proteger a los inocentes ;-).
Profesor: Roberto Uribe P. Pg. N 105

Programacin de Computadores y el Lenguaje C

(versin 2003)

Soluciones: 1.El objetivo de trabajar con la misma cadena es para aumentar la complejidad del problema, sin embargo, una solucin ms sencilla sera: ir copiando caracter a caracter de un arreglo a otro, salvo los espacios y tabuladores. La solucin para el problema original es la siguiente:
# include <stdio.h> char *elim(char *st); main() { char s[40]="\0"; printf("Ahora :\n"); gets(s); printf("%s",elim(s)); return 0; } char *elim(char *st) { int i=0,j=0; for(i=0;st[i]!='\0';) { putchar(st[i]); /*para ver el proceso en pantalla*/ if (st[i]==' ' || st[i]=='\t') /*encuentra espacio o tabulador*/ { putchar('<'); /*marca el inicio de lo que se mueve a la izquierda*/ for(j=i+1;st[j]!='\0';j++) { st[j-1]=st[j]; /*copia caracter a caracter a la izq.*/ putchar(st[j]); /*lo muestra en pantalla*/ } putchar('>'); /*fin de lo que se movio a la izq.*/ st[j-1]='\0'; } else i++; } printf("\n\n"); return(st); }

La idea de este programa es: al encontrar un espacio o tabulador, copia todo el arreglo una posicin a la izquierda, luego, revisa nuevamente desde esa posicin y repite el proceso al encontrar otro espacio o tabulador. Importante es notar que si se cumple la condicin y una vez que se movi el resto del arreglo, se inserta un caracter '\0' al final menos 1, esto para que no quede basura al final del string. Las salidas a pantalla en la funcin es para ver como se va realizando el proceso, es decir, va mostrando lo que se esta moviendo a la izquierda. La funcin anterior tiene dos for, es decir, hace un recorrido al arreglo por cada espacio o tabulador. Analice el siguiente algoritmo :
char *elim(char *st) { int i,dist=0; for (i=0;st[i]!=\0;i++) if (st[i]== || st[i]==\t) dist++; else
Profesor: Roberto Uribe P.

/* encuentra espacio o tabulador */

Pg. N 106

Universidad de Magallanes - Departamento de Ingeniera en Computacin

st[i-dist]=st[i]; st[i-dist]=\0; return (st); }

La nueva versin es mucho ms eficiente, recorre slo una vez el arreglo.

2.Para resolver este ejercicio, lo que se hace es usar una variable auxiliar llamada aux para hacer el intercambio desde el elemento (i,j) al elemento (j,i) de la matriz en cuestin. Si se desea trabajar con otra matriz de diferente tamao, basta con cambiar el valor de N y M en la cabecera del programa.

#include <stdio.h> #define MAX 50 #define N 3 #define M 4 main() { int i=0,j=0,arr[MAX][MAX],aux,mayor; if (N>=M) mayor=N; else mayor=M; /* es necesario para poder decir cuantas veces se hara un intercambio del elemento (i,j) al elemento (j,i) */ for (i=0;i<N;i++) for(j=0;j<M;j++) { printf("\nIngrese el elemento [%d],[%d] : ",i,j); scanf("%d",&arr[i][j]); } /* Aqu se leyeron todos los elementos de la matriz */ printf("\n\nSu Matriz original es : "); for (i=0;i<N;i++) { printf("\n"); for(j=0;j<M;j++) printf("%d\t",arr[i][j]); } /* Aqu simplemente se imprimieron los elementos de la matriz */

for(i=0;i<mayor;i++) for(j=i+1;j<mayor;j++) { aux=arr[j][i]; arr[j][i]=arr[i][j]; arr[i][j]=aux; } /* Aqu la matriz se convirtio en su traspuesta */ printf("\n\nSu Matriz Traspuesta es : "); for (i=0;i<M;i++) { printf("\n"); for(j=0;j<N;j++) printf("%d\t",arr[i][j]); } return 0; }

Profesor: Roberto Uribe P.

Pg. N 107

Programacin de Computadores y el Lenguaje C

(versin 2003)

3.En este ejercicio se us una funcin encuentra que lo primero que hace es buscar el primer caracter del substring sub_str en el primer texto ingresado str y despus que lo haya encontrado se comienza a comparar el resto del substring, contando el nmero de coincidencias (mediante un contador llamado flag)y si el nmero de coincidencias es igual al tamao del substring entonces se retorna 1, y si no se encontr se retorna 0.
#include <stdio.h> #include <string.h> #define MAX 100 int encuentra(char primero[MAX],char segundo[MAX]); main() { int i; char arr1[MAX],arr2[MAX]; printf("\nIngrese el primer texto : "); gets(arr1); /* La funcion gets() permite leer espacios y elimina el salto de lnea almacenado en el buffer del teclado al presionar la tecla enter para introducir el string arr1. A diferencia de la funcin scanf() */ printf("\n\nIngrese el segundo texto : "); gets(arr2); printf("\n\n%d",encuentra(arr1,arr2)); return 0; } int encuentra(char str[MAX],char sub_str[MAX]) { int i=0,j=0,k=0,flag; for(i=0;str[i]!='\0';i++) if (str[i]==sub_str[0]) /* No se mete dentro del if hasta que */ { /* encuentre el primer elemento de sub_str */ flag=1; /* en str */ k=i; for(j=1;j<strlen(sub_str);j++) { k=k+1; if (str[k]!=sub_str[j]) break; flag++; } if (flag==strlen(sub_str)) return 1; } return 0; }

4.Aqu se recibe como parmetro un arreglo de dos dimensiones, y a cada elemento del string st se le asigna el elemento (j,i) de la matriz recibida.
char *funcion_dec(char arr[11][9]) { int i=0,j=0,k=0; char st[100]; for(i=0;i<11;i++) for(j=0;j<9;j++) { st[k]=arr[j][i]; k++; } st[k]='\0'; return st; }
Profesor: Roberto Uribe P. Pg. N 108

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Profesor: Roberto Uribe P.

Pg. N 109

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N 6 : Modos de Almacenamiento Existen cuatro formas de almacenamiento, estas determinan el alcance (Scope) y el tiempo que permanece la variable en memoria.

Variables Automticas (auto) Todas las variables declaradas en una funcin son por defecto automticas, es decir su alcance es local (a la funcin). Ej.:
main() { auto int suma=0; }

En el ejemplo se declar la variable suma explcitamente como automtica. No es necesario poner la palabra reservada auto. Lo anterior es equivalente a:
main() { int suma=0; }

La variable est activa en el par de llaves en la cual es declarada.

Variables Externas (extern) Si una variable se declara fuera de una funcin se dice que es externa (lo que conocemos como variable global). Su alcance va ha ser todo archivo o los archivos fuentes. Ej.:
int parcial=1: main() { extern parcial; . } Sumatoria() { extern int parcial; } /* variable definida externamente */ /* no es necesario */ /* se declara la variable definida */ /* anteriormente */

/* tampoco es necesario */

Para usar la variable externa no es necesario declararla como extern dentro de las funciones del mismo archivo, ya que si se omite la declaracin se asume por defecto que es externa (o global). Por ejemplo, si se tiene un segundo archivo fuente se puede declarar en las primeras lneas de este.

Profesor: Roberto Uribe P.

Pg. N 110

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ej.:

extern int parcial; void estructuras(); { : : }

Se asume que la variable esta definida en otro archivo. Por ejemplo, supongamos que tenemos dos archivos, princip.c y secundar.c:
princip.c
# include<stdio.h> int fact(); int result=0; main() { : : } int fact() { : : }

secundar.c
float pot(int x,int y) { int pot=1 extern int result; : : : result=pot; }

Entonces, la variable result utilizada en la funcin pot del archivo secundar.c es la declarada en princip.c. Si el programa hubiese sido hecho en Unix, habra que generar los cdigos objetos de ambos archivos y luego el ejecutable. Para hacer esto se utiliza la opcin -c al momento de compilar.
cc -c princip.c cc -c secundar.c cc princip.o secundar.o genera princip.o genera secundar.o genera a.out

Variables Registro (register) Las variables de tipo register nos permiten almacenar una variable en algn registro de la CPU en vez de la memoria RAM, esto con la finalidad de que dicha variable sea manipulada mucho ms rpida que en memoria. Esto siempre y cuando sea posible ocupar algunos de los registros, de no ser as, la variable queda declarada como automtica. El uso ms comn para este tipo de variable es en los contadores, ejemplo: Ej.:
main() { register int conta; : : }
Pg. N 111

Profesor: Roberto Uribe P.

Programacin de Computadores y el Lenguaje C

(versin 2003)

Variables Estticas (static) Tienen el mismo alcance que las variables automticas, pero no desaparecen cuando se termina la funcin, es decir, conservan su valor. El siguiente ejemplo demuestra lo anterior: Ej.:
#include <stdio.h> imprime() main() { int i=0; for (i=1; i<4; i++) imprime(); } imprime() { int local=1; static int varstatic=1; printf("\nlocal= %d varstatic=%d",local,varstatic); local++; varsta++; } Salida por pantalla => local=1 local=1 local=1 varstatic=1 varstatic=2 varstatic=3

Como ya sabemos la variable local local pierde su valor y por lo tanto cada vez que es llamada la funcin se inicializa. En el caso de varstatic, la primera vez se inicializa, pero posteriormente se pasa por alto dicha inicializacin y mantiene el ltimo valor asignado.

Variables estticas externas Estas son variables globales declaradas como estticas y su alcance es solamente el archivo donde fue declarada. Supongamos que tenemos dos archivos uno.c y dos.c, en el primero declaramos dos variables globales:
# include<stdio.h> int general; static int enarchivo; main() { : : }

La variable general es conocida en todas las funciones del archivo uno.c y dos.c, la variable enarchivo es conocida solamente en las funciones del archivo uno.c.

Profesor: Roberto Uribe P.

Pg. N 112

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Captulo N 7 : Punteros en C Los punteros (o apuntadores) son una de las herramientas ms poderosas de C, sin embargo en este caso, poder implica peligro. Es fcil cometer errores en el uso de punteros, y estos son los ms difciles de encontrar, una expresin tpica usada en este caso por los programadores se refiere a la "perdida de un puntero", lo cual indica que ocurri un problema en la asignacin de algn puntero. La ventaja de la utilizacin de punteros en C es que mejora enormemente la eficiencia de algunos procesos, adems , permite la modificacin de los parmetros pasados a las funciones (paso de parmetros por referencia) y son usados en los procesos de asignacin dinmica de memoria. Puntero es una representacin simblica de una direccin de memoria, es decir, contiene la direccin de un objeto o variable. Operador & Contiene la direccin o posicin de memoria en la cual se ha almacenado una variable. El operador & es unuario, es decir, tiene un solo operando, y devuelve la direccin de memoria de dicho operando. Supongamos el siguiente ejemplo:
main() { int auxiliar=5; printf("\nauxiliar=%d --->direccin=%p",auxiliar,&auxiliar); } por pantalla => auxiliar=5 ---> direccin=289926.

En este ejemplo se utiliz el modificador de formato %p que muestra la direccin segn el formato del computador usado. Hasta ahora no haba importado el lugar donde se almacenaban los datos. Los punteros se pueden declarar en los programas para despus utilizarse y tomar las direcciones como valores. Por ejemplo:
int *punt; int j=5; /* un apuntador a int */

Se declaro un apuntador punt a int, es decir, el contenido del puntero es una direccin que apunta a un objeto de tipo entero. Si se hiciese la siguiente asignacin:
punt=&j;

estara correcta e implicara que punt apunta a la direccin de memoria de la variable j. Grficamente sera:

Profesor: Roberto Uribe P.

Pg. N 113

Programacin de Computadores y el Lenguaje C

(versin 2003)

Direccines de Memoria

5001

5002 5006

5003

5004

5005

5006 5

5007

5008

punt (apunta a la dir. 5006 que guarda un int)

j (variable int que contiene el dato 5)

entonces, el valor de punt y &j sera 5006. Los punteros pueden ser inicializados, para ello existen varias formas:
punt=NULL; punt=&j; punt=(int *) 285395;

/* asignacin de direccin */ /* absoluta */

En la primera lnea se le asigna un nulo, es como decir que apunta a ninguna parte. En la tercera lnea se hace la asignacin de una posicin especifica de memoria. Entonces, para declarar un puntero, primero se especifica el tipo de dato (bsico o creado por el usuario), luego el nombre del puntero precedido por el caracter *. Operador * El operador * es unuario y toma a su operando como una direccin de memoria, entonces el operador accesa al contenido de esa direccin. Por ejemplo, suponga las variables declaradas anteriormente y la asignacin,
int *punt; int j=5; punt=&j;

entonces, si imprimimos en pantalla:


printf("El contenido de punt es: %d",*punt);

imprimira:
El contenido de punt es: 5

con esto se imprimi el contenido de la direccin a la que apunta punt. Habra sido igual haber impreso la variable j. Si se declarara otra variable int, igualmente es valido hacer:
int *punt; int j=5,otro; punt=&j; : : otro=*punt;
Profesor: Roberto Uribe P. Pg. N 114

Universidad de Magallanes - Departamento de Ingeniera en Computacin

que asignara a otro el dato 5. Si se hace la siguiente asignacin:


*punt=200;

se modifica el contenido de la direccin a la que apunta punt. Por lo tanto tambin se modific la variable j, ya que la direccin de esta es a la que apunta punt. Hay ciertas restricciones en la asignacin de punteros, por ejemplo:
int *p,*q,*r; /* 3 punteros a entero*/ int array[20],var1; register int j; p=&j; q=568200; r=&array; p=&(var1+5);

Todas las asignaciones anteriores estn errneas. A un puntero no se le puede asignar la direccin de una variable register, de hecho, porque esta est almacenada en un registro de la CPU. A un puntero no se le puede asignar un valor cualquiera si no existe una conversin explcita de tipo. No puede recibir la direccin de un nombre de un arreglo dado que este ltimo es un puntero al primer elemento del arreglo. La ltima asignacin tambin es ilegal ya que se pretende asignar la posicin de var1 mas 5 posiciones de memoria. Las siguientes asignaciones estn correctas:
int *p,*q; int array[20],var1; p=NULL; q=&array[5]; p=q;

Primero a p se le asigno el valor nulo, luego a q se le asigno la direccin del sexto elemento del arreglo y finalmente a p se le asigno la misma direccin que q, por lo tanto apuntan a la misma posicin. Hasta ahora se ha ocupado implcitamente punteros en nuestros programas, ejemplo de ello es al ocupar scanf, donde pasamos como parmetro la direccin de la variable, tambin, en arreglos, como el caso de cuando es pasado a una funcin y sus valores resultan modificados.

Paso de parmetros por referencia Sabemos que cuando se pasa como parmetro una variable a una funcin, esta no logra modificar el valor de la variable, eso es dado que fue pasada por valor. Para lograr que se modifique el contenido de una variable debe pasarse por referencia, para ello se pasa a la funcin la direccin de la variable y no el dato.
Profesor: Roberto Uribe P. Pg. N 115

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejercicio N 7.1: Supongamos que se desea hacer una funcin que haga el intercambio de datos entre dos variables (swap). Solucin: Primero hagamos el programa principal, de tal manera de saber como se hace la llamada por referencia. Este podra ser:
#include <stdio.h> void swap(); /*funcion para el intercambio*/ main() { int a=100,b=200; printf("a=%d b=%d",a,b); swap(&a,&b); printf("a=%d b=%d",a,b); }

Nuestro programa resulta bastante simple, lo importante es notar que ahora los parmetros a y b van precedidos de el operador &, es decir, no se pasan los datos 100 y 200, sino, las direcciones de las variables. Ahora, como a la funcin se le pasaron direcciones de variables int, entonces en la cabecera de la funcin deben declararse parmetros como punteros a int. Esto sera:
void swap(int *x,int *y)

Dentro de nuestra funcin lo que tenemos que hacer es intercambiar los valores. Como los parmetros son punteros, entonces debemos trabajar con los contenidos de dichos punteros (o los contenidos de las direcciones a la que apuntan los punteros), para ello utilizamos el operador asterisco. La funcin completa es:
void swap(int *x,int *y) { int aux; aux=*x; *x=*y; *y=aux; }

Con esto logramos nuestro objetivo, la salida al programa es:


a=100 a=200 b=200 b=100

Ejercicio N 7.2: Cree un programa que lea dos nmeros flotantes, luego una funcin que tenga dos parmetros y salga el mayor en el primer parmetro y el menor en el segundo. Solucin: El programa principal sera:
#include <stdio.h> void maxymin(int *x,int *y); main() { int i,j; scanf("%d",&i);
Profesor: Roberto Uribe P. Pg. N 116

Universidad de Magallanes - Departamento de Ingeniera en Computacin

scanf("%d",&j); maxymin(&i,&j); printf("El Max es i=%d, El Min es j=%d",i,j); return 0; }

La funcin no variara mucho respecto al ejercicio anterior:


void maxymin(int *x,int *y) { int aux; if (*x<*y) { aux=*x; *x=*y; *y=aux; } return; }

En el if se pregunto si "el contenido del puntero x es menor que el contenido del puntero y". En esta funcin podramos utilizar la funcin anterior swap para hacer el cambio. En ese caso, aparte de incluir la declaracin de dicha funcin antes del main, maxymin queda:
void maxymin(int *x,int *y) { int aux; if (*x<*y) swap(&*x,&*y); }

Hay que notar que al hacer &*x hablamos de la direccin del contenido del puntero x. Esto se hace utilizando la misma lgica de pasar la direccin. Sin embargo, hablar de &*x es hablar de x, en otras palabras, si decimos que "el dato 120 (por ejemplo) esta almacenado en la direccin x" ,es lo mismo que "el dato *x esta almacenado en x o en &*x". Entonces la llamada a swap puede ser hecha como:
if (*x<*y) swap(x,y);

Lo que cumple con pasar las direcciones de las variables a las funciones, esto ya en este caso los parmetros de por si son direcciones (punteros). Nota: Supongamos las siguientes sentencias:
int a=10,*p; p=&a;

es posible imprimir:
printf("%d",*&a); printf("%p",&*p); printf("%p",&p);

Profesor: Roberto Uribe P.

Pg. N 117

Programacin de Computadores y el Lenguaje C

(versin 2003)

es decir, en la primera lnea se imprime "el contenido de la direccin &a" que es lo mismo que imprimir a, pero, no se puede imprimir &*a, esto provocara un error. En la segunda lnea es igual a imprimir p. En la tercera se imprime la direccin donde esta almacenado el puntero p. Aritmtica de Punteros Las operaciones matemticas que se pueden usar con punteros es el decremento, incremento y resta entre dos punteros, es resto de las operaciones quedan prohibidas. La operatoria de punteros queda sujeta al tipo base de este, por ejemplo:
int *q,dato; q=&dato; q++;

En este caso si el puntero q apunta a la direccin 30000, el incremento apuntara q a la direccin 30002. Esto ya que un entero tiene 2 bytes de largo y el incremento hace que se apunte al siguiente entero. Lo mismo ocurrira con q--. Si a q se le incrementa en 20 hara que q apuntara al vigsimo entero que est despues de la posicin original del puntero. Suponga el siguiente ejemplo:
int *p,arreglo[20],i; : : p=&arreglo[0]; for(i=0;i<20;i++) { printf("%d",*p); p++; }

En este caso se imprime todo el arreglo arreglo utilizando el puntero p. Esto es efectivo dado que al declarar el arreglo, sus elemento se ubican en posiciones contiguas de memoria. Tambin sera correcto utilizar
p=&arreglo[0]; printf("El decimo elemento es : %d",*(p+9));

para referirnos al dcimo elemento del arreglo. Como hay que tener cierto cuidado con el manejo de punteros, veamos este ejemplo:
int *p,arreglo[20],i; : : p=&arreglo[0]; for(i=0;i<20;i++) { printf("%d",*p); p++; } printf("El decimo elemento es : %d",*(p+9));

Este es similar al anterior, sin embargo, no hace lo que supuestamente queremos, porque?, la razn es que el puntero fue incrementado 20 veces y despues del for ya no apunta al primer elemento del arreglo, por lo tanto puede imprimir cualquier valor (que sera aquel ubicado 9 variables enteras ms all).
Profesor: Roberto Uribe P. Pg. N 118

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Tambin es posible hacer la resta entre dos punteros, esto con el objeto de saber cuantos datos del tipo base (de los punteros) se encuentran entre ambos. Igualmente se puede hacer la comparacin entre punteros:
if (p>q) printf("\np es mayor que q\n");

En este caso indicara que p esta ubicado en una posicin de memoria superior a la de q. Algo ms sobre punteros Los punteros no solamente pueden apuntar a tipos conocidos, sino que tambin a tipos creados por el usuario, como es el caso de punteros a estructuras. Podemos mencionar adems que un uso frecuente de estos son en estructuras de datos para trabajar con listas enlazadas, arboles, etc., sin embargo esto ltimo no corresponde verlo en este libro. Otro ejemplo de uso de punteros es cuando un arreglo es definido como un arreglo de punteros, por ejemplo, la siguiente declaracin crea un arreglo de punteros de 5 elementos:
int *arrepunt[5];

donde cada una de las componentes del arreglo es un puntero a entero. Entonces, sentencias como las siguientes son correctas:
arrepunt[0]=&var1; printf("\n%d",*arrepunt[0]);

entonces, al primer elemento del arreglo se le asign la direccin de la variable entera var1, posteriormente se imprimi el contenido de dicho puntero.

malloc, free y sizeof Muchas veces en nuestros programas necesitaremos ocupar memoria en el momento en que este se est ejecutando, para ello existen dos funciones malloc y free. La primera, pide memoria del conjunto de memoria disponible, free hace lo contrario, devuelve la memoria pedida para que pueda ser ocupada posteriormente. Estas funciones se encuentran en la librera llamada stdlib.h y son la base de la asignacin dinmica de memoria en C. Por ejemplo, si creamos un puntero a char y en algn momento necesitamos memoria para guardar algn dato, se puede hacer:
char *p1; : p1=malloc(20);

lo que nos permitir crear 20 lugares de memoria para guardar datos, y p1 quedara apuntando al primero de ellos. El parmetro pasado es un entero, pero en realidad el tipo
Profesor: Roberto Uribe P. Pg. N 119

Programacin de Computadores y el Lenguaje C

(versin 2003)

definido en stdlib.h es size_t que es parecido a un unsigned int. El prototipo de la funcin malloc es la siguiente:
void *malloc(size_t cantidad_de_bytes)

El valor devuelto por malloc es un puntero (void *) que se convierte a el tipo de puntero de la parte izquierda de la asignacin. Sin embargo, para evitar problemas de portabilidad lo ideal es hacer la conversin explcita, de la forma:
p1=(char *)malloc(20);

que convierte lo retornado por malloc a un puntero a char. Para devolver la memoria solicitada, la instruccin sera:
free(p1);

En el ejemplo anterior un char ocupa un byte, no es problema pedir espacio para 20 char, sin embargo, si el puntero fuese entero, se tiene que multiplicar la cantidad pedida por el tamao en bytes de un entero que es 2, entonces, si no sabemos el largo en bytes de un tipo o de una variable se nos complicara pedir memoria, adems que, dependiendo el computador los tipos podran tener diferente largo. Para resolver estos problemas y para hacer nuestro programa ms portable existe el operador en tiempo de compilacin llamado sizeof (tamao de) que retorna el tamao en bytes del parmetro ingresado, que puede ser una variable o un identificador de tipo. Por ejemplo, si deseramos imprimir el tamao (en bytes) de un entero, lo correcto sera hacer:
printf("%d",sizeof(int));

Suponga lo siguiente:
int a,matriz[20][10]; double var33; : printf("%d",sizeof(var33)); printf("%d",sizeof(matriz)); printf("%d\t\t%d",sizeof(a),sizeof(int)); :

Imprimira el tamao de las variables var33, matriz (que sera 20*10*el largo de un entero) y el tamao del tipo entero. En el ejemplo, slo es obligatorio utilizar parntesis cuando se pregunta el tamao de un tipo. Con lo anterior podramos crear memoria para un puntero a enteros usando
int *p2; p2=(int *)malloc(10*sizeof(int));

lo que creara espacio para 10 enteros (y p2 apuntara al primero de ellos).

Profesor: Roberto Uribe P.

Pg. N 120

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Un ejercicio grfico El siguiente ejercicio pretende mostrar grficamente que ocurre con las variables y punteros durante la creacin y asignacin.

int *p; int z;

??

??

despues de la declaracin anterior, es decir, crea una variable entera z la cual tiene su espacio en memoria, aunque su valor es desconocido (basura). Adems, una variable puntero p (a int) la cual an no tiene espacio asignado (para contener valores) y no apunta a ningura parte.

z=100;
p z

?? p=&z;

100

100

Despues de estas asignaciones, la variable z contiene el valor 100 y la variable p apunta a la direccin donde est z. Entonces, recin ahora se puede hablar del contenido de p, es decir, si se ejecuta:
printf(%d,*p);

Se imprime el valor 100. Si despus,


p=NULL;
p z

100

NULL

Donde NULL es la forma de representar que el puntero apunta a nada. En la figura se muestra como barras paralelas decreciendo en tamao. Si luego se hace:
p=(int *)malloc(sizeof(int));
Profesor: Roberto Uribe P. Pg. N 121

Programacin de Computadores y el Lenguaje C

(versin 2003)

se crea el espacio necesario en memoria para guarda un valor entero, a la que apuntar la variable p, a este valor slo se puede accesar a travs de p. Grficamente:
p z

100

??

*p=150;

100

150

Despus de esta asignacin, el contenido de p es igual a 150, y z an mantiene el valor 100. Si ahora hacemos nuevamente:
p=&z;
p z

100

150

Con esto, en nuestra jerga diriamos que: se nos perdio un puntero. En realidad, formalmente p no est perdido, si no que ahora apunta a z, pero nos es imposible recuperar el valor que tena antes. Como se muestra en la figura, no hay ninguna forma de acceder al espacio de memoria que contiene el valor 150, siendo que ese espacio sigue ocupado. Si despus de esto, se ejecuta la siguiente linea:
*p=200;

Profesor: Roberto Uribe P.

Pg. N 122

Universidad de Magallanes - Departamento de Ingeniera en Computacin

ocurre lo siguiente:
p z

200

150

Entonces, ahora, tanto z como el contenido de p tienen el valor 200. Finalmente, si:
printf(%d %d,z,*p);

imprimira en pantalla:
200 200

Un ltimo comentario es recalcar que lo que almacena p, es una direccin de memoria, es decir, la direccin de memoria a la que est apuntando, en los esquemas anteriores esta se representa a travs de la flecha

Profesor: Roberto Uribe P.

Pg. N 123

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Propuestos 1.Para el siguiente extracto de programa:


int *p,arreglo[6],i; : : /* datos del arreglo: 5 4 56 32 21 50 */ p=arreglo; for(i=0;i<6;i++) { printf("%d",*p); printf("%p",p); p++; }

a) Indique que hace el programa. b) Si el primer elemento del arreglo esta ubicado en la posicin de memoria 13500, entonces, a que direccin de memoria queda apuntando p al finalizar el ciclo for?, escriba cada valor que va saliendo por pantalla.

2.Escriba un programa que lea 100 nmeros enteros y los almacene en un arreglo. Luego escriba una funcin que entregue a la funcin principal el valor mximo y mnimo, para ello ocupe parmetros pasados por referencia (a la funcin se le pasan tres parmetros: el arreglo y dos pasados por referencia que contendrn el mximo y mnimo).

3.Escriba un programa que ingrese primero 2 datos (x,y) y que calcule la potencia de x elevado a y, luego un tercer dato (z) para el cual se calcular el factorial. La potencia y el factorial deben ser funciones a las cuales se le pasan parmetros por referencia. Los datos (x,y,z) deben ser ledos desde el programa principal.

Profesor: Roberto Uribe P.

Pg. N 124

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Captulo N 8 : typedef, struct y union

Typedef El lenguaje C dispone de un mecanismo denominado typedef que se utiliza para redefinir tipos otorgndoles nuevos nombres, esto permite entre otras cosas que las mantenciones futuras del programa sean ms fciles, tambin permite una mayor transportabilidad entre diferentes mquinas y evitar posibles problemas con los tipos de datos. El formato para typedef es:
typedef <tipo> <nuevo_tipo>;

Ejemplo:

typedef int enteros;

En este caso se redefini el tipo int, de esta manera el nuevo tipo enteros es ms descriptivo. Entonces, con lo anterior podemos declarar variables usando enteros. Por ejemplo, las siguientes declaraciones
enteros a,b,c=5; enteros arra[20];

crean variables de tipo int, tres variables y un arreglo de 20 elementos. Ejemplo:


# define N 50 /* define una const. N=50 */ typedef float arrfloat[N]; . . . main() { arrfloat numeros,otronum[N]; : : numeros[i]=5.05; /*asignacion valida*/ : }

En el ejemplo anterior se defini un nuevo tipo que es un arreglo de flotantes, es decir, en la declaracin que esta dentro del main, la variable numeros es un arreglo de 50 y la variable otronum es un arreglo de 50 por 50. Por ejemplo, para inicializar en 0 al arreglo otronum, se hace de la manera conocida:
for(i=0;i<N;i++) for(j=0;j<N;j++) otronum[i][j]=0.0;

Profesor: Roberto Uribe P.

Pg. N 125

Programacin de Computadores y el Lenguaje C

(versin 2003)

Estructuras Las estructuras son conjuntos de una o ms variables que pueden ser de igual o distinto tipo (En Pascal se llaman register --> registro). La idea de agrupar datos en estructuras es para relacionar ms adecuadamente esos datos. Por ejemplo, si deseramos mantener en un programa los datos personales de un individuo, primero tendramos que identificar los atributos de inters, como ser nombre, apellido, edad, fono, etc. Luego, crear una variable para cada atributo (eso con los conocimientos adquiridos hasta ahora). Finalmente hacer las operaciones. Las estructuras nos permiten trabajar dichos datos como una sola variable. Para definir una estructura se hace de la siguiente manera:
struct <nombre_estructura> { <tipo> <nombre_campo1>; <tipo> <nombre_campo2>; : : }[lista de variables];

Entonces, para el ejemplo anterior podramos definir la siguiente estructura:


struct persona { char nombre[30]; char apellido[30]; int edad; long fono; };

La palabra clave struct declara una estructura, el identificador persona es el nombre de la estructura y puede ser utilizado en declaraciones posteriores. Cada elemento de la estructura se conoce como "miembro" o "campo". Al final de la llave pueden ir identificadores que sern variables del tipo indicado (struct persona); esto reserva memoria para cada una de las variables. Ejemplo:
struct persona { char nombre[30]; char apellido[30]; int edad; long fono; }pers1,pers2;

Tambin se pueden declarar variables locales como:


: : main() { struct persona persona3;
Profesor: Roberto Uribe P. Pg. N 126

Universidad de Magallanes - Departamento de Ingeniera en Computacin

struct persona persona4={"Rene","Mancilla",18,222120L}; . . . }

En la segunda declaracin (persona4), se inicializ con datos. En trminos reales una estructura define un nuevo tipo de dato, y por lo tanto pueden aplicrsele todo lo visto para los tipos de datos bsicos, como ser: crear arreglos de estructuras, punteros a estructuras, estructuras como parmetros a funciones, etc. Para referirse a un miembro de una estructura se hace de la siguiente manera:
<nombre_estructura>.<nombre_miembro>

Por ejemplo, para ingresar datos va teclado a la variable persona3, sera:


: : printf("\nIngrese datos"); printf("\nNombre :"); scanf("%s",persona3.nombre); printf("\nApellido:"); scanf("%s",persona3.apellido); printf("\nEdad :"); scanf("%d",&persona3.edad); printf("\nFono :"); scanf("%ld",&persona3.fono); : :

Es decir, de la misma manera que si fuese cualquier variable. Lo nico a considerar es en el caso de leer el campo nombre (arreglos), si este se leyera caracter a caracter el subndice se asocia a el miembro y no a la variable struct. Osea, la forma correcta sera:
for(i=0;i<30;i++) scanf("%c",persona3.nombre[i]);

y no,
scanf("%c",persona3[i].nombre);

que sera un error, ya que se estara hablando del miembro nombre de la componente i de un arreglo llamado persona3.

Arreglos de estructuras Comnmente las estructuras se llaman registros, en la vida real estos registros se agrupan, es decir, usualmente en nuestras aplicaciones necesitamos conjuntos de datos y no solamente datos independientes, ejemplo de esto es, una lista de empleados, una lista de clientes, una lista de cuentas corrientes, etc. Cada uno de estos conjuntos agrupan a n registros (estructuras) y cada registro contiene datos particulares que caracterizan al elemento.
Profesor: Roberto Uribe P. Pg. N 127

Programacin de Computadores y el Lenguaje C

(versin 2003)

Como cualquier otro tipo, se pueden crear arreglos donde cada una de sus componentes sea una estructura. Por ejemplo, se podra crear un arreglo para mantener una lista de nombres de personas. Usando la estructura anterior, esto podra ser:
: main() { struct persona individuos[100]; :

/* para 100 personas */

y luego referirnos a alguna componente como:


individuos[0].nombre

para hablar del miembro nombre de la persona ubicada en la posicin 0 del arreglo. Un arreglo de estructuras se maneja como cualquier otro arreglo. Estos conjuntos de datos los encontramos con el nombre de Bases de Datos, aunque formalmente cada conjunto de datos es una Tabla que forma parte de una Base de Datos. Nos podemos imaginar que una Tabla es un archivo en nuestro disco duro, sin embargo, como an no poseemos los conocimientos para trabajar con archivos en C, podemos trabajar con los datos en memoria, a travs de arreglos.

Ejercicio N 8.1: Crear un programa que permita mantener una lista con los datos de los obreros de una empresa, para ello suponga que el mximo de obreros es de 40. Adems, agregue los datos correspondientes a, nmero de horas extra que hace en el mes, el valor por hora extra que se le paga a cada obrero y el total de sobresueldo (horas extra por valor hora). Realice las siguientes operaciones: Ingresar el total de datos para los 40 obreros, luego imprima una lista resumida de los datos (slo nombre, horas extra, valor por hora y total). Solucin: Como se pide una lista de 40 obreros podemos crear una estructura que contenga los atributos importantes de los obreros, luego declarar un arreglo de 40 para contener todos los registros necesarios.

#include <stdio.h> #define MAX 40 struct obrero /* definicion de estructura */ { char nombre[30]; /*incluido apellido*/ char direccion[30]; int hextra; /*Horas Extras*/ int hvalor; /*Valor por Hora*/ long total; /*hextra*hvalor*/ }; main() { struct obrero personal[MAX]; int i=0; for (i=0;i<MAX;i++)
Profesor: Roberto Uribe P. Pg. N 128

Universidad de Magallanes - Departamento de Ingeniera en Computacin

{ printf("Nombre :"); scanf("%s,personal[i].nombre); printf("\nDireccion :"); scanf("%d",personal[i].direccin); printf("\nHoras Extras :"); scanf("%d",&personal[i].hextra); printf("\nValor Hora :"); scanf("%d",&personal[i].hvalor); printf("\n\n); personal[i].total=personal[i].hextra*personal[i].hvalor; } system("clear") /*llamada al comando de 'borrar pantalla' en Unix*/ printf("\nNombre\t\tHoras\t\tValor\t\tTotal\n") for (i=0;i<MAX;i++) { printf("%s",personal[i].nombre); printf("\t\t%d",personal[i].hextra); printf("\t\t%d",personal[i].hvalor); printf("\t\t%d",personal[i].total); } return 0; }

Una modificacin a nuestro programa para reemplazar struct obrero en las declaraciones es usar typedef para renombrar el tipo. Para esto hay que agregar la sentencia despues de la definicin de la estructura y colocar por ejemplo:
nuevo tipo typedef struct obrero empleados; tipo

y con esto se puede usar el tipo empleados en vez del tipo struct obrero. Entonces, en el main la declaracin del arreglo personal puede ser reemplazada por:
empleados personal[MAX];

En este ejercicio, se podra haber utilizado funciones para las operaciones, de esta manera el programa es ms modular. Por ejemplo, el llenado del arreglo podra ser:
void llenar(empleados perso[MAX]) { int i=0; for (i=0;i<MAX;i++) { printf("Nombre :"); scanf("%s,perso[i].nombre); printf("\nDireccion :"); scanf("%d",perso[i].direccin); printf("\nHoras Extras :"); scanf("%d",&perso[i].hextra); printf("\nValor Hora :"); scanf("%d",&perso[i].hvalor); printf("\n\n); perso[i].total=perso[i].hextra*perso[i].hvalor; } }

Profesor: Roberto Uribe P.

Pg. N 129

Programacin de Computadores y el Lenguaje C

(versin 2003)

entonces, la llamada a esta funcin desde el main es:


llenar(personal);

Note que el parmetro pasado a la funcin es todo el arreglo de estructuras, es por eso que cada uno de sus componentes sale modificado, si se hubiese pasado a la funcin cada componente tendramos que haber usado parmetros pasados por referencia. Ejercicio N8.2: Para el ejercicio anterior, crear una funcin que permita responder la siguiente pregunta, dado el nombre de un obrero Cual es el sobresueldo que obtiene este mes?. Supongamos que el nombre se ingresa fuera de esta funcin, entonces este es un parmetro que ingresa a dicha funcin. Solucin: Con lo planteado en el ejercicio, entonces entendemos que los parmetros que se pasan a la funcin son el string que contiene el nombre ingresado y el arreglo personal, esto ltimo ya que este es local (al main). Entonces la cabecera de nuestra funcin sera:
void busca(empleados personal[MAX],char *nom)

El algoritmo principal que hay que implementar dentro de la funcin es el buscar un obrero especfico, esto implica que cada obrero del arreglo debe compararse con el nombre ingresado. Lo anterior significa que hay que recorrer el arreglo, es decir, necesitamos un for. Para comparar dos string podemos usar la funcin strcmp de la librera string.h. Entonces, nuestra funcin completa quedara:
void busca(empleados personal[MAX],char *nom) { int i; for (i=0;i<MAX;i++) { if (strcmp(personal[i].nombre,nom)==0) { printf("\nEl obrero %s tiene un sobre sueldo de %ld\n", personal[i].nombre,personal[i].total); return; /*para terminar la funcion cuando el nombre es encontrado*/ } } printf("\nError, el nombre no existe\n"); return; } Recuerde que el pasar el parmetro nom como char *nom, es decir como puntero, implica que el tamao del string nom es el tamao del string que fue pasado en la llamada a la

funcin. Ejercicio N 8.3: Una aplicacin que sera de inters realizar y que es muy comn en los sistemas de bases de datos es el ordenamiento de los datos segn algn atributo. Entonces, para el ejercicio 14 hacer una funcin a la cual se le pase como parmetro el arreglo de datos y esta realice el ordenamiento por nombre del obrero. Solucin: Como la informacin esta contenida en un arreglo y conocemos el mtodo de ordenamiento llamado burbuja, poseemos entonces lo necesario para implementar la funcin. La nica diferencia con el mtodo anteriormente visto, es que ahora las comparaciones de los
Profesor: Roberto Uribe P. Pg. N 130

Universidad de Magallanes - Departamento de Ingeniera en Computacin

subndices del arreglo se deben hacer utilizando las funciones de string.h, ya que los elementos a comparar son strings.
void ordena(empleados personal[MAX]) { int i=0,j=0,auxext,auxval; long auxtot; char aux[30]; for(i=0;i<(MAX-1);i++) for(j=i+1;j<MAX;j++) if (strcmp(personal[i].nombre,personal[j].nombre)>0) { strcpy(aux,personal[i].nombre); /*intercambia nombre*/ strcpy(personal[i].nombre,personal[j].nombre); strcpy(personal[j].nombre,aux); strcpy(aux,personal[i].direccion); /*intercambia direccion*/ strcpy(personal[i].direccion,personal[j].direccion); strcpy(personal[j].direccion,aux); auxext=personal[i].hextra; /*intercambia hextra*/ personal[i].hextra=personal[j].hextra; personal[j].hextra=auxext; auxval=personal[i].hvalor; /*intercambia hvalor*/ personal[i].hvalor=personal[j].hvalor; personal[j].hvalor=auxval; auxtot=personal[i].total; /*intercambia total*/ personal[i].total=personal[j].total; personal[j].total=auxtot; } return; }

Como en los casos anteriores el arreglo sale modificado. Note que se usaron las funciones strcmp para comparar y strcpy para copiar.

Algo ms sobre estructuras Cuando se declara una variable de un tipo estructura, sus miembros se ubican en posiciones contiguas de memoria. Sobre estructuras tambin se puede aplicar el operador tamao de, los siguientes ejemplo son correctos:
printf("%d",sizeof(empleados)); printf("%d",sizeof(personal));

En la primera sentencia se imprimira el tamao en bytes del tipo empleados (al menos 30+30+2+2+4). En la segunda sentencia se imprime el tamao de todo el arreglo de estructuras.

Estructuras Anidadas Se produce un anidamiento de estructuras cuando el miembro de una estructura es otra.

Profesor: Roberto Uribe P.

Pg. N 131

Programacin de Computadores y el Lenguaje C

(versin 2003)

Ejemplo:
#include <stdio.h> #define N 50 #define LARGO 30 struct fecha { int dia; int mes; int anho; }; struct identifica { char nombre[LARGO]; char apellido[LARGO]; struct fecha fnac; char direccion[LARGO]; /*...*/ char ciudad[LARGO]; }; struct obrero{ struct identifica datos; long sueldobase; }; main() { struct fecha auxdia,otrodia={1,1,1990}; struct identifica auxperson; struct obrero listado[N]; : : }

En este caso se definieron tres estructuras, donde las dos ltimas contienen un miembro que es una estructura. Para referirse al miembro de una estructura que a su vez es otra se usa igualmente el operador punto. Por ejemplo:
auxdia.anho auxperson.fnac.dia listado[i].datos.fnac.dia

En el primer caso se habla del miembro anho de la variable auxdia, en el segundo del miembro dia del miembro fnac de la variable auxperson. En el ltimo caso, como nos referimos a un arreglo hablamos del campo dia del miembro fnac del miembro datos de la componente i del arreglo listado. Entonces, para llenar de valores a la estructura auxperson se debe hacer:
scanf("%s",auxperson.nombre); scanf("%s",auxperson.apellido); scanf("%d",&auxperson.fnac.dia); scanf("%d",&auxperson.fnac.mes); scanf("%d",&auxperson.fnac.anho); : :

Profesor: Roberto Uribe P.

Pg. N 132

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Funciones y Estructuras En las actuales versiones de C se permiten realizar ciertas operaciones que en versiones anteriores no, como por ejemplo hacer la asignacin directa de una estructura a otra, pasar como parmetro a una funcin una estructura completa y que una funcin retorne un tipo estructura. Para el caso de la asignacin, la copia se realiza miembro a miembro. Suponga que existe una variable pers2 del tipo struct identifica, en el siguiente ejemplo se realiza la asignacin de auxperson a pers2.
pers2=auxperson;

Tambin se puede hacer la copia de un solo miembro,


strcpy(pers2.nombre,auxperson.nombre);

Para ver el paso de una estructura como parmetro y el retorno de una estructura, revisemos el siguiente ejemplo:
#include <stdio.h> #include <string.h> struct obrero{ char nombre[30]; int edad; long fono; }; void muestra(struct obrero x); struct obrero asigna(); main() { struct obrero aa,bb={"Perico",28,226368L}; /* L al final indica que es long*/ muestra(bb); aa=asigna(); muestra(aa); return 0; } void muestra(struct obrero x) { printf("\nNombre : %s",x.nombre); printf("\nEdad : %d",x.edad); printf("\nFono : %ld\n",x.fono); return; } struct obrero asigna() { struct obrero x; scanf("%s",x.nombre); scanf("%d",&x.edad); scanf("%ld",&x.fono); return(x); }
Profesor: Roberto Uribe P. Pg. N 133

Programacin de Computadores y el Lenguaje C

(versin 2003)

obrero

La novedad de este ejemplo es que una funcin retorna un variable de tipo struct que a su vez es asignada a la variable del mismo tipo aa. La funcin muestra slo imprime los valores del parmetro en pantalla.

Punteros a Estructuras Otra forma de asignarle valores a una estructura es que los valores se asignen dentro de la funcin, para ello debemos usar parmetros por referencia, es decir, pasar la direccin de memoria de la estructura, por ejemplo, nuestra funcin asigna puede ser llamada de la siguiente manera:
asigna(&aa);

entonces, debera ser declarada anteriormente como


void asigna();

En la cabecera de la funcin debemos declarar el parmetro como un puntero a una estructura, es decir,
void asigna(struct obrero *est)

donde est es un puntero. Dentro de la funcin debemos utilizar el contenido de la variable. Para hacer ms entendible declararemos una variable auxiliar y luego copiaremos los datos.
void asigna(struct obrero *est) { struct obrero x; scanf("%s",x.nombre); scanf("%d",&x.edad); scanf("%ld",&x.fono); strcpy((*est).nombre,x.nombre); (*est).edad=x.edad; (*est).fono=x.fono; return; }

Como sabemos, para hablar del contenido de un puntero utilizamos el operador *, sin embargo, no podemos hacer:
*est.edad

ya que sera un error, esto debido a que el operador punto tiene mayor prioridad que el operador asterisco, por ello se utilizan los parntesis. En el caso anterior, se estara hablando del contenido del miembro edad de la variable est, es decir, edad debera ser un puntero, y eso no es as. Para simplificar nuestra funcin slo bastaba hacerla de la siguiente manera:
Profesor: Roberto Uribe P. Pg. N 134

Universidad de Magallanes - Departamento de Ingeniera en Computacin

void asigna(struct obrero *est) { scanf("%s",(*est).nombre); scanf("%d",&(*est).edad); scanf("%ld",&(*est).fono); return; }

Es posible reemplazar
(*est).edad

por
est->edad

donde, el operador -> reemplaza el formato anterior. Este operador es comnmente llamado operador flecha y se construye con el signo menos seguido del signo mayor que.

Algo ms sobre punteros a estructuras Supongamos que se declara un puntero a la estructura fecha definida anteriormente, como fue indicado debe usarse el operador flecha para referirse a sus miembros:
: struct fecha *f; : f->dia=10; f->mes=06; f->anho=1968; :

Entonces, la siguiente sentencia:


++f->dia;

incrementa el miembro dia, es decir, sera equivalente a escribir:


f->dia=f->dia+1;

o
++(f->dia);

En cambio, la sentencia
(++f)->dia;

incrementara el puntero f, es decir, f apuntara a la siguiente direccin de memoria donde exista una variable de tipo struct fecha, en la componente dia. Suponga ahora que tenemos las siguientes definiciones antes del main
Profesor: Roberto Uribe P. Pg. N 135

Programacin de Computadores y el Lenguaje C

(versin 2003)

: : struct fecha { int dia; int mes; int anho; }; typedef struct fecha *puntfec; :

si dentro del main declaramos una variable como:


main { puntfec f2; :

entonces f2 es un puntero a la estructura fecha, formalmente es una variable del tipo puntfec (que es un puntero), y por lo tanto debe manejarse como lo visto anteriormente. Si hicisemos la siguiente declaracin,
puntfec *f3;

entonces, f3 es un puntero al tipo puntfec que a su vez en un puntero. En otras palabras f3 es un puntero a un puntero a fecha. Por lo tanto, para referirnos a el contenido de f3 debemos usar el operador *, esto tomando en cuenta la prioridad del operador flecha (que es mayor). Osea,
(*f3)->anho

para referirnos al miembro ao de la variable.

Uniones (unin) Una unin es una variable que permite almacenar tipos de datos distintos en el mismo espacio de memoria. La sintaxis de una variable unin es idntica a una variable struct. Ej.:
union unica { int entero; float flotante; char caracter; };

Las declaraciones son de la siguiente forma:


union unica valores; union unica arrunion[5]; union unica *ptrunion;

La idea es que el compilador guarda espacio para almacenar la mayor de las alternativas, es decir, el tamao en bytes del miembro que ocupa ms espacio, en este caso, el tamao para un float. S
Profesor: Roberto Uribe P. Pg. N 136

Universidad de Magallanes - Departamento de Ingeniera en Computacin

int es de 2 bytes float es de 4 bytes char es de 1 byte.

Para el caso de la variable valores, guarda un espacio de 4 bytes. S la variable valores hubiese sido un struct, entonces se hubiese podido almacenar los tres miembros, sin embargo, como es unin slo almacena uno. Ejemplo: Asignacin a uniones.
valores.entero=505;

Asigna 505 a la unin ocupando 2 bytes.


valores.flotante=0.6;

Borra el dato 505 y almacena 0.6 en 4 bytes. Se puede representar valores grficamente como: Si fuese estructura:
float

int

char

Si fuese union:

char int float

Entonces, el tamao es de 4 bytes, si fuese struct contendra 7 bytes.

Profesor: Roberto Uribe P.

Pg. N 137

Programacin de Computadores y el Lenguaje C

(versin 2003)

Problemas Resueltos y Propuestos Resueltos:

Problema especfico : Existe un programa escrito en C, dicho programa se encarga de manejar los datos de una empresa, esta puede tener hasta un mximo de 100 empleados. Para lo anterior se utilizan las siguientes estructuras:
struct obrero{ int codigo; char apellido[30]; char nombre[25]; int Edad; char direccion[35]; int coddepto; }; struct depto{ int coddepto; char nomdepto[35]; }; struct sueldo{ int codigo; long sueldobase; long otros; }; struct aux{ int codigo; char apellido[30]; };

No se preocupe de la forma de lectura y almacenamiento en disco, slo realice las funciones que se le piden. Al ejecutarse el programa, este carga los datos en las siguientes variables:
struct obrero arobrero[100]; /*arreglo que contiene los datos de cada obrero */ struct depto ardepto[30]; /*arreglo que contiene el codigo y nombre de cada depto. */ struct sueldo arsueldo[100]; /*arreglo que contiene los sueldos de los empleados */ struct aux obreord[100]; /* arreglo de enteros */

Todas estas variables son globales. Cada obrero al ser ingresado al sistema se le asigna un nmero (cdigo), este es en orden correlativo. Dicho cdigo se utiliza para identificar al obrero, por ejemplo, en el arreglo arsueldo, se ocupa para indicar el sueldo de un obrero cuyo cdigo esta indicado.
Profesor: Roberto Uribe P. Pg. N 138

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Ejemplo:
Arreglo arobrero: codigo 1 2 3 4 5 6 : : : -1 -1 -1 apellido Alexander Sanchez Valencia Gonzalez Gonzalez ...... ...... ...... ...... ...... ...... Arreglo ardepto: coddepto 1 2 3 . . . -1 -1 nomdepto Administracin Mantencin Informtica ..... ..... ..... ..... ..... Arreglo arsueldo: codigosueldobase 1 2 3 4 . . . -1 -1 230.000 180.000 200.000 140.000 otros 51.000 33.000 40.000 23.000 nombreedad Nicolai Alfredo Josefina Ramiro Miguelina ..... ..... ..... ..... 25 32 29 25 31 .. .. .. .. direccion O'Higgins 54 R. Correa 1050 I. C. Pinto 33 Mardones 0166 Bories 1420 ..... ..... ..... ..... coddepto 3 4 3 2 3 .. .. .. ..

.... ... .... ... Entonces Josefina Valencia del departamento 40.000 pesos. (los datos con -1 indican vacos o nulos).

de Informtica gana 200.000 +

Problemas: 1.Se le pide crear un mdulo (funcin) que realice lo siguiente: Ingrese un nombre de departamento y que imprima en pantalla el apellido, nombre, sueldo total (sueldobase+otros) de todos los empleados pertenecientes a ese depto. 2.Usando las estructuras y arreglos anteriores, haga una funcin que lea por teclado un nombre de departamento y un valor numrico, luego imprima las personas que pertenecen a ese departamento (apellido, nombre, sueldototal), con la condicin de que el sueldo total no
Profesor: Roberto Uribe P. Pg. N 139

Programacin de Computadores y el Lenguaje C

(versin 2003)

supere el valor numrico ingresado. Es decir todas las personas del depto .... que ganen menos de ..... 3.Escriba una funcin que ordene los obreros alfabticamente por apellido de menor a mayor (a-z). Para ello no modifique el arreglo original, duplique en otro arreglo (obreord), el cdigo y apellido. Luego de duplicado y ordenado, imprima en pantalla el apellido, nombre y sueldo total, obviamente ordenado por apellido. 4.La empresa a estimado aumentar el sueldo base de todos los empleados de un departamento determinado en un 10 %. Cree una funcin que realice este proceso. Es decir que lea el nombre de un depto. y que luego aumente en 10 % el sueldo base de todos los empleados de dicho depto.

Propuestos: Problema especfico Con los conocimientos que hasta ahora poseemos, suponga que se diseo una Base de Datos para llevar el control de las inscripciones de crditos de los alumnos de la carrera de Ingeniera de Ejecucin en Computacin e Informtica. Dicha Base de Datos tiene las siguientes Tablas:
ALUMNOS(n_mat,rut,apellido,nombre) ASIGNATURAS(cod,nombre_ramo,tel,descripcion,semcar,annocar) INSCRIPCION(n_mat,cod,semestre,anno) NOTAS(n_mat,cod,opcion,semestre,anno,promedio) REQUISITOS(cod,cod_req)

Donde:
n_mat cod tel semcar annocar semestre anno cod_req : : : : : : : : nmero de matrcula del alumno, cdigo de la asignatura, horas de teora, ejercicios y laboratorio, semestre en que se dicta la asignatura, ao en que se dicta la asignatura. semestre en que se inscribi el ramo(1 del segundo ao), ao en que se inscribi el ramo (ej. 1 de 1996) cdigo del ramo requisito.

La representacin de sus estructuras en C es:


struct alumnos{ long n_mat ; long rut; char apellido[30]; char nombre[30]; }alum[200]; struct asignaturas{ char cod[7]; char nombre_ramo[30]; int tel; char descripcion[40];
Profesor: Roberto Uribe P. Pg. N 140

Universidad de Magallanes - Departamento de Ingeniera en Computacin

int semcar; int annocar; }asig[25]; struct inscripcion{ long n_mat; char cod[7]; int semestre; int anno; }insc[5000]; /* este arreglo es slo un supuesto */ struct notas{ long n_mat; char cod[7]; int opcion; int semestre; int anno; float promedio; }not[5000]; struct requisitos{ char cod[7]; char cod_req[7]; }req[100];

Explicacin: Para la siguiente serie de problemas asuma que los arreglos ya contienen los datos, Ud. slo debe responder las consultas que se le piden. Como ejemplo de los datos contenidos en los arreglos, suponga:

: asignaturas[10]=("PRG2161","Programacin de Computadores","402","Programacin C",1,2) : asignaturas[15]=("LII3161","Lenguajes de Programacin II","402","Orientacin Objetos",1,3) : : inscripcion[405]=(9416035,"PRG2161",1,1996) inscripcion[406]=(9516010,"PRG2161",1,1996) :

en a

Nota: los datos dentro de los arreglos NO ESTN ORDENADOS!!,

Problemas : 5.Imprima una lista con los nombres y apellidos de todos los alumnos que inscribieron ramos en un semestre y ao determinado, por ejemplo: el segundo semestre de 1995. Los parmetros semestre y ao son ingresados a la funcin (no ledos por teclado). 6.La alumna Carolina Bonacic puede inscribir Lenguajes de Programacin I??, es decir, ingrese como parmetro a una funcin dos string, el primero un nombre de alumno y el segundo un nombre de un ramo. Verifique que el alumno puede o no inscribir el ramo, retorne 1 si puede y 0 si no. Recuerde que un ramo puede tener como requisito ms de una asignatura. 7.Imprimir la lista de los crditos tomados por el alumnos Juan Couecar el segundo semestre de 1995, indicando :
Profesor: Roberto Uribe P. Pg. N 141

Programacin de Computadores y el Lenguaje C

(versin 2003)

Nombre Ramo

Opcin

TEL

Promedio

8.-

Suponga que en la cabecera de un programa aparecen las siguientes definiciones:


struct num { int re; int im; };

/*parte real*/ /*parte imaginaria*/

typedef num imagin;

Es decir, se tiene un nuevo tipo de dato para el manejo de nmeros imaginarios. Ud. debe de implementar las funciones que permitar realizar la suma, resta, multiplicacin y divisin de dos numeros imaginarios. Las funciones deben ingresar ambos operandos y retornar el resultado. Slo se pide las funciones. 9.Uno de los problemas que hay al finalizar un Semestre Acadmico es preparar el horario para el semestre siguiente, este problema es sumamente complejo, a Ud. se le pide implementar una pequea parte de la solucin. Debe hacer un programa que permita ingresar el nombre de un ramo (string), el nmero de semestre (int) a el horario, para ello tome en cuenta el horario tiene 6 bloques y 5 das, donde cada bloque puede ser ocupado por una asignatura. Haga la implementacin completa para el ingreso de los datos y validaciones. Es decir, el usuario ingresa un bloque y un da y el programa debe indicar si este ya esta ocupado por alguna asignatura, si no es as, entonces puede ingresar los datos correspondientes Simplificacin del problema: Asuma que la solucin es slo para una carrera. No tome en cuenta el nmero de alumnos por sala. Recomendaciones: Primero resuelva el problema suponiendo que existe slo una sala. Luego para n salas, por ejemplo 5. Para aumentar la complejidad del problema modifique el programa para que las asignaturas puedan ocupar mximo dos bloques a la semana.

Profesor: Roberto Uribe P.

Pg. N 142

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Profesor: Roberto Uribe P.

Pg. N 143

Programacin de Computadores y el Lenguaje C

(versin 2003)

Captulo N9 : Archivos en C (en construccin)

Tipo usado en archivos FILE El tipo FILE es definido por C en el archivo de cabecera stdio.h para el manejo de archivos. Esta es una estructura, y se usar siempre con punteros a esta. La definicin de sta estructura depende del compilador, pero en general mantienen un campo con la posicin actual de lectura/escritura, un buffer para mejorar las prestaciones de acceso al archivo y algunos campos para uso interno. Funciones para manejo de archivos A continuacin se presenta un listado de las funciones ms frecuentes para la administracin de archivos en C. Funcin fopen : Sintaxis:
FILE *fopen(char *nombre, char *modo);

Esta funcin sirve para abrir y crear archivos en disco. El valor de retorno es un puntero a una estructura FILE. Los parmetros de entrada son: 1. nombre: una cadena que contiene un nombre de archivo vlido, esto depende del sistema operativo que estemos usando. El nombre puede incluir el camino completo. 2. modo: es una cadena que especifica el tipo de archivo que se abrir o se crear y el tipo de datos que puede contener, de texto o binarios:
o o o r: slo lectura. El archivo debe existir. w: se abre para escritura, se crea un archivo nuevo o se sobrescribe si ya existe. a: aadir, se abre para escritura, el cursor se sita al final del archivo. Si el

archivo no existe, se crea.


o o o r+: lectura y escritura. El archivo debe existir. w+: lectura y escritura, se crea un archivo nuevo o se sobrescribe si ya existe. a+: aadir, lectura y escritura, el cursor se sita al final del archivo. Si el

archivo no existe, se crea.


o o t: tipo texto, si no se especifica t ni b, se asume por defecto que es t b: tipo binario.

Profesor: Roberto Uribe P.

Pg. N 144

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Por ejemplo: el siguiente cdigo hable un archivo para lectura y escritura de tipo binario. Al comienzo aparece declarada la variable fdata como puntero a FILE.
FILE *fdata; : : if ((fdata=fopen("datos.dat","r+b"))==NULL) { printf("Error al abrir archivo"); return 0; }

Funcin fclose : Sintaxis:


int fclose(FILE *archivo);

Cierra un archivo y almacena los datos que an estn en el buffer de memoria, actualiza algunos datos de la cabecera del archivo que mantiene el sistema operativo. Adems permite que otros programas puedan abrir el archivo para su uso. Un valor de retorno cero indica que el archivo ha sido correctamente cerrado, si ha habido algn error, el valor de retorno es la constante EOF. El parmetro es un puntero a la estructura FILE del archivo que queremos cerrar.

Funcin fgetc : Sintaxis:


int fgetc(FILE *archivo);

Esta funcin lee un carcter desde un archivo. El valor de retorno es el carcter ledo como un unsigned char convertido a int. Si no hay ningn carcter disponible, el valor de retorno es EOF. El parmetro es un puntero a una estructura FILE del archivo del que se har la lectura.

Funcin fputc : Sintaxis:


int fputc(int caracter, FILE *archivo);

Esta es la funcin inversa a fgetc y escribe un carcter a un archivo. El valor de retorno es el carcter escrito, si la operacin fue completada con xito, en caso contrario ser EOF. Los parmetros de entrada son el carcter a escribir, convertido a int y un puntero a una estructura FILE del archivo en el que se har la escritura.
Profesor: Roberto Uribe P. Pg. N 145

Programacin de Computadores y el Lenguaje C

(versin 2003)

Funcin feof : Sintaxis:


int feof(FILE *archivo);

Esta funcin permite verificar si se ha llegado el fin del archivo. Muy frecuentemente deberemos trabajar con todos los valores almacenados en un archivo de forma secuencial, la forma que suelen tener los cilos o bucles para leer todos los datos de un archivo es permanecer leyendo mientras no se detecte el fin de archivo. Por ejemplo:

while(!feof(fDB))

El valor de retorno es cero mientras no se haya alcanzado el fin de archivo (cuando llega al final del archivo retorna un nmero distinto de cero). El parmetro es un puntero a la estructura FILE.

Funcin rewind : Sintaxis:


void rewind(FILE *archivo);

La funcin rewind o rebobinar, ubica el control del archivo al principio de este. Esta funcin es heredada de los tiempos de las cintas magnticas, donde literalmente haba que rebobinar la cita hasta el principio. Funcin fgets : Sintaxis:
char *fgets(char *cadena, int n, FILE *archivo);

Esta funcin est diseada para leer cadenas de caracteres. Leer hasta n-1 caracteres o hasta que lea un retorno de lnea. En este ltimo caso, el carcter de retorno de lnea tambin es ledo. El parmetro n nos permite limitar la lectura para no exceder el lmite de la cadena. El valor de retorno es un puntero a la cadena leda, si se ley con xito, y es NULL si se detecta el final del archivo o si hay un error. Los parmetros son: la cadena a leer, el nmero de caracteres mximo a leer y un puntero a una estructura FILE del archivo del que se leer.

Funcin fputs :
Profesor: Roberto Uribe P. Pg. N 146

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Sintaxis:
int fputs(const char *cadena, FILE *archivo);

La funcin fputs escribe una cadena en un archivo. No se aade el carcter de retorno de lnea ni el carcter nulo final. El valor de retorno es un nmero no negativo o EOF en caso de error. Los parmetros de entrada son la cadena a escribir y un puntero a la estructura FILE del archivo donde se realizar la escritura. Funcin fread : Sintaxis:
size_t fread(void *varreg, size_t tamao, size_t nreg, FILE*archivo);

Esta funcin est pensada para trabajar con registros de longitud constante. Es capaz de leer desde un archivo uno o varios registros de la misma longitud y a partir de una direccin de memoria determinada. El usuario es responsable de asegurarse de que hay espacio suficiente para contener la informacin leda. El valor de retorno es el nmero de registros ledos, no el nmero de bytes. Los parmetros son: un puntero a la zona de memoria donde se almacenarn los datos ledos (varreg), el tamao de cada registro, el nmero de registros a leer y un puntero a la estructura FILE del archivo del que se har la lectura.

Funcin fwrite : Sintaxis:


size_t fwrite(void *varreg,size_t tamao,size_t nreg, FILE *archivo);

Esta funcin es equivalente a fread, pero para escritura. Puede de escribir en un archivo uno o varios registros de la misma longitud almacenados a partir de una direccin de memoria determinada. El valor de retorno es el nmero de registros escritos, no el nmero de bytes. Los parmetros son: un puntero a la zona de memoria donde se almacenarn los datos ledos, el tamao de cada registro, el nmero de registros a leer y un puntero a la estructura FILE del archivo del que se har la lectura.

Funcin fprintf : Sintaxis:


int fprintf(FILE *archivo, const char *formato, ...);

Es equivalente a printf, pero la salida se dirige a un archivo en lugar de la salida estandar.


Profesor: Roberto Uribe P. Pg. N 147

Programacin de Computadores y el Lenguaje C

(versin 2003)

Funcin fscanf : Sintaxis:


int fscanf(FILE *archivo, const char *formato, ...);

Equivalente a scanf, pero la entrada se toma de un archivo en lugar del teclado (o entrada estandar stdin).

Funcin fflush : Sintaxis:


int fflush(FILE *archivo);

fuerza la salida de los datos acumulados en el buffer de salida del archivo. Para mejorar las prestaciones del manejo de archivos se utilizan buffers, almacenes temporales de datos en memoria, las operaciones de salida se hacen a travs del buffer, y slo cuando el buffer se llena se realiza la escritura en el disco y se vaca el buffer. En ocasiones nos hace falta vaciar ese buffer de un modo manual, para eso sirve sta funcin.
fflush

El valor de retorno es cero si la funcin se ejecut con xito, y EOF si hubo algn error. El parmetro de entrada es un puntero a la estructura FILE del archivo del que se quiere vaciar el buffer. Si es NULL se har el vaciado de todos los archivos abiertos.
Funcin fseek :

Sintaxis:
int fseek(FILE *archivo,long int desplazamiento,int origen);

Situa el control de archivo (o cursor) para leer o escribir en un lugar especificado en desplazamiento. El valor de retorno es cero si la funcin tuvo xito, y un valor distinto de cero si hubo algn error. Los parmetros de entrada son: un puntero a una estructura FILE del archivo en el que queremos cambiar el cursor de lectura/escritura, el valor del desplazamiento(en bytes) y el punto de origen desde el que se calcular el desplazamiento. El parmetro origen puede tener tres posibles valores: 1. SEEK_SET : el desplazamiento se cuenta desde el principio del archivo. El primer byte del archivo tiene un desplazamiento cero. 2. SEEK_CUR : el desplazamiento se cuenta desde la posicin actual del cursor. 3. SEEK_END : el desplazamiento se cuenta desde el final del archivo.
Profesor: Roberto Uribe P. Pg. N 148

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Funcin ftell : Sintaxis:


long int ftell(FILE *archivo);

La funcin ftell sirve para averiguar la posicin actual del cursor de lectura/escritura de un archivo. El valor de retorno ser esa posicin en bytes, o -1 si hay algn error.

Funcin remove : Sintaxis :


int remove(char *filename);

Esta funcin sirve para borrar permanentemente un archivo. El parmetro de entrada es la ruta absoluta o relativa del archivo a borrar. Si la eliminacin del archivo fue exitosa, el valor de retorno es cero, de lo contrario es un nmero distinto de cero. Un ejemplo interesante con fread Supongamos la siguiente estructura:
struct _obrero { char nombre[30]; int edad; long fono; }; typedef _obrero obrero;

supongamos ahora que se tiene un archivo llamado datos.dat, el cual fue escrito usando la misma estructura (con fwrite). Entonces para leer todo el archivo y mostrarlo en pantalla sera:
void muestradatos() { FILE *fdata; Int total=0; obrero a; if ((fdata=fopen("datos.dat","r+b"))==NULL) { printf("Error al abrir archivo"); return; } while(!feof(fdata)) {
Profesor: Roberto Uribe P. Pg. N 149

Programacin de Computadores y el Lenguaje C

(versin 2003)

fread(&a, sizeof(obrero), 1, fdata); muestraobrero(a); total++; } printf(\ntotal de datos leidos:: %d\n,total); } void muestraobrero(obrero a) { printf(%s \t %d \t %ld \n,a.nombre, a.edad, a.fono); return; }

Observe que a fread se le paso la direccin de a, eso, dado que el parmetro requerido por la funcin es un puntero, en este caso un puntero a obrero. El parmetro 1, es que leemos slo un dato de tipo obrero. Cada vez que se hace una lectura el control del archivo se mueve al dato siguiente, y el ciclo termina cual se llega al final de archivo. Si escribe y ejecuta este cdigo, es posible que ocurra lo siguiente, la variable total con un dato ms y en el listado, aparece repetido el ltimo obrero, porque??. Este es un error tpico y es producto de que despues de leer el ltimo dato, an no se alcanza el fin de archivo, por lo tanto se mete una vez ms al while, se incrementa nuevamente total y el fread falla, asi que se muestra el ltimo valor que teniala variable a. Si se reemplaza el while por:
while(!feof(fdata)) { if (fread(a, sizeof(obrero), 1, fdata)<1) printf(error al leer obrero); else { muestraobrero(a); total++; } }

Con esto se arregla el problema, y es porque la ltima lectura no alcanza a leer un dato de tipo obrero, por lo tanto el valor de fread es menor que 1.

Profesor: Roberto Uribe P.

Pg. N 150

Universidad de Magallanes - Departamento de Ingeniera en Computacin

ltimas Notas El siguiente paso a seguir en programacin es el estudio de las estructuras de datos, este tema corresponde tanto a la construccin se complejas estructuras generalmente usando punteros como es el caso de listas enlazadas, listas doblemente enlazadas, arboles binarios y arboles en general, as como tambin recursividad y medicin de la eficiencia de algoritmos para las estructuras mencionadas. No es necesario el conocimiento de un lenguaje especfico para comprender estructuras de datos, basta usar seudolenguajes, sin embargo, es necesario para poder realizar la implementacin de dichos algoritmos. En las carreras de Ingeniera en Computacin o Informtica estos tpicos se ven en las asignaturas que siguen la lnea de Programacin de Computadores como Estructuras de Datos y Algoritmos. Respecto del lenguaje C, lo visto en este curso es slo una parte, queda mucho ms por aprender .

Profesor: Roberto Uribe P.

Pg. N 151

Programacin de Computadores y el Lenguaje C

(versin 2003)

Anexo N 1 : Estructura de un Compilador A nivel general un compilador verifica que el programa fuente cumpla con los requisitos que exige el lenguaje, es decir, primero verifica que los caracteres y smbolos usados sean los permitidos (anlisis lxico), despues ve si estos smbolos estn usados adecuadamente, osea, en el orden o lugar correcto (anlisis sintctico). La estructura fundamental de un compilador queda expuesto en el siguiente diagrama:

Programa Fuente

Analizador Lxico (lexer)

Tabla de Smbolos (Tokens)

Analizador Sintctico (Parser)

Optimizacin de Cdigo

Generacin de Cdigo

Listado Errores (Semnticos, Sintcticos) Cdigo Objeto

Generacin de Cdigo Intermedio (anlisis Semntico)

Para mquinas particulares

Profesor: Roberto Uribe P.

Pg. N 152

Universidad de Magallanes - Departamento de Ingeniera en Computacin

Anexo N 2 : Algunos Conceptos Lenguajes de Programacin: Son formas de indicarle al computador de manera detallada qu es lo que nosotros queremos que haga. Lenguaje de alto nivel: Es el lenguaje ms prximo al hombre, el que nosotros entendemos. Lenguaje de bajo nivel o de mquina: Es el lenguaje ms prximo a la mquina. C: Es un lenguaje de programacin de nivel medio (compilado), es de propsito general. Pascal: Lenguaje de programacin de alto nivel (compilado), de propsito general. Fortran: Lenguaje de alto nivel desarrollado para aplicaciones matemticas y cientficas, su nombre viene de FORmula TRANslation. En un principio era un lenguaje no estructurado, pero las nuevas versiones si lo son. Compilador: Permite traducir las instrucciones escritas en lenguaje de alto nivel en instrucciones de bajo nivel. Programacin Estructurada: Mtodo de Programacin que pretende evitar al mximo los errores en los programas, su tcnica es la de dividir el programa en bloques o etapas que se irn definiendo y concretando en forma descendente hasta llegar a completar el programa o resolver el problema. Las unidades bsicas de Programacin Estructurada son: Secuencia: Una serie de procesos, que va uno tras de otro. Seleccin: Proceso que permite elegir otros procesos. Iteracin: Proceso que ocurre una cantidad de veces (Loop). Lenguaje Estructurado. Tipo de Lenguaje creado para facilitar la programacin estructurada. Diagramas de Flujo: Es una representacin grfica de la definicin, anlisis o solucin de un programa en el cual los smbolos se utilizan para representar operaciones, datos, etc. Permite visualizar el comportamiento de cada paso de un programa. Algoritmos: Son una secuencia de pasos muy detallados y ordenados lgicamente que nos permiten realizar una determinada accin.

Profesor: Roberto Uribe P.

Pg. N 153