You are on page 1of 93

Universidad Autnoma

de Baja California
Facultad de Ingenieria Arquitectura y Diseo

Programacin Estructurada
Clave: 12125
Pedro Nez Ypiz

Ensenada Baja California, Agosto 2013

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

C O N T E N I D O

1. Instalacion del IDE (Entorno de Desarrollo Integrado) para C/C++


2. Principios de C
o
o
o
o
o
o
o
o
o
o

3. Estructuras Condicionales
o
o
o

7.1 Deficicin y uso de Estructuras


7.2 Deficicion de nuevos tipos de datos

8. Apuntadores
o
o
o

6.1 Funciones void


6.2 Funciones y arreglos
6.3 Prototipos de funciones
6.4 Ejercicios

7. Estructuras
o
o

5.1 Arreglos unidimensionales y multidimensionales


5.2 Cadenas
5.3 Ejercicios

6. Funciones
o
o
o
o

4.1 La sentencia for


4.2 La sentencia while
4.3 La sentencia do-while
4.4 Uso de break y continue
4.5 Ejercicios

5. Arreglos y cadenas
o
o
o

3.1 La sentencia if
3.3 La sentencia switch
3.3 Ejercicios

4. Ciclos
o
o
o
o
o

2.1 Orgenes del C


2.2 Caractersticas de C
2.3 Estructura de un programa en C
2.4 Variables
2.4.1 Definicin de variables globales
2.4.2 Lectura y escritura de variables
2.5 Constantes
2.6 Operadores Aritmticos
2.7 Operadores de Comparacin
2.8 Operadores lgicos
2.9 Orden de precedencia
2.10 Ejercicios

8.1 Definicin de un apuntador


8.2 Apuntadores y Funciones
8.3 Apuntadores y Arreglos

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

9. Biblioteca <stdlib.h>
o
o
o
o
o

10. Biblioteca <math.h>


o
o

o
o
o

17.1 Funciones bsicas para el manejo de cadenas


17.1.1 Bsqueda en cadenas
17.2 Prueba y conversin de caracteres <ctype.h>
17.3 Operaciones con la memoria <memory.h>
17.4 Ejercicios

12. Manejo de Archivos


o
o
o
o

15.1 Funciones matemticas


15.2 Constantes matemticas

11. Manejo de cadenas <string.h>


o

14.1 Funciones aritmticas


14.2 Nmeros aleatorios
14.3 Conversin de cadenas
14.4 Bsqueda y ordenamiento
14.5 Ejercicios

12.1 Generalidades
121.2 Funciones C para archivos
12.3 Archivos secuenciales
12.4 Archivos de acceso aleatorio

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 1

Compilacin de un programa
en C/C++

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

1. Instalacion del IDE (Entorno de Desarrollo Integrado)


paratrabajar en C

1.1 Instalacion del IDE DevC++ Windows 7 y anteriores

1.1.1 Para La instalacin de DevC++ descargar el


programa de la siguiente Liga.
http://sourceforge.net/projects/dev-cpp/files/Binaries/DevC%2B%2B%204.9.9.2/devcpp4.9.9.2_setup.exe/download?use_mirror=iweb

1.1.2 Pasos para instalar DevC++


http://www.slideshare.net/16134817/cmo-instalar-dev-c
1. Versin: 4.9.9.2 Nuestro entorno para programar en C++
2. Una vez que ejecute el instalador, y Seleccione el idioma de la
instalacin
3. Aceptar la licencia
4. Seleccionar los componentes ainstalar, vienen por defecto
5. Configurar la carpeta destino:
6. Al hacer clic en siguiente, arrancael proceso de instalacin:
7. Elegir si Dev C++ estar disponiblepara todos los usuarios del PC
8. La instalacin termina, con lacasilla Ejecutar seleccionada, clicen
Terminar
9. El programa inicia por 1ra vez
10. Se configura el idioma delprograma, seleccionar
Spanish(LatinoAmrica)
11. En estos dos pasos, hacer clic en Next
12. Luego, habr una segunda y ltimacarga de archivos
13. La instalacin ha finalizado
14. Esto es lo 1ro que vers activa odesactiva las sugerencias, clic
enCerrar
15. Clic en Archivo Fuente y listo,A Programar en C++!

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

Instalacion de IDE DevC++ Windows 8

Pasos de la Instalacin del wxdevcpp


Hace varios aos que los autores del Dev C++ han dejado de actualizar el proyecto, por lo que
ahora es un poco difcil lograr instalarlo en Windows Vista o Windows 7.
wxdevcpp es un clon de Dev C++ que se mantiene al da y se puede instalar sin ningn
problema en cualquier versin de Windows, incluyendo Windows Vista y Windows 7; a
dems, cuenta con una biblioteca de clases para la creacin de cuadros de dialogo wxWidget.
A continuacin se detallan los pasos para la instalacin del wxdevcpp.
1. Presione aqu, para descargar el software.
2. Una vez descargado, hacer doble click sobre el programa instalador

3. Precionar el botn Acepto, para aceptar la licencia GNU

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

4. Presionar el botn "Siguiente >", no es necesario modificar ninguna opcin en esta


ventana.

5. Presione el botn "Siguiente >", aqu tampoco es necesario modificar ninguna opcin.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

6. Elegir un directorio destino para la instalacin del software (se puede dejar la opcin
pre establecida), luego precionar el boton de Instalar

7. Si no dispone de una conexin a Internet presione No, en caso de disponer de una


conexin a Internet, podr descargar las ltimas versiones de los distintos paquetes que
incluye el software.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

8. Esperar a que se extraigan y copien todos los archivos.

9. Despus de unos minutos se mostrar el mensaje "Completado" y se podr presionar el


botn "Cerrar".

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

10. Presionar el botn "Si" para que todos los usuarios de la computadora puedan usar el
programa.

Despus de esto, el programa instalador se cerrar.

11. Para concluir la instalacin deberemos ejecutar el programa Dev C++ por primera vez,
haciendo click sobre su cono en el men de inicio.

10

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

12. Elegir el idioma "Espaol (Castellano)", tambin se debe marcar la casilla "Use XP
Theme"

13. Elegir "Yes, create the cache now" y luego presionar "Next"

11

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

14. Hacer click en "Next" para que se inicie la configuracin final, este ltimo paso podra
tomar muchos minutos!

15. Despus de la larga espera slo habr que presionar el botn "Ok" y se podr empezar
a usar el software.

12

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

13

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 2
Principios de C

14

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

2. Principios de C
En este captulo se ofrece una breve historia del desarrollo del lenguaje C y se consideran tambin sus
caractersticas.
En el resto del captulo se ven los aspectos bsicos de los programas de C, tales como su estructura, la
declaracin de variables, tipos de datos y operadores.
2.1 Orgenes del C
El proceso de desarrollo del lenguaje C se origina con la creacin de un lenguaje llamado BCPL, que fue
desarrollado por Martin Richards. El BCPL tuvo influencia en un lenguaje llamado B, el cual se us en 1970 y
fue inventado por Ken Thompson y que permiti el desarrollo de C en 1971, el cual lo invent e implement
Dennis Ritchie. Para 1973 el sistema operativo UNIX estaba casi totalmente escrito en C.
Durante muchos aos el estndar para C fue la versin 5 del sistema operativo UNIX, documentada en ``The
C Programming Language'' escrito por Brian W. Kernighan and Dennis M. Ritchie in 1978 comnmente
referido como K&R.
Posteriormente se hicieron varias implementaciones las cuales mostraban las siguientes tendencias:

Nuevas caractersticas
Diferencias de mquinas
Diferencias de productos
Errores en los compiladores
Malas implementaciones

Esto origin que en el verano de 1983 se estableciera un comit para resolver estas discrepancias, el cual
empez a trabajar en un estndar ANSI C, la cual fue completada en 1988.
2.2 Caractersticas de C
Algunas de las caractersticas ms importantes que definen el lenguaje y que han permitido que sea tan
popular, como lenguaje de programacin son:

Tamao pequeo.
Uso extensivo de llamadas a funciones.
Comandos breves (poco tecleo).
Lenguaje estructurado.
Programacin de bajo nivel (nivel bit)
Implementacin de apuntadores - uso extensivo de apuntadores para la memoria, arreglos,
estructuras y funciones

Las diversas razones por la cual se ha convertido en un lenguaje de uso profesional son:

El uso de constructores de alto nivel.


El poder manejar actividades de bajo-nivel.
El generar programas eficientes.
La posibilidad de poder ser compilado en una variedad de computadoras, con pocos cambios
(portabilidad).

Un punto en contra es que tiene una deteccin pobre de errores, lo cual en ocasiones es problemtico para
los principiantes.

15

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


2.3 Estructura de un programa en C
Un programa de C tiene bsicamente la siguiente forma:

Comandos del preprocesador.


Definiciones de tipos.
Prototipos de funciones - declara el tipo de funcin y las variables pasadas a la misma.
Variables
Funciones

Para un programa se debe tener una funcin main().


Una funcin tiene la forma:

tipo nombre_de_la_funcion (parmetros)


{
variables locales
sentencias de C
}

A continuacin se muestra un primer programa:

/* Programa ejemplo */
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf( "HOLA MUNDO CRUEL Y DESPIADADO \n" );
system (PAUSE);
return 0;
}

NOTAS:

C requiere las libreras para cargar el funcionamiento de las sentencias siempre vanal inico del
programa y se identifican con el # seguida de la palabra include
#include
C requiere un punto y coma al final de cada sentencia .
printf es una funcin estndar de C, la cual es llamada en la funcin main()
\n significa salto de lnea. Salida formateada.
return 0; es tambin una funcin estndar que hace que el programa termine.corretamente .

En caso de que se hubiera llamado a la funcin printf de la siguiente forma:

16

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


printf("HOLA\n MUNDO \n CRUEL \n Y \n DESPIADADO");

La salida tendra la siguiente forma:

HOLA
MUNDO
CRUEL
Y
DESPIADADO

2.4 Variables
C tiene los siguientes tipos de datos simples:

Tabla 2.1: Tipos de C


Tipo

Tamao (bytes) Lmite inferior Lmite superior

char

--

--

unsigned char

255

short int

-32768

+32767

unsigned short int

35536

31

+231 -1

(long) int

float

-3.2 x 1038

+3.2 x 1038

double

-1.7 x 10308

+1.7 x 10308

-2

Los tipos de datos bsicos tiene varios modificadores que les preceden. Se usa un modificador para alterar el
significado de un tipo base para que encaje con las diversas necesidades o situaciones. Los modificadores
son: signed, unsigned, long y short.
En los sistemas UNIX todos los tipos int son long int, a menos que se especifique explcitamente
short int.
Nota: no hay un tipo booleano en C -- se deber usar char, int o an mejor unsigned char.

signed, unsigned, long y short pueden ser usados con los tipos char e int. Aunque es permitido el
uso de signed en enteros, es redundante porque la declaracin de entero por defecto asume un nmero con
signo.
Para declarar una variable en C, se debe seguir el siguiente formato:

tipo lista_variables;
tipo es un tipo vlido de C y lista_variables puede consistir en uno o ms indentificadores separados por una
coma. Un identificador debe comenzar con una letra o un guin bajo.

17

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Ejemplo:

int i, j, k;
float x,y,z;
char ch;

2.4.1 Definicin de variables globales


Una varible global se declara fuera de todas las funciones, incluyendo a la funcin main(). Una variable
global puede ser utilizada en cualquier parte del programa.
Por ejemplo:
#include <stdlib.h>
#include <stdio.h>

short numero, suma;


int numerogr, sumagr;
char letra;
main()
{
...
}

Es tambin posible preinicializar variables globales usando el operador de asignacin =, por ejemplo:
#include <stdlib.h>
#include <stdio.h>

float suma= 0.0;


int sumagr= 0;
char letra= 'A';
main()
{
...
}

Que es lo mismo que:


#include <stdlib.h>
#include <stdio.h>

float suma;
int sumagr;
char letra;
main()
{
suma = 0.0;
sumagr= 0;
letra = 'A';
...

18

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


}

Dentro de C tambin se permite la asignacin mltiple usando el operador =, por ejemplo:

a = b = c = d = 3;

...que es lo mismo, pero ms eficiente que:

a
b
c
d

=
=
=
=

3;
3;
3;
3;

La asignacin mltiple se puede llevar a cabo, si todos los tipos de las variables son iguales.
Se pueden redefinir los tipos de C usando typedef. Como un ejemplo de un simple uso se considera como
se crean dos nuevos tipos real y letra. Estos nuevos tipos pueden ser usados de igual forma como los tipos
predefinidos de C.

typedef float real;


typedef char letra;
/* Declaracion de variables usando el nuevo tipo */
real suma=0.0;
letra sig_letra;

2.4.2 Lectura y escritura de variables


El lenguaje C usa salida formateada. La funcin printf tiene un caracter especial para formatear (%) -- un
caracter enseguida define un cierto tipo de formato para una variable.

%c
%s
%d
%f

caracteres
cadena de aracteres
enteros
flotantes

Por ejemplo:

printf("%c %d %f",ch,i,x);

La sentencia de formato se encierra entre " ", y enseguida las variables. Asegurarse que el orden de
formateo y los tipos de datos de las variables coincidan.

scanf() es la funcin para entrar valores a variables. Su formato es similar a printf. Por ejemplo:
scanf("%c %d %f %s",&ch, &i, &x, cad);

19

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Observar que se antepone & a los nombres de las varibles, excepto a la cadena de caracteres. En el captulo
8 que trata sobre apuntadores se revisar ms a fondo el uso de este operador.
2.5 Constantes
ANSI C permite declarar constantes. Cuando se declara una constante es un poco parecido a declarar una
variable, excepto que el valor no puede ser cambiado.
La palabra clave const se usa para declarar una constante, como se muestra a continuacin:

const A = 1;
int a = 2;

Notas:

Se puede usar const antes o despus del tipo.


Es usual inicializar una constante con un valor, ya que no puede ser cambiada de alguna otra forma.

La directiva del preprocesador #define es un mtodo ms flexible para definir constantes en un programa.
#include <stdlib.h>
#include <stdio.h>

#define N 20
#define CONST 43
float suma= 0.0;
int sumagr= 0;
char letra= 'A';
main()
{
...
}

Una buena prctica de programacin es que las constantes sean maysculas.


2.6 Operadores Aritmticos
Lo mismo que en otros lenguajes de programacin, en C se tienen los operadores aritmticos ms usuales

+
*
/
%

suma
resta
multiplicacin
divisin
mdulo

El operador de asignacin es =, por ejemplo: i=4; ch='y';


Incremento ++ y decremento -- unario. Los cuales son ms eficientes que las respectivas asignaciones. Por
ejemplo: x++ es ms rpido que x=x+1.

20

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Los operadores ++ y -- pueden ser prefijos o postfijos. Cuando son prefijos, el valor es calculado antes de
que la expresin sea evaluada, y cuando es postfijo el valor es calculado despus que la expresin es
evaluada.
En el siguiente ejemplo, ++z es prefijo y -- es postfijo:

int x,y,z;
main()
{
x=( ( ++z ) - ( y-- ) ) % 100;
}

Que es equivalente a:

int x,y,z;
main()
{
z++;
x = ( z-y ) % 100;
y--;
}

El operador % (mdulo o residuo) solamente trabaja con enteros, aunque existe una funcin para flotantes
(15.1 fmod() ) de la biblioteca matemtica.
El operador divisin / es para divisin entera y flotantes. Por lo tanto hay que tener cuidado. El resultado de x
= 3 / 2; es uno, an si x es declarado como float. La regla es: si ambos argumentos en una divisin son
enteros, entoces el resultado es entero. Si se desea obtener la divisin con la fraccin, entonces escribirlo
como: x = 3.0 / 2; o x = 3 / 2.0 y an mejor x = 3.0 / 2.0.
Por otra parte, existe una forma ms corta para expresar clculos en C. Por ejemplo, si se tienen expresiones
como: i = i + 3; o x = x * (y + 2); , pueden ser reescritas como:

expr1 oper = expr2


Lo cual es equivalente, pero menos eficiente que:

expr1 = expr1 oper expr2

Por lo que podemos reescribir las expresiones anteriores como: i += 3; y x *= y + 2;


respectivamente.
2.7 Operadores de Comparacin
El operador para probar la igualdad es ==, por lo que se deber tener cuidado de no escribir accidentalmente
slo =, ya que:

21

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


if ( i = j ) ...
Es una sentencia legal de C (sintcticamente hablando aunque el compilador avisa cuando se emplea), la cual
copia el valor de ``j'' en ``i'', lo cual ser interpretado como VERDADERO, si j es diferente de cero.
Diferente es !=, otros operadores son: < menor que, > mayor que, <= menor que o igual a y >= (mayor que o
igual a).

2.8 Operadores lgicos


Los operadores lgicos son usualmente usados con sentencias condicionales o relacionales, los operadores
bscios lgicos son:

&& Y lgico, || O lgico y ! negacin.

2.9 Orden de precedencia


Es necesario ser cuidadosos con el significado de expresiones tales como a + b * c, dependiendo de lo
que se desee hacer

(a + b) * c
o

a + (b * c)
Todos los operadores tienen una prioridad, los operadores de mayor prioridad son evaluados antes que los
que tienen menor prioridad. Los operadores que tienen la misma prioridad son evaluados de izquierda a
derecha, por lo que:

a - b - c
es evaluado como

(a - b) - c

22

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Prioridad Operador(es)
Ms alta ( ) [ ] ->
! ~ ++ -- -

(tipo) * & sizeof

*/%
+<< >>
< <= > >=
== !=
&
^
|
&&
||
?
= += -= *= /=

Ms baja ,

De acuerdo a lo anterior, la siguiente expresin:

a < 10 && 2 * b < c


Es interpretada como:

(a < 10) && ( (2 * b) < c )

23

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


2.10 Ejercicios
Escribir programas en C para hacer las siguientes tareas:
1.
2.
3.

4.

5.
6.

24

Leer la entrada de dos nmeros y mostrar el doble producto del primero menos la mitad del segundo.
Lea y escriba su nombre, apellido paterno, apellido materno y matricula en un formato adecuado.
Escribir un programa para leer un ``flotante'' que representa un nmero de grados Celsius, e imprime
como un ``flotante'' la temperatura equivalente en grados Fahrenheit. La salida puede ser de la
siguiente forma: 100.0 grados Celsius son 212.0 grados Fahrenheit.
Escribir un programa para imprimir varias veces el ejercicio 2. Puede usar varias instrucciones printf,
con un caracter de nueva lnea en cada una, o una instruccin con varios caracteres nueva lnea en
la cadena de formateo.
Escribir un programa que lea el radio de un crculo como un nmero flotante y muestre el rea y el
permetro del crculo.
Dados ciertos centmetros como entrada de tipo flotante, imprimir su equivalencia a pies (enteros) y
pulgadas (flotante, 1 decimal), dando las pulgadas con una precisin de un lugar decimal Suponer
2.54 centmetros por pulgada, y 12 pulgadas por pie.
Si la entrada es 333.3, el formato de la salida deber ser:
333.3 centmetros son 10 pies 11.2 pulgadas.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 3

Estructuras Condicionales

25

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

3. Estructuras Condicionales
En este captulo se revisan los distintos mtodos con los que C controla el flujo lgico de un programa.
Los operadores relaciones binarios que se usan son:

<
<=
>
>=
==
!=

Menor que
Menor Igualque
Mayor que
Mayor igual que
Exactamente Igual
Diferente

Los operadores lgicos binarios:

||
&&

OR
AND

y el operador lgico unario de negacin !, que slo toma un argumento.

NOT

Los operadores anterior son usados con las siguientes estructuras que se muestran.
3.1 La sentencia if
Las tres formas como se puede emplear la sentencia if son:

if (condicion)
sentencia;
...o

if (condicion)
sentencia1;
else
sentencia2;
...o

if (condicion1)
sentencia1;
else
if (condicion2)
sentencia2;
...

else
sentencian;

26

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


El flujo lgico de esta estructura es de arriba hacia abajo. La primera sentencia se ejecutar y se saldr de la
estructura if si la primera condicin es verdadera. Si la primera condicin fue falsa, y existe otra condicin,
se evala, y si la condicin es verdadera, entonces se ejecuta la sentencia asociada. Si existen ms
condiciones dentro de la estructura if, se van evaluando stas, siempre y cuando las condiciones que le
precedan sean falsas.
La sentencia que esta asociada a la palabra reservada else, se ejecuta si todas las condiciones de la
estructura if fueron falsas.
Por ejemplo:

int main()
{
int x, y, w;
........
if (x>0)
{
z=w;
.......
}
else
{
z=y;
.......
}
}

3.2 La sentencia switch


Aunque con la estructura if ... else if se pueden realizar comprobaciones mltiples, en ocasiones no
es muy elegante, ya que el cdigo puede ser difcil de seguir y puede confundir incluso al autor transcurrido un
tiempo. Por lo anterior, C tiene incorporada una sentencia de bifurcacin mltiple llamada switch. Con esta
sentencia, la computadora comprueba una variable sucesivamente frente a una lista de constantes enteras o
de caracter. Despus de encontrar una coincidencia, la computadora ejecuta la sentencia o bloque de
sentencias que se asocian con la constante. La forma general de la sentencia switch es:

switch (variable) {
case constante1:
secuencia de sentencias
break;

case constante2:
secuencia de sentencias
break;

case constante3:
secuencia de sentencias
break;
...

default:
secuencia de sentencias
}

27

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


donde la computadora ejecuta la sentencia default si no coincide ninguna constante con la variable, esta
ltima es opcional. Cuando se encuentra una coincidencia, la computadora ejecuta las sentencias asociadas
con el case hasta encontrar la sentencia break con lo que sale de la estructura switch.
Las limitaciones que tiene la sentencia switch ... case respecto a la estructura if son:

Slo se tiene posibilidad de revisar una sola variable.


Con switch slo se puede comprobar por igualdad, mientras que con if puede ser con cualquier
operador relacional.
No se puede probar ms de una constante por case.

La forma como se puede simular el ltimo punto, es no teniendo sentencias asociados a un case, es decir,
teniendo una sentencia nula donde slo se pone el caso, con lo que se permite que el flujo del programa caiga
al omitir las sentencias, como se muestra a continuacin:

switch (letra)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
numvocales++;
break;
case ' ':
numesp++;
break;
default:
numotras++;
break;
}

3.3 Ejercicios
1.
2.
3.

4.

28

Escribir un programa que lea dos caracteres, e imprima su valor cuando se pueda interpretar como
un nmero hexadecimal. Aceptar letras maysculas y minsculas para los valores del 10 al 15.
Leer un valor entero. Suponer que el nmero es un da de la semana. Suponer que 0 corresponde a
Domingo y as sucesivamente. Imprimir el nombre del da.
Dados como entrada 3 enteros representando la fecha como da, mes, ao, imprimir la fecha del da
anterior. Por ejemplo para una entrada como: 1 3 1992 La salida ser: Fecha anterior a 1-3-1992 es
29-02-1992
Escribir un programa el cual lea dos valores enteros. Si el primero es menor que el segundo, que
imprima el mensaje ``Arriba''. Si el segundo es menor que el primero, que imprima el mensaje
``Abajo''. Si los nmeros son iguales, que imprima el mensaje ``igual''. Si hay un error en la lectura de
los datos, que imprima un mensaje conteniendo la palabra ``Error'' y haga exit( 0 );

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 4

CICLOS

29

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

4. CICLOS
En este captulo se revisan los mecanismos de C para repetir un cojunto de instrucciones hasta que se
cumple cierta condicin.
4.1 La sentencia for
La sentencia for tiene el siguiente formato:

for ( expresion1; expresion2; expresion3)


sentencia;
o { bloque de sentencias }
En donde expresion1 se usa para realizar la inicializacin de variables, usando una o varias sentencias, si
se usan varias sentencias deber usarse el operador , para separarlas. Por lo general, establece el valor de
la variable de control del ciclo. expresion2 se usa para la condicin de terminacin del ciclo y
expresion3 es el modificador a la variable de control del ciclo cada vez que la computadora lo repite, pero
tambin puede ser ms que un incremento.
Por ejemplo:

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

genera la siguiente salida a pantalla ...

X=3
X=2
X=1

Todos las siguientes sentencias for son vlidas en C. Las aplicaciones prcticas de tales sentencias no son
importantes aqu, ya que tan slo se intenta ilustrar alguanas caractersticas que pueden ser de utilidad:

for ( x=0; ( (x>3) && (x<9) ); x++ )


for ( x=0, y=4; ( (x>3) && (x<9) ); x++, y+=2)
for ( x=0, y=4, z=4000; z; z/=10)

En el segundo ejemplo se muestra la forma como mltiples expresiones pueden aparecer, siempre y cuando
estn separadas por una coma ,
En el tercer ejemplo, el ciclo continuar iterando hasta que z se convierta en

30

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


4.2 La sentencia while
La sentencia while es otro ciclo o bucle disponible en C. Su formato es:

while ( expresion) sentencia;


donde sentencia puede ser una sentencia vaca, una sentencia nica o un bloque de sentencias que se
repetirn. Cuando el flujo del programa llega a esta instruccin, primero se revisa si la condicin es verdad
para ejecutar la(s) sentencia(s), y despus el ciclo while se repetir mientras la condicin sea verdadera.
Cuando llega a ser falsa, el control del programa pasa a la lnea que sigue al ciclo.
En el siguiente ejemplo se muetra una rutina de entrada desde el teclado, la cual se cicla mientras no se pulse
A:

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

Antes de entrar al ciclo se inicializa la variable carac a nulo. Despus pasa a la sentencia while donde se
comprueba si carac no es igual a 'A', como sea verdad entonces se ejecuta la sentencia del bucle ( carac
= getchar();). La funcin getchar() lee el siguiente carcter del flujo estndar (teclado) y lo devuelve,
que en nuestro ejemplo es el caracter que haya sido tecleado. Una vez que se ha pulsado una tecla, se
asigna a carac y se comprueba la condicin nuevamente. Despus de pulsar A, la condicin llega a ser
falsa porque carac es igual a A, con lo que el ciclo termina.
De lo anterior, se tiene que tanto el ciclo for, como el ciclo while comprueban la condicin en lo alto del
ciclo, por lo que el cdigo dentro del ciclo no se ejecuta siempre.
A continuacin mostramos otro ejemplo:

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

que genera la siguiente salida en pantalla:

x = 3
x = 2
x = 1

31

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Como se observa, dentro del ciclo tenemos ms de una sentencia, por lo que se requiere usar la llave abierta
y la llave cerrada { ... } para que el grupo de sentencias sean tratadas como una unidad.
Como el ciclo while pueda aceptar tambin expresiones, y no solamente condiciones lo siguiente es vlido:

while ( x-- );
while ( x = x + 1 );
while ( x += 5 );

Si se usan este tipo de expresiones, solamente cuando el resultado de x--, x=x+1 o x+=5 sea cero, la
condicin fallar y se podr salir del ciclo.
De acuerdo a lo anterior, podemos realizar una operacin completa dentro de la expresin. Por ejemplo:

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

En este ejemplo se usan las funciones de la biblioteca estndar getchar() -- lee un caracter del teclado y
putchar() escribe un caracter dado en pantalla. El ciclo while proceder a leer del teclado y lo mostrar
hasta que el caracter A sea ledo.
4.3 La sentencia do-while
Al contrario de los ciclos for y while que comprueban la condicin en lo alto del bucle, el bucle do ...
while la examina en la parte baja del mismo. Esta caracterstica provoca que un ciclo do ... while
siempre se ejecute al menos una vez. La forma general del ciclo es:

do {
sentencia;
} while (condicin);
Aunque no son necesarias las llaves cuando slo est presente una sentencia, se usan normalmente por
legibilidad y para evitar confusin (respecto al lector, y no del compilador) con la sentencia while.
En el siguiente programa se usa un ciclo do ... while para leer nmeros desde el teclado hasta que uno
de ellos es menor que o igual a 100:

32

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int main()
{
int num;
do
{
scanf("%d", &num);
} while ( num>100 );
}

Otro uso comn de la estructura do ... while es una rutina de seleccin en un men, ya que siempre se
requiere que se ejecute al menos una vez.

int main()
{
int opc;
printf("1. Derivadas\n");
printf("2. Limites\n");
printf("3. Integrales\n");
do
{
printf("
Teclear una opcion:
scanf("%d", &opc);

");

switch(opc)
{
case 1:
printf("\tOpcion 1 seleccionada\n\n");
break;
case 2:
printf("\tOpcion 2 seleccionada\n\n");
break;
case 3:
printf("\tOpcion 3 seleccionada\n\n");
break;
default:
printf("\tOpcion no disponible\n\n");
break;
}
} while( opc != 1 && opc != 2 && opc != 3);
}

Se muestra un ejemplo donde se reescribe usando do ... while uno de los ejemplos ya mostrados.

33

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


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

4.4 Uso de break y continue


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

int main()
{
int t;
for(t=0; t<100; t++)
{
printf("%d ", t);
if (t==10) break;
}
}

Este programa muestra en pantalla los nmeros del 0 al 10, cuando alcanza el valor 10 se cumple la condicin
de la sentencia if, se ejecuta la sentencia break y sale del ciclo.
La sentencia continue funciona de manera similar a la sentencia break. Sin embargo, en vez de forzar la
salida, continue fuerza la siguiente iteracin, por lo que salta el cdigo que falta para llegar a probar la
condicin. Por ejemplo, el siguiente programa visualizar slo los nmeros pares:

int main()
{
int x;
for( x=0; x<100; x++)
{
if (x%2)
continue;
printf("%d ",x);
}
}

Finalmente se considera el siguiente ejemplo donde se leen valores enteros y se procesan de acuerdo a las
siguientes condiciones. Si el valor que sea ledo es negativo, se desea imprimir un mensaje de error y se
abandona el ciclo. Si el valor es mayor que 100, se ignora y se continua leyendo, y si el valor es cero, se
desea terminar el ciclo.

34

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int main()
{
int valor;
while( scanf("%d", &valor) == 1 && valor != 0)
{
if ( valor<0 )
{
printf("Valor no valido\n");
break;
/* Salir del ciclo */
}
if ( valor>100)
{
printf("Valor no valido\n");
continue;
/* Pasar al principio del ciclo nuevamente */
}
printf("Se garantiza que el valor leido esta entre 1 y
100");
}
}

4.5 Ejercicios
1.
2.

3.

Escribir un programa que lea 5 nmeros y encuentre el promedio, el mximo y el mnimo de esos
valores.
Escribir un programa que lea nmeros hasta que se encuentre el cero. El segundo nmero se
sumar al primero, luego el tercero se restar, el cuarto se sumar, y as se deber seguir alternado
hasta que se llegue al cero. Cuando se llegue a esta condicion deber imprimir el resultado, el total
de operandos de la operacin (sin incluir el cero), y la suma de los operandos que se restaron.
Escribir un programa que lea un valor entero que ser la base para un sistema numrico (binario,
octal o decimal), despus que lea un entero positivo en esa base y que imprima su valor en base 10.
Se debe validar que el nmero pertenezca a esa base. La base ser menor que o igual a 10. El
programa podra tener la siguiente salida:

Entrada
Base
Numero
==============
10
1234
8
77
2
1111
4.

Salida
=========
1234
63
15

Leer tres valores representando lo siguiente:


o El capital (nmero entero de pesos)
o Una tasa de interes en porciento (flotante)
o y un nmero de aos (entero).
Calcular los valores de la suma del capital y el interes compuesto para un perodo dado de aos.
Para cada ao el interes es calculado como: interes = capital * tasa_interes /

100;
el cual se suma al capital

35

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


capital += interes;
Imprimir los valores de moneda con una precisin de dos decimales. Imprimir los valores del inters
compuesto para cada ao al final del perodo. La salida puede ser como la siguiente:

Capital inicial 35000.00 con tasa del 12.50 en 10 aos


Ao
Interes
Suma
-----+-----------+--------1
4375.00
39375.00
2
4921.88
44296.88
3
5537.11
49833.98
4
6229.25
56063.23
5
7007.90
63071.14
6
7883.89
70955.03
7
8869.38
79824.41
8
9978.05
89802.45
9 11225.31
101027.76
10 12628.47
113656.23
5.

Leer un valor positivo, y hacer la siguiente secuencia: si el nmero es par, dividirlo entre 2; si es non,
multiplicarlo por 3 y sumarle 1. Repetir lo anterior hasta que el valor sea 1, imprimiendo cada valor,
tambin se deber imprimir cuantas operaciones de estas son hechas.
Una salida podra ser la siguiente:

El valor inicial es 9
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
El siguiente valor es
Valor fina1 1, numero

28
14
7
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
de pasos 19.

Si el valor ingresado es menor que 1, imprimir un mensaje que contenga la palabra Error y haga

exit(0)

36

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 5

Arreglos y cadenas

37

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

5. Arreglos y cadenas
En el siguiente captulo se presentan los arreglos y las cadenas. Las cadenas se consideran como un arreglo
de tipo char.
5.1 Arreglos unidimensionales y multidimensionales
Los arreglos son una coleccin de variables del mismo tipo que se referencian utilizando un nombre comn.
Un arreglo consta de posiciones de memoria contigua. La direccin ms baja corresponde al primer elemento
y la ms alta al ltimo. Un arreglo puede tener una o varias dimensiones. Para acceder a un elemento en
particular de un arreglo se usa un ndice.
El formato para declarar un arreglo unidimensional es:

tipo nombre_arr [ tamao ]


Por ejemplo, para declarar un arreglo de enteros llamado listanum con diez elementos se hace de la siguiente
forma:

int listanum[10];

En C, todos los arreglos usan cero como ndice para el primer elemento. Por tanto, el ejemplo anterior declara
un arreglo de enteros con diez elementos desde listanum[0] hasta listanum[9].
La forma como pueden ser accesados los elementos de un arreglo, es de la siguiente forma:

listanum[2] = 15; /* Asigna 15 al 3er elemento del arreglo listanum*/


num = listanum[2]; /* Asigna el contenido del 3er elemento a la variable
num */

El lenguaje C no realiza comprobacin de contornos en los arreglos. En el caso de que sobrepase el final
durante una operacin de asignacin, entonces se asignarn valores a otra variable o a un trozo del cdigo,
esto es, si se dimensiona un arreglo de tamao N, se puede referenciar el arreglo por encima de N sin
provocar ningn mensaje de error en tiempo de compilacin o ejecucin, incluso aunque probablemente se
provoque el fallo del programa. Como programador se es responsable de asegurar que todos los arreglos
sean lo suficientemente grandes para guardar lo que pondr en ellos el programa.
C permite arreglos con ms de una dimensin , el formato general es:

tipo nombre_arr [ tam1 ][ tam2 ] ... [ tamN];


Por ejemplo un arreglo de enteros bidimensionales se escribir como:

int tabladenums[50][50];

Observar que para declarar cada dimensin lleva sus propios parntesis cuadrados.
Para acceder los elementos se procede de forma similar al ejemplo del arreglo unidimensional, esto es,

tabladenums[2][3] = 15; /* Asigna 15 al elemento de la 3 fila y la 4


columna*/

38

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


num = tabladenums[25][16];

A continuacin se muestra un ejemplo que asigna al primer elemento de un arreglo bidimensional cero, al
siguiente 1, y as sucesivamente.

main()
{
int t,i,num[3][4];
for(t=0; t<3; ++t)
for(i=0; i<4; ++i)
num[t][i]=(t*4)+i*1;
for(t=0; t<3; ++t)
{
for(i=0; i<4; ++i)
printf("num[%d][%d]=%d
printf("\n");
}

", t,i,num[t][i]);

En C se permite la inicializacin de arreglos, debiendo seguir el siguiente formato:

tipo nombre_arr[ tam1 ][ tam2 ] ... [ tamN] = {lista-valores};


Por ejemplo:

int i[10] = {1,2,3,4,5,6,7,8,9,10};


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

5.2 Cadenas
A diferencia de otros lenguajes de programacin que emplean un tipo denominado cadena string para
manipular un conjunto de simbolos, en C, se debe simular mediante un arreglo de caracteres, en donde la
terminacin de la cadena se debe indicar con nulo. Un nulo se especifica como '\0'. Por lo anterior, cuando
se declare un arreglo de caracteres se debe considerar un carcter adicional a la cadena ms larga que se
vaya a guardar. Por ejemplo, si se quiere declarar un arreglo cadena que guarde una cadena de diez
caracteres, se har como:

char cadena[11];

Se pueden hacer tambin inicializaciones de arreglos de caracteres en donde automticamente C asigna el


caracter nulo al final de la cadena, de la siguiente forma:

char nombre_arr[ tam ]="cadena";

39

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Por ejemplo, el siguiente fragmento inicializa cadena con ``hola'':

char cadena[5]="hola";

El cdigo anterior es equivalente a:

char cadena[5]={'h','o','l','a','\0'};

Para asignar la entrada estndar a una cadena se puede usar la funcin scanf con la opcin %s (observar que
no se requiere usar el operador &), de igual forma para mostrarlo en la salida estndar.
Por ejemplo:

main()
{
char nombre[15], apellidos[30];
printf("Introduce tu nombre: ");
scanf("%s",nombre);
printf("Introduce tus apellidos: ");
scanf("%s",apellidos);
printf("Usted es %s %s\n",nombre,apellidos);
}

El lenguaje C no maneja cadenas de caracteres, como se hace con enteros o flotantes, por lo que lo siguiente
no es vlido:

main()
{
char nombre[40], apellidos[40], completo[80];
nombre="Jos Mara";
/* Ilegal */
apellidos="Morelos y Pavn";
/* Ilegal */
completo="Gral."+nombre+appellidos; /* Ilegal */
}

5.3 Ejercicios
1.

2.

Escribir un programa que lea un arreglo de cualquier tipo (entero, flotante, char), se podra pedir al
usuario que indique el tipo de arreglo, y tambin escribir un programa que revise el arreglo para
encontrar un valor en particular.
Leer un texto, un caracter a la vez desde la entrada estndar (que es el teclado), e imprimir cada
lnea en forma invertida. Leer hasta que se encuentre un final-de-datos (teclar CONTROL-D para
generarlo).
El programa podra probarse tecleando progrev | progrev para ver si una copia exacta de la
entrada original es recreada.

40

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Para leer caracteres hasta el final de datos, se puede usar un ciclo como el siguiente

char ch;
while( ch=getchar(), ch>=0 ) /* ch < 0 indica fin-de-datos */
o

char ch;
while( scanf( "%c", &ch ) == 1 ) /* se lee un caracter */
3.

Escribir un programa para leer un texto hasta el fin-de-datos, y mostrar una estadstica de las
longitudes de las palabras, esto es, el nmero total de palabras de longitud 1 que hayan ocurrido, el
total de longitud 2 y as sucesivamente.
Define una palabra como una secuencia de caracteres alfabticos. Se debern permitir palabras
hasta de una longitud de 25 letras.
Una salida tpica podra ser como esta:

longitud
longitud
longitud
longitud

41

1 : 16 ocurrencias
2 : 20 ocurrencias
3 : 5 ocurrencias
4 : 2 ocurrencias
........

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 6

Funciones

42

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

6. Funciones
Una funcin es un conjunto de declaraciones, definiciones, expresiones y sentencias que realizan una tarea
especfica.
El formato general de una funcin en C es

especificador_de_tipo nombre_de_funcin( lista_de_parmetros )


{
variables locales
cdigo de la funcin
}
El especificador_de_tipo indica el tipo del valor que la funcin devolver mediante el uso de return. El valor
puede ser de cualquier tipo vlido. Si no se especfica un valor, entonces la computadora asume por defecto
que la funcin devolver un resultado entero. No se tienen siempre que incluir parmetros en una funcin. la
lista de parmetros puede estar vaca.
Las funciones terminan y regresan automticamente al procedimiento que las llam cuando se encuentra la
ltima llave }, o bien, se puede forzar el regreso antes usando la sentencia return. Ademas del uso
sealado la funcin return se usa para devolver un valor.
Se examina a continuacin un ejemplo que encuentra el promedio de dos enteros:

float encontprom(int num1, int num2)


{
float promedio;
promedio = (num1 + num2) / 2.0;
return(promedio);
}
main()
{
int a=7, b=10;
float resultado;
resultado = encontprom(a, b);
printf("Promedio=%f\n",resultado);
}

6.1 Funciones void


Las funciones void dan una forma de emular, lo que en otros lenguajes se conocen como procedimientos
(por ejemplo, en PASCAL). Se usan cuando no requiere regresar un valor. Se muestra un ejemplo que
imprime los cuadrados de ciertos nmeros.

43

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


void cuadrados()
{
int contador;
for( contador=1; contador<10; contador++)
printf("%d\n",contador*contador);
}
main()
{
cuadrados();
}

En la funcin cuadrados no esta definido ningn parmetro, y por otra parte tampoco se emplea la sentencia
return para regresar de la funcin.
6.2 Funciones y arreglos
Cuando se usan un arreglo como un argumento a la funcin, se pasa slo la direccin del arreglo y no la copia
del arreglo entero. Para fines prcticos podemos considerar el nombre del arreglo sin ningn ndice como la
direccin del arreglo.
Considerar el siguiente ejemplo en donde se pasa un arreglo a la funcin imp_rev, observar que no es
necesario especificar la dimensin del arreglo cuando es un parmetro de la funcin.

void imp_rev(char s[])


{
int t;
for( t=strlen(s)-1; t>=0; t--)
printf("%c",s[t]);
}
main()
{
char nombre[]="Facultad";
imp_rev(nombre);
}

Observar que en la funcin imp_rev se usa la funcin strlen para calcular la longitud de la cadena sin
incluir el terminador nulo. Por otra parte, la funcin imp_rev no usa la sentencia return ni para terminar
de usar la funcin, ni para regresar algn valor.
Se muestra otro ejemplo,

44

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


float enconprom(int tam, float lista[])
{
int i;
float suma = 0.0;
for ( i=0; i<tam; i++)
suma += lista[i];
return(suma/tam);
}
main()
{
float numeros[]={2.3, 8.0, 15.0, 20.2, 44.01, -3.0, -2.9};
printf("El promedio de la lista es %f\n", enconprom(7,numeros) );
}

Para el caso de que se tenga que pasar un arreglo con ms de una dimensin, no se indica la primera
dimensin pero, el resto de las dimensiones deben sealarse. Se muestra a continuacin un ejemplo:

void imprtabla(int tamx,int tamy, float tabla[][5])


{
int x,y;
for ( x=0; x<tamx; x++ )
{
for ( y=0; y<tamy; y++ )
printf("t[%d][%d]=%f",x,y,tabla[x][y]);
printf("\n");
}
}

6.3 Prototipos de funciones


Antes de usar una funcin C debe tener conocimiento acerca del tipo de dato que regresar y el tipo de los
parmetros que la funcin espera.
El estndar ANSI de C introduj una nueva (mejor) forma de hacer lo anterior respecto a las versiones previas
de C.
La importancia de usar prototipos de funciones es la siguiente:

Se hace el cdigo ms estructurado y por lo tanto, ms fcil de leer.


Se permite al compilador de C revisar la sintaxis de las funciones llamadas.

Lo anterior es hecho, dependiendo del alcance de la funcin. Bsicamente si una funcin ha sido definida
antes de que sea usada (o llamada), entonces se puede usar la funcin sin problemas.
Si no es as, entonces la funcin se debe declarar. La declaracin simplemente maneja el tipo de dato que la
funcin regresa y el tipo de par^o'ametros usados por la funcin.
Es una prctica usual y conveniente escribir el prototipo de todas las funciones al principio del programa, sin
embargo esto no es estrictamente necesario.

45

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Para declarar un prototipo de una funcin se indicar el tipo de dato que regresar la funcin, el nombre de la
funcin y entre parntesis la lista del tipo de los parmetros de acuerdo al orden que aparecen en la definicin
de la funcin. Por ejemplo:

int longcad(char []);

Lo anterior declara una funcin llamada longcad que regresa un valor entero y acepta una cadena como
parmetro.
6.4 Ejercicios
1.

2.
3.

Escribir una funcin ``reemplaza'', la cual toma una cadena como parmetro, le reemplaza todos los
espacios de la cadena por un guin bajo, y devuelve el nmero de espacios reemplazados. Por
ejemplo:

char cadena[] = "El gato negro";


n = reemplaza( cadena );
deber devolver:

cadena convertida "El_gato_negro"


n = 2
4.
5.

46

Escribir un programa que lea una lnea de texto en un buffer (una cadena de caracteres) usando la
funcin gets y calcule la longitud de la lnea (NO usar la funcin strlen).
Modificar el programa anterior para que lea un archivo de texto. El archivo deber redireccionarse al
programa, debiendo mostrar el contenido del mismo. En caso de que se lea una lnea con longitud 0
deber terminar el programa.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 6

Estructuras

47

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

7. Estructuras
7.1 deficicin y uso Estructuras
En C una estructura es una coleccin de variables que se referencian bajo el mismo nombre. Una estructura
proporciona un medio conveniente para mantener junta informacin que se relaciona. Una definicin de
estructura forma una plantilla que se puede usar para crear variables de estructura. Las variables que forman
la estructura son llamados elementos estructurados.
Generalmente, todos los elementos en la estructura estn relacionados lgicamente unos con otros. Por
ejemplo, se puede representar una lista de nombres de correo en una estructura. Mediante la palabra clave
struct se le indica al compilador que defina una plantilla de estructura.

struct direc
{
char nombre[30];
char calle[40];
char ciudad[20];
char estado[3];
unsigned int codigo;
};
Con el trozo de cdigo anterior no ha sido declarada ninguna variable, tan slo se ha definido el formato. Para
declarar una variable, se har como sigue:

struct direc info_direc;

Se pueden declarar una o ms variables cuando se define una estructura entre ) y ;. Por ejemplo:

struct direc
{
char nombre[30];
char calle[40];
char ciudad[20];
char estado[3];
unsigned int codigo;
} info_direc, binfo, cinfo;
observar que direc es una etiqueta para la estructura que sirve como una forma breve para futuras
declaraciones. Como en este ltima declaracin se indican las variables con esta estructura, se puede omitir
el nombre de la estructura tipo.
Las estructuras pueden ser tambin preinicializadas en la declaracin:

struct direc info_direc={"Vicente Fernandez","Fantasia


2000","Dorado","MMX",12345};

Para referenciar o accesar un miembro (o campo) de una estructura, C proporciona el operador punto ., por
ejemplo, para asignar a info_direc otro cdigo, lo hacemos como:

info_direc.codigo=54321;

48

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


7.2 Definicin de nuevos tipos de datos
Se sealo previamente (seccin 2.4.1) que typedef se puede usar para definir nuevos nombres de datos
explictamente, usando algunos de los tipos de datos de C, donde su formato es:
typedef <tipo> <nombre>;
Se puede usar typedef para crear nombres para tipos ms complejos, como una estructura, por ejemplo:

typedef struct direc


{
char nombre[30];
char calle[40];
char ciudad[20];
char estado[3];
unsigned int codigo;
} sdirec;
sdirec info_direc={"Vicente Fernandez","Fantasia
2000","Dorado","MMX",12345};
en este caso direc sirve como una etiqueta a la estructura y es opcional, ya que ha sido definido un nuevo
tipo de dato, por lo que la etiqueta no tiene mucho uso, en donde sdirec es el nuevo tipo de datos e
info_direc es una variable del tipo sdirec, la cual es una estructura.
Con C tambin se pueden tener arreglos de estructuras:

typedef struct direc


{
char nombre[30];
char calle[40];
char ciudad[20];
char estado[3];
unsigned int codigo;
} info_direc;
info_direc artistas[1000];
por lo anterior, artistas tiene 1000 elementos del tipo info_direc. Lo anterior podra ser accesado de
la siguiente forma:

artistas[50].codigo=22222;

49

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 8

Apuntadores

50

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

8. Apuntadores
Los apuntadores son una parte fundamental de C. Si usted no puede usar los apuntadores apropiadamente
entonces esta perdiendo la potencia y la flexibilidad que C ofrece bsicamente. El secreto para C esta en el
uso de apuntadores.
C usa los apuntadores en forma extensiva. Porqu?

Es la nica forma de expresar algunos clculos.


Se genera cdigo compacto y eficiente.
Es una herramienta muy poderosa.

C usa apuntadores explcitamente con:

Es la nica forma de expresar algunos clculos.


Se genera cdigo compacto y eficiente.
Es una herramienta muy poderosa.

C usa apuntadores explcitamente con:

Arreglos,
Estructuras y
Funciones

8.1 Definicin de un apuntador


Un apuntador es una variable que contiene la direccin en memoria de otra variable. Se pueden tener
apuntadores a cualquier tipo de variable.
El operador unario o mondico & devuelve la direccin de memoria de una variable.
El operador de indireccin o dereferencia * devuelve el ``contenido de un objeto apuntado por un
apuntador''.
Para declarar un apuntador para una variable entera hacer:

int *apuntador;

Se debe asociar a cada apuntador un tipo particular. Por ejemplo, no se puede asignar la direccin de un
short int a un long int.
Para tener una mejor idea, considerar el siguiente cdigo:

51

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


main()
{
int x = 1, y = 2;
int *ap;
ap = &x;
y = *ap;
x = ap;
*ap = 3;
}

Cuando se compile el cdigo se mostrar el siguiente mensaje:

warning: assignment makes integer from pointer without a cast.


Con el objetivo de entender el comportamiento del cdigo supongamos que la variable x esta en la localidad
de la memoria 100, y en 200 y ap en 1000. Nota: un apuntador es una variable, por lo tanto, sus valores
necesitan ser guardados en algn lado.

int x = 1, y = 2;
int *ap;
ap = &x;

100
x 1

200
y 2

1000
ap 100

Las variables x e y son declaradas e inicializadas con 1 y 2 respectivamente, ap es declarado como un


apuntador a entero y se le asigna la direccin de x (&x). Por lo que ap se carga con el valor 100.

y = *ap;

100
x 1

200
y 1

1000
ap 100

Despus y obtiene el contenido de ap. En el ejemplo ap apunta a la localidad de memoria 100 -- la localidad
de x. Por lo tanto, y obtiene el valor de x -- el cual es 1.

x = ap;

100

200

x 100 y 1

52

1000
ap 100

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Como se ha visto C no es muy estricto en la asignacin de valores de diferente tipo (apuntador a entero). As
que es perfectamente legal (aunque el compilador genera un aviso de cuidado) asigna el valor actual de ap a
la variable x. El valor de ap en ese momento es 100.

*ap = 3;

100
x 3

200
y 1

1000
ap 100

Finalmente se asigna un valor al contenido de un apuntador (*ap).


Importante: Cuando un apuntador es declarado apunta a algn lado. Se debe inicializar el apuntador antes de
usarlo. Por lo que:

main()
{
int *ap;
*ap = 100;
}

puede generar un error en tiempo de ejecucin o presentar un comportamiento errtico.


El uso correcto ser:

main()
{
int *ap;
int x;
ap = &x;
*ap = 100;
}

Con los apuntadores se puede realizar tambin aritmtica entera, por ejemplo:

main()
{
float *flp, *flq;
*flp = *flp + 10;
++*flp;
(*flp)++;
flq = flp;
}

NOTA: Un apuntador a cualquier tipo de variables es una direccin en memoria -- la cual es una direccin
entera, pero un apuntador NO es un entero.

53

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


La razn por la cual se asocia un apuntador a un tipo de dato, es por que se debe conocer en cuantos bytes
esta guardado el dato. De tal forma, que cuando se incrementa un apuntador, se incrementa el apuntador por
un ``bloque'' de memoria, en donde el bloque esta en funcin del tamao del dato.
Por lo tanto para un apuntador a un char, se agrega un byte a la direccin y para un apuntador a entero o a
flotante se agregan 4 bytes. De esta forma si a un apuntador a flotante se le suman 2, el apuntador entonces
se mueve dos posiciones float que equivalen a 8 bytes.
8.2 Apuntadores y Funciones
Cuando C pasa argumentos a funciones, los pasa por valor, es decir, si el parmetro es modificado dentro de
la funcin, una vez que termina la funcin el valor pasado de la variable permanece inalterado.
Hay muchos casos que se quiere alterar el argumento pasado a la funcin y recibir el nuevo valor una vez que
la funcin ha terminado. Para hacer lo anterior se debe usar una llamada por referencia, en C se puede
simular pasando un puntero al argumento. Con esto se provoca que la computadora pase la direccin del
argumento a la funcin.
Para entender mejor lo anterior consideremos la funcin swap() que intercambia el valor de dos argumentos
enteros:

void swap(int *px, int *py);


main()
{
int x, y;
x = 10;
y = 20;
printf("x=%d\ty=%d\n",x,y);
swap(&x, &y);
printf("x=%d\ty=%d\n",x,y);
}
void swap(int *px, int *py)
{
int temp;
temp = *px;
*px = *py;
*py = temp;

/* guarda el valor de la direccion x */


/* pone y en x */
/* pone x en y */

8.3 Apuntadores y arreglos


Existe una relacin estrecha entre los punteros y los arreglos. En C, un nombre de un arreglo es un ndice a la
direccin de comienzo del arreglo. En esencia, el nombre de un arreglo es un puntero al arreglo. Considerar lo
siguiente:

int a[10], x;
int *ap;
ap = &a[0];

54

/* ap apunta a la direccion de a[0] */

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


x = *ap;
*/

/* A x se le asigna el contenido de ap (a[0] en este caso)

*(ap + 1) = 100;
usando ap*/

/* Se asigna al segundo elemento de 'a' el valor 100

Como se puede observar en el ejemplo la sentencia a[t] es idntica a ap+t. Se debe tener cuidado ya que C
no hace una revisin de los lmites del arreglo, por lo que se puede ir fcilmente ms alla del arreglo en
memoria y sobreescribir otras cosas.
C sin embargo es mucho ms stil en su relacin entre arreglos y apuntadores. Por ejemplo se puede teclear
solamente:

ap = a; en vez de ap = &a[0]; y tambin *(a + i) en vez de a[i], esto es, &a[i] es equivalente
con a+i.
Y como se ve en el ejemplo, el direccionamiento de apuntadores se puede expresar como:

a[i] que es equivalente a *(ap + i)

Sin embargo los apuntadores y los arreglos son diferentes:

Un apuntador es una variable. Se puede hacer ap = a y ap++.


Un arreglo NO ES una variable. Hacer a = ap y a++ ES ILEGAL.

Este parte es muy importante, asegrese haberla entendido.


Con lo comentado se puede entender como los arreglos son pasados a las funciones. Cuando un arreglo es
pasado a una funcin lo que en realidad se le esta pasando es la localidad de su elemento inicial en memoria.
Por lo tanto:

strlen(s) es equivalente a strlen(&s[0])


Esta es la razn por la cual se declara la funcin como:

int strlen(char s[]); y una declaracin equivalente es int strlen(char *s);


ya que char s[] es igual que char *s.
La funcin strlen() es una funcin de la biblioteca estndar que regresa la longitud de una cadena. Se muestra
enseguida la versin de esta funcin que podra escribirse:

55

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int strlen(char *s)
{
char *p = s;
while ( *p != '\0' )
p++;
return p - s;
}

Se muestra enseguida una funcin para copiar una cadena en otra. Al igual que en el ejercicio anterior existe
en la biblioteca estndar una funcin que hace lo mismo.

void strcpy(char *s, char *t)


{
while ( (*s++ = *t++) != '\0' );
}

En los dos ltimos ejemplos se emplean apuntadores y asignacin por valor. Nota: Se emplea el uso del
caracter nulo con la sentencia while para encontrar el fin de la cadena.

56

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 9

Biblioteca <stdlib.h>

57

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

9. Biblioteca <stdlib.h>
Para usar todas las funciones de sta biblioteca se debe tener la siguiente directiva

#include <stdlib.h>

Las funciones de la biblioteca pueden ser agrupadas en tres categoras bsicas:

Aritmticas;
Nmeros aleatorios; y
Conversin de cadenas.

El uso de todas las funciones es sencillo. Se consideran dentro del captulo en forma breve.
9.1 Funciones aritmticas
Hay cuatro funciones enteras bsicas:

int abs(int j);


long int labs(long int j);
div_t div(int numer, int denom);
ldiv_t ldiv(long int numer, long int denom);

Fundamentalmente hay dos funciones para enteros y para compatibilidad con enteros largos.

abs() La funcin regresa el valor absoluto del argumento entero j.


div() Calcula el valor numer entre denom y devuelve el cociente y el resto en una estructura
llamada div_t que contiene dos miembros llamados quot y rem.

La estructura div_t esta definida en stdlib.h como sigue:

typedef struct {
int quot;
int rem;
} div_t;

/* cociente */
/* residuo */

La estructura ldiv_t es definida de una forma similar.


Se muestra un ejemplo donde se hace uso de la funcin div_t:

58

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


#include <stdlib.h>
main()
{
int num=8, den=3;
div_t res;
res = div(num,den);
printf("Respuesta:\n\t Cociente = %d\n\t Residuo = %d\n",
res.quot, res.rem);
}

que genera la siguiente salida:

Respuesta:
Cociente = 2
Residuo = 2

9.2 Nmeros aleatorios


Los nmeros aleatorios son tiles en programas que necesitan simular eventos aleatorios, tales como juegos,
simulaciones y experimentos. En la prctica ninguna funcin produce datos aleatorios verdaderos -- las
funciones producen nmeros pseudo-aleatorios. Los nmeros aleatorios son calculados a partir de una
frmula dada (los distintos generadores usan diferentes frmulas) y las secuencias de nmeros que son
producidas se repiten. Una semilla (seed) es usualmente inicializada para que la secuencia sea generada.
Por lo tanto, si la semilla es siempre inicializada con el mismo valor todo el tiempo, el mismo conjunto ser
siempre calculado.
Una tcnica comn para introducir ms aleatoriedad en el generador de nmeros aleatorios es usando el
tiempo y la fecha para inicializar la semilla, ya que ste siempre estar cambiando.
Hay muchas funciones de nmeros (pseudo) aleatorios en la biblioteca estndar. Todas ellas operan con la
misma idea bsica pero generan secuencias diferentes de nmeros (basadas en funciones generadoras
diferentes) sobre rangos diferentes de nmeros.
El conjunto ms simple de funciones es:

int rand(void);
void srand(unsigned int semilla);

rand() La funcin devuelve un entero pseudo-aleatorio entre 0 y


(RAND_MAX).
srand() Establece su argumento como la semilla de una nueva serie de enteros pseudo-aleatorios.

Un ejemplo sencillo del uso del tiempo de la fecha es inicializando la semilla a travs de una llamada:

srand( (unsigned int) time( NULL ) );

59

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


El siguiente programa tarjeta.c muestra el uso de estas funciones para simular un paquete de tarjetas
que esta siendo revueltas.

/*
** Se usan numeros aleatorios para revolver las "tarjetas" de la baraja.
** El segundo argumento de la funcion indica el numero de tarjetas.
** La primera vez que esta funcion es llamada, srand es
** llamada para inicializar el generador de numeros aleatorios.
*/
#include <stdlib.h>
#include <time.h>
#define VERDADERO
1
#define FALSO
0
void intercambiar( int *baraja, int n_cartas )
{
int
i;
static int
primera_vez = VERDADERO;
/*
** Inicializar el generador de numeros con la fecha actual
** si aun no se ha hecho.
*/
if( primera_vez ){
primera_vez = FALSO;
srand( (unsigned int)time( NULL ) );
}
/*
** "intercambiar" empleando pares de cartas.
*/
for( i = n_cartas - 1; i > 0; i -= 1 ){
int
alguno;
int
temp;
alguno = rand() % i;
temp = baraja[ alguno ];
baraja[ alguno ] = baraja[ i ];
baraja[ i ] = temp;
}
}

9.3 Conversin de cadenas


Existen unas cuantas funciones para convertir cadenas a enteros, enteros largos y valores flotantes. Estas
son:

60

double atof(const char *cadena) Convierte una cadena a un valor flotante.


int atoi(const char *cadena) Convierte una cadena a un valor entero.
int atol(const char *cadena) Convierte una cadena a un valor entero largo.
double strtod(const char *cadena, char **finap) Convierte una cadena a un valor de punto flotante.
double strtol(const char *cadena, char *finap, int base) Convierte una cadena a un entero largo
de acuerdo a una base dada, la cual deber estar entre 2 y 36 inclusive.
unsigned long strtoul(const char *cadena, char *finap, int base) Convierte una cadena a un
entero largo sin signo.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Varias de las funciones se pueden usar en forma directa, por ejemplo:

char
char
char
char
char
char
char

*cad1 =
*cad2 =
*cad3 =
*cad4 =
*cad5 =
*cad6 =
*cad7;

"100";
"55.444";
"
1234";
"123cuatro";
"invalido123";
"123E23Hola";

int i;
float f:
i
f
i
i
i
f

=
=
=
=
=
=

atoi(cad1);
/* i =
atof(cad2);
/* f =
atoi(cad3);
/* i =
atoi(cad4);
/* i =
atoi(cad5);
/* i =
strtod(cad6, &cad7);

100 */
55.44 */
1234 */
123 */
0 */
/* f=1.230000E+25 y cad7=hola*/

Nota:

Los caracteres en blanco son saltados.


Caracteres ilegales son ignorados.
Si la conversin no puede ser hecha se regresa cero y errno es puesta con el valor ERANGE.

9.4 Bsqueda y ordenamiento


La biblioteca stdlib.h tiene dos funciones tiles para hacer bsqueda y ordenamiento de datos de
cualquier tipo. La funcin qsort() ya fue vista previamente en la seccin 10.3.
Para completar la lista se anota el prototipo, pero para ver un ejemplo pasar al captulo indicado.
La funcin qsort de la biblioteca estndar es muy til, ya que esta diseada para ordenar un arreglo por un
valor llave de cualquier tipo en orden ascendente, con tal de que los elementos del arreglo sean de un tipo fijo.
El prototipo de la funcin de acuerdo a stdlib.h es:

void qsort(void *base, size_t nmiemb, size_t tam,


int (*compar)(const void *, const void *));

Similarmente, hay una funcin para bsqueda binaria, bsearch() la cual tiene el siguiente prototipo en
stdlib.h como:

void *bsearch(const void *key, const void *base, size_t nmemb,


size_t size, int (*compar)(const void *, const void *));

A continuacin se muestra un ejemplo que hace uso de la funcin bsearch():

#define TAM 10

61

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


#include <stdio.h>
#include <stdlib.h>
typedef struct {
int llave;
char informacion[30];
} Registro;
int compara_registro(void const *i, void const *j)
{
int a, b;
a = ((Registro *) i)->llave;
b = ((Registro *) j)->llave;
return a - b;
}
main()
{
Registro llave;
Registro *resp;
Registro arreglo[TAM];
int long_arreglo = TAM;
arreglo[0].llave = -43; arreglo[1].llave = -9; arreglo[2].llave =
0;
arreglo[3].llave = 3; arreglo[4].llave = 4; arreglo[5].llave = 9;
arreglo[6].llave = 10; arreglo[7].llave = 12; arreglo[8].llave =
30;
arreglo[9].llave = 203;
printf("Introduce el valor de la llave que se buscara en el
arreglo: ");
scanf("%d",&llave.llave); /* valor del indice que sera buscado */
resp = (Registro *) bsearch(&llave, arreglo, long_arreglo,
sizeof(Registro),
compara_registro);
if (resp != NULL )
printf("Se localizo la llave %d\n",resp->llave);
else
printf("No se localizo ningun elemento con la llave %d\n",
llave.llave);
}

La funcin bsearch() regresa un apuntador al registro que coincide con la llave dada, o bien, el valor NULL
si no encuentra el registro.
Observar que el tipo del argumento de la llave debe ser del mismo tipo que la del arreglo de los elementos (en
nuestro caso Registro).
9.5 Ejercicios
1.
2.

62

Escribir un programa que simule el lanzamiento de un dado.


Escribir un programa que simule el melate, en donde se seleccionan 6 nmeros enteros en un rango
de 1 al 44

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


3.

63

Escribir un programa que lea un nmero de la lnea de entrada y genere un nmero flotante aleatorio
en el rango de 0 a el nmero de entrada.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 10

Biblioteca <math.h>

64

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

10. Biblioteca <math.h>


La biblioteca de matemticas es relativamente fcil de usar, al igual que las vistas previamente. Se debe
incluir la directiva de preprocesamiento #include <math.h>, adems de recordar de ligar la biblioteca de
matemticas al compilar:

gcc progmat.c -o progmat -lm

Un error comn es el olvidar incluir el archivo <math.h>.


10.1 Funciones matemticas
Se muestra a continuacin una lista de funciones matemticas. Son fciles de usar y algunas de ellas han
sido ya usadas previamente. No se proporciona ejemplo de las mismas.

double
double
double
double

acos(double x) Calcula el arco coseno de x.


asin(double x) Calcula el arco seno de x.
atan(double x) Devuelve el arco tangente en radianes.
atan2(double y, double x) Calcula el arco tangente de las dos variables x e y.

Es similar a calcular el arco tangente de y / x, excepto en que los signos de ambos argumentos son
usados para determinar el cuadrante del resultado.
double ceil(double x) Redondea x hacia arriba al entero ms cercano.
double cos(double x) devuelve el coseno de x, donde x est dado en radianes.
double cosh(double x) Devuelve el coseno hiperblico de x.
double exp(double x) Devuelve el valor de e (la base de los logaritmos naturales) elevado a
la potencia x.
double fabs(double x) Devuelve el valor absoluto del nmero en punto flotante x.
double floor(double x) Redondea x hacia abajo al entero ms cercano.
double fmod(double x, double y) Calcula el resto de la divisin de x entre y. El valor
devuelto es x - n * y, donde n es el cociente de x / y.
double frexp(double x, int *exp) Se emplea para dividir el nmero x en una fraccin
normalizada y un exponente que se guarda en exp.

65

x=res X 2exp

long int labs(long int j) Calcula el valor absoluto de un entero largo.


double ldexp(double x, int exp) Devuelve el resultado de multiplicar el nmero x por 2
elevado a exp (inversa de frexp).
double log(double x); Devuelve el logaritmo neperiano de x.
double log10(double x) Devuelve el logaritmo decimal de x.
double modf(double x, double *iptr) Divide el argumento x en una parte entera y una

parte fraccional. La parte entera se guarda en iptr.


double pow(double x, double y) Devuelve el valor de x elevado a y.
double sin(double x) Devuelve el seno de x.
double sinh(double x) Regresa el seno hiperblico de x.
double sqrt(double x) Devuelve la raz cuadrada no negativa de x.
double tan(double x) Devuelve la tangente de x.
double tanh(double x) Devuelve la tangente hiperblica de x.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


10.2 Constantes matemticas
La biblioteca de matemticas define varias constantes (por lo general desechadas). Siempre es aconsejable
usar estas definiciones.

66

M_E La base de los logaritmos naturales e.


M_LOG2E El logaritmo de e de base 2.
M_LOG10E El logaritmo de e de base 10.
M_LN2 El logartimo natural de 2.
M_LN10 El logaritmo natural de 10.

M_PI

M_PI_2

M_PI_4

M_1_PI

M_2_PI

M_2_SQRTPI
M_SQRT2 La raz cuadrada positiva de 2
M_SQRT1_2 La raz cuadrada positiva de 1/2

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 11

Manejo de cadenas
Biblioteca <string.h>

67

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

11. Manejo de cadenas <string.h>


Recordando la presentacin de arreglos hecha (captulo 5) en donde las cadenas estn definidas como un
arreglo de caracteres o un apuntador a una porcin de memoria conteniendo caracteres ASCII. Una cadena
en C es una secuencia de cero o ms caracteres seguidas por un caracter NULL o \0:

Es importante preservar el caracter de terminacin NULL, ya que con ste es como C define y maneja las
longitudes de las cadenas. Todas las funciones de la biblioteca estndar de C lo requieren para una operacin
satisfactoria.
En general, aparte de algunas funciones restringidas en longitud (strncat(), strncmp() y
strncpy()), al menos que se creen cadenas a mano, no se debern encontrar problemas. Se debern usar
las funciones para manejo de cadenas y no tratar de manipular las cadenas en forma manual desmantelando
y ensamblando cadenas.
11.1 Funciones bsicas para el manejo de cadenas
Todas las funciones para manejo de cadenas tienen su prototipo en:

#include <string.h>

Las funciones ms comunes son descritas a continuacin:

68

char *strcpy(const char *dest, const char *orig) -- Copia la cadena de caracteres apuntada por orig
(incluyendo el carcter terminador '\0') al vector apuntado por dest. Las cadenas no deben
solaparse, y la de destino, debe ser suficientemente grande como para alojar la copia.
int strcmp(const char *s1, const char *s2) -- Compara las dos cadenas de caracteres s1 y s2.
Devuelve un entero menor, igual o mayor que cero si se encuentra que s1 es, respectivamente,
menor que, igual a, o mayor que s2.
char *strerror(int errnum) -- Devuelve un mensaje de error que corresponde a un nmero de error.
int strlen(const char *s) -- Calcula la longitud de la cadena de caracteres.
char *strncat(char *s1, const char *s2, size_t n) -- Agrega n caracteres de s2 a s1.
int strncmp(const char *s1, char *s2, size_t n) -- Compara los primeros n caracteres de dos cadenas.
char *strncpy(const char *s1, const char *s2, size_t n) -- Copia los primeros n caracteres de s2 a s1.
strcasecmp(const char *s1, const char *s2) -- versin que ignora si son maysculas o minsculas de
strcmp().
strncasecmp(const char *s1, const char *s2, size_t n) -- versin insensible a maysculas o
minsculas de strncmp() que compara los primeros n caracteres de s1.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


El uso de muchas funciones es directo, por ejemplo:

char *s1 = "Hola";


char *s2;
int longitud;
longitud = strlen("Hola");
(void) strcpy(s2,s1);

/* long = 4 */

Observar que tanto strcat() y strcopy() regresan una copia de su primer argumento, el cual es el
arreglo destino. Observar tambin que orden de los argumentos es arreglo destino seguido por arreglo fuente
lo cual a veces es una situacin para hacerlo incorrectamente.
La funcin strcmp() compara lexicogrficamente las dos cadenas y regresa:

Menor que cero -- si s1 es lxicamente menor que s2;


Cero -- si s1 y s2 son lxicamente iguales;
Mayor que cero -- si s1 es lxicamente mayor que s2;

Las funciones de copiado strncat(), strncmp() y strncpy() son versiones ms restringidas que sus
contrapartes ms generales. Realizan una tarea similar, pero solamente para los primeros n caracteres.
Observar que el caracter de terminacin NULL podra ser violado cuando se usa estas funciones, por ejemplo:

char *s1 = "Hola";


char *s2 = 2;
int longitud = 2;
(void) strncpy(s2, s1, longitud); /* s2 = "Ho" */

donde s2 no tiene el terminador NULL.


11.1.1 Bsqueda en cadenas
La biblioteca tambin proporciona varias funciones de bsqueda en cadenas.

69

char *strchr(const char *s, int c) -- Devuelve un puntero a la primera ocurrencia del carcter c en la
cadena de caracteres s.
char *strrchr(const char *s, int c) -- Encuentra la ltima ocurrencia del caracter c en la cadena.
char *strstr(const char *s1, const char *s2) -- Localiza la primera ocurrencia de la cadena s2 en la
cadena s1.
char *strpbrk(const char *s1, const char *s2) -- Regresa un apuntador a la primera ocurrencia en la
cadena s1 de cualquier carcter de la cadena s2, o un apuntador nulo si no hay un caracter de s2
que exista en s1.
size_t strspn(const char *s1, const char *s2) -- Calcula la longitud del segmento inicial de s1 que
consta nicamente de caracteres en s2.
size_t strcspn(const char *s1, const char *s2) -- Regresa el nmero de caracteres al principio de s1
que no coinciden con s2.
char *strtok(char *s1, const char *s2) -- Divide la cadena apuntada a s1 en una secuencia de
``tokens'', cada uno de ellos esta delimitado por uno o ms caracteres de la cadena apuntada por s2.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Las funciones strchr() y strrchr() son las ms simples de usar, por ejemplo:

char *s1 = "Hola";


char *resp;
resp = strchr(s1,'l');

Despus de la ejecucin, resp apunta a la localidad s1 + 2.


La funcin strpbrk() es una funcin ms general que busca la primera ocurrencia de cualquier grupo de
caracteres, por ejemplo:

char *s1 = "Hola";


char *resp;
res = strpbrk(s1,"aeiou");

En este caso, resp apunta a la localidad s1 + 1, la localidad de la primera o.


La funcin strstr() regresa un apuntador a la cadena de bsqueda especificada o un apuntador nulo si la
cadena no es encontrada. Si s2 apunta a una cadena de longitud cero (esto es, la cadena ""), la funcin
regres s1. Por ejemplo:

char *s1 = "Hola";


char *resp;
resp = strstr(s1,"la");

la cual tendr resp = s1 + 2.


La funcin strtok() es un poco ms complicada en cuanto a operacin. Si el primer argumento no es
NULL entonces la funcin encuentra la posicin de cualquiera de los caracteres del segundo argumento. Sin
embargo, la posicin es recordada y cualquir llamada subsecuente a strtok() iniciar en sa posicin si
en estas subsecuentes llamadas el primer argumento no es NULL. Por ejemplo, si deseamos dividir la cadena
s1 usando cada espacio e imprimir cada ``token'' en una nueva lnea haramos lo siguiente:

char s1[] = "Hola muchacho grande";


char *t1;
for ( t1 = strtok(s1," ");
t1 != NULL;
t1 = strtok(NULL, " ") )
printf("%s\n",t1);

Se emplea un ciclo for en una forma no regular de conteo:

70

En la inicializacin se llama a la funcin strtok() con la cadena s1.


Se termina cuando t1 es NULL.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

Se esta asignando tokens de s1 a t1 hasta la terminacin llamando a strtok() con el primer


argumento NULL.

11.2 Prueba y conversin de caracteres <ctype.h>


Una biblioteca relacionada #include <ctype.h> la cual contiene muchas funciones tiles para convertir
y probar caracteres individuales.
Las funciones ms comunes para revisar caracteres tienen los siguientes prototipos:

int isalnum(int c) -- Verdad si c es alfanumrico.


int isalpha(int c) -- Verdad si c es una letra.
int isascii(int c) -- Verdad si c es ASCII.
int iscntrl(int c) -- Verdad si c es un caracter de control.
int isdigit(int c) -- Verdad si c es un dgito decimal.
int isgraph(int c) -- Verdad si c es un caracter imprimible, exceptuando el espacio en blanco.
int islower(int c) -- Verdad si c es una letra minscula.
int isprint(int c) -- Verdad si c es un caracter imprimible, incluyendo el espacio en blanco.
int ispunct(int c) -- Verdad si c es un signo de puntuacin.
int isspace(int c) -- Verdad si c es un espacio
int isupper(int c) -- Verdad si c es una letra mayscula.
int isxdigit(int c) -- Verdad si c es un dgito hexadecimal.

Las funciones para conversin de caracteres son:


int toascii(int c) -- Convierte c a ASCII o un unsigned char de 7 bits, borrando los bits altos.

int tolower(int c) -- Convierte la letra c a minsculas, si es posible.


int toupper(int c) -- Convierte la letra c a maysculas, si es posible.

El uso de estas funciones es directo y por lo tanto, no se dan ejemplos.


11.3 Operaciones con la memoria <memory.h>
Finalmente se ver un resumen de algunas funciones bsicas de memoria. Sin embargo, no son funciones
estrictamente de cadenas, pero tienen su prototipo en #include <string.h>:

void *memchr(void *s, int c, size_t n) -- Busca un caracter en un buffer.


int memcmp(void *s1, void *s2, size_t n) -- Compara dos buffers.
void *memcpy(void *dest, void *fuente, size_t n) -- Copia un buffer dentro de otro.
void *memmove(void *dest, void *fuente, size_t n) -- Mueve un nmero de bytes de un buffer a otro.
void *memset(void *s, int c, size_t n) -- Pone todos los bytes de un buffer a un caracter dado.

El uso de estas funciones es directo y parecido a las operaciones de comparacin de caracteres (excepto que
la longitud exacta (n) de todas las operaciones deber ser indicada ya que no hay una forma propia de
terminacin).
Observar que en todos los casos bytes de memoria son copiados, por lo que la funcin sizeof() ayuda en
estos casos, por ejemplo:

char fuente[TAM], dest[TAM];

71

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int ifuente[TAM],idest[TAM];
memcpy(dest, fuente, TAM); /* Copia chars (bytes) OK */
memcpy(idest,ifuente,TAM*sizeof(int));
/* Copia arreglo de enteros */

La funcin memmove() se comporta de la misma forma que memcpy() excepto que las localidades de la
fuente y el destino podran traslaparse.
La funcin memcmp() es similar a strcmp() excepto que unsigned bytes son comparados y se devuelve
cero si s1 es menor que s2, etc.
11.4 Ejercicios
1.
2.
3.

Escribir una funcin similar a strlen que pueda manejar cadenas sin terminador. Tip: se necesitar
conocer y pasar la longitud de la cadena.
Escribir una funcin que regrese verdad, si una cadena de entrada es un palndromo. Un palndromo
es una palabra que se lee igual de izquierda a derecha, o de derecha a izquierda. Por ejemplo, ANA.
Sugerir una posible implementacin de la funcin strtok():
1. usando otras funciones de manejo de cadenas.
2. desde los principios de apuntadores.

Cmo se logra el almacenamiento de una cadena separada?

72

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

TEMA 12

Archivos

73

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

12 Archivos
12.1 Generalidades:
Muy a menudo necesitamos almacenar cierta cantidad de datos de forma ms o menos permanente. La
memoria del ordenador es volatil, y lo que es peor, escasa y cara. De modo que cuando tenemos que guardar
nuestros datos durante cierto tiempo tenemos que recurrir a sistemas de almacenamiento ms econmicos,
aunque sea a costa de que sean ms lentos.
Durante la historia de los ordenadores se han usado varios mtodos distintos para el almacenamiento de
datos. Al principio se recurri a cintas de papel perforadas, despus a tarjetas perforadas. A continuacin se
pas al soporte magntico, empezando por grandes rollos de cintas magnticas abiertas.
Hasta aqu, todos los sistemas de almacenamiento externo eran secuenciales, es decir, no permitan acceder
al punto exacto donde se guardaba la informacin sin antes haber partido desde el principio y sin haber ledo
toda la informacin, hasta el punto donde se encontraba la que estabamos buscando.
Con las cintas magnticas empez lo que con el tiempo sera el acceso aleatorio a los datos. Se poda
reservar parte de la cinta para guardar cierta informacin sobre la situacin de los datos, y aadir ciertas
marcas que hicieran ms sencillo localizarla.
Pero no fu hasta la aparicin de los discos magnticos cuando sta tcnica lleg a su sentido ms amplio.
En los discos es ms sencillo acceder a cualquier punto de la superficie en poco tiempo, ya que se accede al
punto de lectura y escritura usando dos coordenadas fsicas. Por una parte la cabeza de lectura/escritura se
puede mover en el sentido del radio del disco, y por otra el disco gira permanentemente, con lo que cualquier
punto del disco pasa por la cabeza en un tiempo relativamente corto. Esto no pasa con las cintas, donde slo
hay una coordenada fsica.
Con la invencin y proliferacin de los discos se desarrollaron los ficheros de acceso aleatorio, que permiten
acceder a cualquier dato almacenado en un fichero en relativamente poco tiempo.
Actualmente, los discos duros tienen una enorme capacidad y son muy rpidos, aunque an siguen siendo
lentos, en comparacin con las memorias RAM. El caso de los CD es algo intermedio. En realidad son
secuenciales en cuanto al modo de guardar los datos, cada disco slo tiene una pista de datos grabada en
espiral. Sin embargo, este sistema, combinado con algo de memoria RAM, proporciona un acceso muy
prximo al de los discos duros.
En cuanto al tipo de acceso, en C y C++ podemos clasificar los archivos segn varias categoras:
1.

2.

3.

74

Dependiendo de la direccin del flujo de datos:


o De entrada: los datos se leen por el programa desde el archivo.
o De salida: los datos se escriben por el programa hacia el archivo.
o De entrada/salida: los datos pueden se escritos o ledos.
Dependiendo del tipo de valores permitidos a cada byte:
o De texto: slo estn permitidos ciertos rangos de valores para cada byte. Algunos bytes
tienen un significado especial, por ejemplo, el valor hexadecimal 0x1A marca el fin de
fichero. Si abrimos un archivo en modo texto, no ser posible leer ms all de un byte con
ese valor, aunque el fichero sea ms largo.
o Binarios: estn permitidos todos lo valores para cada byte. En estos archivos el final del
fichero se detecta de otro modo, dependiendo del soporte y del sistema operativo. La
mayora de las veces se hace guardando la longitud del fichero. Cuando queramos
almacenar valores enteros, o en coma flotante, o imgenes, etc, deberemos usar este tipo
de archivos.
Segn el tipo de acceso:
o Archivos secuenciales: imitan el modo de acceso de los antiguos ficheros secuenciales
almacenados en cintas magnticas y
o Archivos de acceso aleatorio: permiten acceder a cualquier punto de ellos para realizar
lecturas y/o escrituras.

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


4.

Segn la longitud de registro:


o Longitud variable: en realidad, en este tipo de archivos no tiene sentido hablar de longitud
de registro, podemos considerar cada byte como un registro. Tambin puede suceder que
nuestra aplicacin conozca el tipo y longitud de cada dato almacenado en el archivo, y lea o
escriba los bytes necesarios en cada ocasin. Otro caso es cuando se usa una marca para
el final de registro, por ejemplo, en ficheros de texto se usa el carcter de retorno de lnea
para eso. En estos casos cada registro es de longitud diferente.
o Longitud constante: en estos archivos los datos se almacenan en forma de registro de
tamao contante. En C usaremos estructuras para definir los registros. C dispone de
funciones de librera adecuadas para manejar este tipo de ficheros.
o Mixtos: en ocasiones pueden crearse archivos que combinen los dos tipos de registros, por
ejemplo, dBASE usa registros de longitud constante, pero aade un registro especial de
cabecera al principio para definir, entre otras cosas, el tamao y el tipo de los registros.

Es posible crear archivos combinando cada una de estas categoras, por ejemplo: archivos secuenciales de
texto de longitud de registro variable, que son los tpicos archivos de texto. Archivos de acceso aleatorio
binarios de longitud de registro constante, normalmente usados en bases de datos. Y tambin cualquier
combinacin menos corriente, como archivos secuenciales binarios de longitud de registro constante, etc.
En cuanto a cmo se definen estas propiedades, hay dos casos. Si son binarios o de texto o de entrada,
salida o entrada/salida, se define al abrir el fichero, mediante la funcin fopen en C o mediante el mtodo open
de fstream en C++.
La funcin open usa dos parmetros. El primero es el nombre del fichero que contiene el archivo. El segundo
es em modo que es una cadena que indica el modo en que se abrir el archivo: lectura o escritura, y el tipo de
datos que contiene: de texto o binarios.
En C, los ficheros admiten seis modos en cuanto a la direccin del flujo de datos:

r: slo lectura. El fichero debe existir.


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

En cuanto a los valores permitidos para los bytes, se puede aadir otro carcter a la cadena de modo:

t: modo texto. Normalmente es el modo por defecto. Se suele omitir.


b: modo binario.

En ciertos sistemas operativos no existe esta distincin, y todos los ficheros son binarios.
12.2 Tipos, funciones y clases usados frecuentemente con ficheros
Funciones y tipos C estndar:
Tipo FILE:
C define la estructura de datos FILE en el fichero de cabecesa "stdio.h" para el manejo de ficheros. Nosotros
siempre usaremos punteros a estas estructuras.
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 fichero y algunos campos
para uso interno.

75

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Funcin fopen:
Sintaxis:

FILE *fopen(char *nombre, char *modo);

sta funcin sirve para abrir y crear ficheros en disco. El valor de retorno es un puntero a una estructura FILE.
Los parmetros de entrada son:
1.
2.

nombre: una cadena que contiene un nombre de fichero vlido, esto depende del sistema operativo
que estemos usando. El nombre puede incluir el camino completo.
modo: especifica en tipo de fichero que se abrir o se crear y el tipo de datos que puede contener,
de texto o binarios:
o r: slo lectura. El fichero debe existir.
o w: se abre para escritura, se crea un fichero nuevo o se sobreescribe si ya existe.
o a: aadir, se abre para escritura, el cursor se situa al final del fichero. Si el fichero no existe,
se crea.
o r+: lectura y escritura. El fichero debe existir.
o w+: lectura y escritura, se crea un fichero nuevo o se sobreescribe si ya existe.
o a+: aadir, lectura y escritura, el cursor se situa al final del fichero. Si el fichero no existe, se
crea.
o t: tipo texto, si no se especifica "t" ni "b", se asume por defecto que es "t"
o b: tipo binario.

Funcin fclose:
Sintaxis:

int fclose(FILE *fichero);

Es importante cerrar los ficheros abiertos antes de abandonar la aplicacin. Esta funcin sirve para eso.
Cerrar un fichero almacena los datos que an estn en el buffer de memoria, y actualiza algunos datos de la
cabecera del fichero que mantiene el sistema operativo. Adems permite que otros programas puedan abrir el
fichero para su uso. Muy a menudo, los ficheros no pueden ser compartidos por varios programas.
Un valor de retorno cero indica que el fichero 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 fichero que queremos
cerrar.
Funcin fgetc:
Sintaxis:

int fgetc(FILE *fichero);

Esta funcin lee un carcter desde un fichero.


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 fichero del que
se har la lectura.

76

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Funcin fputc:
Sintaxis:

int fputc(int caracter, FILE *fichero);

Esta funcin escribe un carcter a un fichero.


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 fichero en el que se har la escritura.
Funcin feof:
Sintaxis:

int feof(FILE *fichero);

Esta funcin sirve para comprobar si se ha alcanzado el final del fichero. Muy frecuentemente deberemos
trabajar con todos los valores almacenados en un archivo de forma secuencial, la forma que suelen tener los
bucles para leer todos los datos de un archivo es permanecer leyendo mientras no se detecte el fin de fichero.
Esta funcin suele usarse como prueba para verificar si se ha alcanzado o no ese punto.
El valor de retorno es distinto de cero slo si no se ha alcanzado el fin de fichero. El parmetro es un puntero
a la estructura FILE del fichero que queremos verificar.
Funcin rewind:
Sintaxis:

void rewind(FILE *fichero)

Es una funcin heredada de los tiempos de las cintas magnticas. Literalmente significa "rebobinar", y hace
referencia a que para volver al principio de un archivo almacenado en cinta, haba que rebobinarla. Eso es lo
que hace sta funcin, sita el cursor de lectura/escritura al principio del archivo.
El parmetro es un puntero a la estructura FILE del fichero que queremos rebobinar.

77

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Ejemplos:

// ejemplo1.c: Muestra un fichero dos veces.


#include <stdio.h>
int main()
{
FILE *fichero;
fichero = fopen("ejemplo1.c", "r");
while(!feof(fichero)) fputc(fgetc(fichero), stdout);
rewind(fichero);
while(!feof(fichero)) fputc(fgetc(fichero), stdout);
fclose(fichero);
getchar();
return 0;
}

Funcin fgets:
Sintaxis:

char *fgets(char *cadena, int n, FILE *fichero);

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 evitar derbordar el espacio disponible en 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
fichero 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 fichero del que se leer.
Funcin fputs:
Sintaxis:

int fputs(const char *cadena, FILE *stream);

La funcin fputs escribe una cadena en un fichero. 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 fichero donde se realizar la escritura.
Funcin fread:
Sintaxis:

78

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


size_t fread(void *puntero, size_t tamao, size_t nregistros, FILE *fichero);

Esta funcin est pensada para trabajar con registros de longitud constante. Es capaz de leer desde un
fichero 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, el tamao de cada registro, el nmero de
registros a leer y un puntero a la estructura FILE del fichero del que se har la lectura.
Funcin fwrite:
Sintaxis:

size_t fwrite(void *puntero, size_t tamao, size_t nregistros, FILE *fichero);

Esta funcin tambin est pensada para trabajar con registros de longitud constante y forma pareja con fread.
Es capaz de escribir hacia un fichero 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 fichero del que se har la lectura.
Ejemplo:

// copia.c: Copia de ficheros


// Uso: copia <fichero_origen> <fichero_destino>
#include <stdio.h>
int main(int argc, char **argv) {
FILE *fe, *fs;
unsigned char buffer[2048]; // Buffer de 2 Kbytes
int bytesLeidos;
if(argc != 3) {
printf("Usar: copia <fichero_origen> <fichero_destino>\n");
return 1;
}
// Abrir el fichero de entrada en lectura y binario
fe = fopen(argv[1], "rb");
if(!fe) {
printf("El fichero %s no existe o no puede ser abierto.\n", argv[1]);
return 1;
}
// Crear o sobreescribir el fichero de salida en binario
fs = fopen(argv[2], "wb");
if(!fs) {
printf("El fichero %s no puede ser creado.\n", argv[2]);
fclose(fe);
return 1;
}

79

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


// Bucle de copia:
while((bytesLeidos = fread(buffer, 1, 2048, fe)))
fwrite(buffer, 1, bytesLeidos, fs);
// Cerrar ficheros:
fclose(fe);
fclose(fs);
return 0;
}

Funcin fprintf:
Sintaxis:

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

La funcin fprintf funciona igual que printf en cuanto a parmetros, pero la salida se dirige a un fichero en lugar
de a la pantalla.
Funcin fscanf:
Sintaxis:

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

La funcin fscanf funciona igual que scanf en cuanto a parmetros, pero la entrada se toma de un fichero en
lugar del teclado.
Funcin fflush:
Sintaxis:

int fflush(FILE *fichero);

Esta funcin fuerza la salida de los datos acumulados en el buffer de salida del fichero. Para mejorar las
prestaciones del manejo de ficheros 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.
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 fichero del que se quiere vaciar el buffer. Si es NULL se har el
vaciado de todos los ficheros abiertos.

Funciones C especficas para ficheros de acceso aleatorio


Funcin fseek:
Sintaxis:

80

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int fseek(FILE *fichero, long int desplazamiento, int origen);

Esta funcin sirve para situar el cursor del fichero para leer o escribir en el lugar deseado.
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 fichero en el que queremos cambiar el
cursor de lectura/escritura, el valor del desplazamiento y el punto de origen desde el que se calcular el
desplazamiento.
El parmetro origen puede tener tres posibles valores:
1.
2.
3.

SEEK_SET el desplazamiento se cuenta desde el principio del fichero. El primer byte del fichero
tiene un desplazamiento cero.
SEEK_CUR el desplazamiento se cuenta desde la posicin actual del cursor.
SEEK_END el desplazamiento se cuenta desde el final del fichero.

Funcin ftell:
Sintaxis:

long int ftell(FILE *fichero);

La funcin ftell sirve para averiguar la posicin actual del cursor de lectura/excritura de un fichero.
El valor de retorno ser esa posicin, o -1 si hay algn error.
El parmetro de entrada es un puntero a una estructura FILE del fichero del que queremos leer la posicin del
cursor de lectura/escritura.
12.3 Archivos secuenciales
En estos archivos, la informacin slo puede leerse y escribirse empezando desde el principio del archivo.
Los archivos secuenciales tienen algunas caractersticas que hay que tener en cuenta:
1.
2.
3.

La escritura de nuevos datos siempre se hace al final del archivo.


Para leer una zona concreta del archivo hay que avanzar siempre, si la zona est antes de la zona
actual de lectura, ser necesario "rebobinar" el archivo.
Los ficheros slo se pueden abrir para lectura o para escritura, nunca de los dos modos a la vez.

Esto es en teora, por supuesto, en realidad C no distingue si los archivos que usamos son secuenciales o no,
es el tratamiento que hagamos de ellos lo que los clasifica como de uno u otro tipo.
Pero hay archivos que se comportan siempre como secuenciales, por ejemplo los ficheros de entrada y salida
estndar: stdin, stdout, stderr y stdaux.
Tomemos el caso de stdin, que suele ser el teclado. Nuestro programa slo podr abrir ese fichero como de
lectura, y slo podr leer los caracteres a medida que estn disponibles, y en el mismo orden en que fueron
tecleados.

81

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Lo mismo se aplica para stdout y stderr, que es la pantalla, en estos casos slo se pueden usar para escritura,
y el orden en que se muestra la informacin es el mismo en que se enva.
Un caso especial es stdaux, que suele ser el puerto serie. Tambin es un archivo secuencial, con respecto al
modo en que se leen y escriben los datos. Sin embargo se un fichero de entrada y salida.
Trabajar con archivos secuenciales tiene algunos inconvenientes. Por ejemplo, imagina que tienes un archivo
de este tipo en una cinta magntica. Por las caractersticas fsicas de este soporte, es eviente que slo
podemos tener un fichero abierto en cada unidad de cinta. Cada fichero puede ser ledo, y tambin
sobrescrito, pero en general, los archivos que haya a continuacin del que escribimos se perdern, o bien
sern sobreescritos al crecer el archivo, o quedar un espacio vaco entre el final del archivo y el principio del
siguiente.
Lo normal cuando se quera actualizar el contenido de un archivo de cinta aadiendo o modificando datos, era
abrir el archivo en modo lectura en una unidad de cinta, y crear un nuevo fichero de escritura en una unidad
de cinta distinta. Los datos ledos de una cinta se editan o modifican, y se copian en la otra secuencialmente.
Cuando trabajemos con archivos secuenciales en disco haremos lo mismo, pero en ese caso no necesitamos
dos unidades de disco, ya que en los discos es posible abrir varios archivos simultaneamente.
En cuanto a las ventajas, los archivos secuenciales son ms sencillos de manejar, ya que requieren menos
funciones, adems son ms rpidos, ya que no permiten moverse a lo largo del archivo, el punto de lectura y
escritura est siempre determinado.
En ocasiones pueden ser tiles, por ejemplo, cuando slo se quiere almacenar cierta informacin a medida
que se recibe, y no interesa analizarla en el momento. Posteriormente, otro programa puede leer esa
informacin desde el principio y analizarla. Este es el caso de archivos "log" o "diarios" por ejemplo, los
servidores de las pginas WEB pueden generar una lnea de texto cada vez que alguien accede al una de las
pginas y las guardan en un fichero secuencial.
12.4 Archivos de acceso aleatorio
Los archivos de acceso aleatorio son ms verstiles, permiten acceder a cualquier parte del fichero en
cualquier momento, como si fueran arrays en memoria. Las operaciones de lectura y/o escritura pueden
hacerse en cualquier punto del archivo.
En general se suelen establecer ciertas normas para la creacin, aunque no todas son obligatorias:
1.
2.
3.
4.

Abrir el archivo en un modo que te permita leer y escribir. Esto no es imprescindible, es posible usar
archivos de acceso aleatorio slo de lectura o de escritura.
Abrirlo en modo binario, ya que algunos o todos los campos de la estructura pueden no ser
caracteres.
Usar funciones como fread y fwrite, que permiten leer y escribir registros de longitud constante desde
y hacia un fichero.
Usar la funcin fseek para situar el puntero de lectura/escritura en el lugar apropiado de tu archivo.

Por ejemplo, supongamos que nuestros registros tienen la siguiente estructura:

struct stRegistro {
char Nombre[34];
int dato;
int matriz[23];
} reg;

82

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Teniendo en cuenta que los registros empiezan a contarse desde el cero, para hacer una lectura del registro
nmero 6 usaremos:

fseek(fichero, 5*sizeof(stRegistro), SEEK_SET);


fread(&reg, sizeof(stRegistro), 1, fichero);

Anlogamente, para hacer una operacin de escritura, usaremos:

fseek(fichero, 5*sizeof(stRegistro), SEEK_SET);


fwrite(&reg, sizeof(stRegistro), 1, fichero);

Muy importante: despus de cada operacin de lectura o escritura, el cursor del fichero se actualiza
automticamente a la siguiente posicin, as que es buena idea hacer siempre un fseek antes de un fread o
un fwrite.
En el caso de streams, la forma de trabajar es anloga:

fichero.seekg(5*sizeof(stRegistro), ios::beg);
fichero.read(&reg, sizeof(stRegistro));

Y para hacer una operacin de escritura, usaremos:

fichero.seekp(5*sizeof(stRegistro), ios::beg);
fichero.write(&reg, sizeof(stRegistro));

Calcular la longitud de un fichero


Para calcular el tamao de un fichero, ya sea en bytes o en registros se suele usar el siguiente procedimiento:

long nRegistros;
long nBytes;
fseek(fichero, 0, SEEK_END); // Colocar el cursor al final del fichero
nBytes = ftell(fichero); // Tamao en bytes
nRegistros = ftell(fich)/sizeof(stRegistro); // Tamao en registros

En el caso de streams:

long nRegistros;
long nBytes;
fichero.seekg(0, ios::end); // Colocar el cursor al final del fichero
nBytes = fichero.tellg(); // Tamao en bytes
nRegistros = fichero.tellg()/sizeof(stRegistro); // Tamao en registros

Borrar registros
Borrar registros puede ser complicado, ya que no hay ninguna funcin de librera estndar que lo haga.

83

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

84

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Es su lugar se suele usar uno de estos dos mtodos:
1.

Marcar el registro como borrado o no vlido, para ello hay que aadir un campo extra en la estructura
del registro:

struct stRegistro {
char Valido; // Campo que indica si el registro es vlido
char Nombre[34];
int dato;
int matriz[23];
}

Si el campo Valido tiene un valor prefijado, por ejemplo 'S' o ' ', el registro es vlido. Si tiene un valor
prefijado, por ejemplo 'N' o '*', el registro ser invlido o se considerar borrado.
De este modo, para borrar un registro slo tienes que cambiar el valor de ese campo.
Pero hay que tener en cuenta que ser el programa el encargado de tratar los registros del modo
adecuado dependiendo del valor del campo Valido, el hecho de marcar un registro no lo borra
fsicamente.
Si se quiere elaborar ms, se puede mantener un fichero auxiliar con la lista de los registros
borrados. Esto tiene un doble propsito:

2.

Que se pueda disear una funcin para sustituir a fseek() de modo que se tengan en cuenta
los registros marcados.
o Que al insertar nuevos registros, se puedan sobrescribir los anteriormente marcados como
borrados, si existe alguno.
Hacer una copia del fichero en otro fichero, pero sin copiar el registro que se quiere borrar. Este
sistema es ms tedioso y lento, y requiere cerrar el fichero y borrarlo o renombrarlo, antes de poder
usar de nuevo la versin con el registro eliminado.

Lo normal es hacer una combinacin de ambos, durante la ejecucin normal del programa se borran registros
con el mtodo de marcarlos, y cuando se cierra la aplicacin, o se detecta que el porcentaje de registros
borrados es alto o el usuario as lo decide, se "empaqueta" el fichero usando el segundo mtodo.
Ejemplo:
A continuacin se incluye un ejemplo de un programa que trabaja con registros de acceso aleatorio, es un
poco largo, pero bastante completo:

// alea.c: Ejemplo de ficheros de acceso aleatorio.


#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
struct stRegistro {
char valido; // Campo que indica si el registro es vlido S->Vlido, N->Invlido
char nombre[34];
int dato[4];
};

85

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int Menu();
void Leer(struct stRegistro *reg);
void Mostrar(struct stRegistro *reg);
void Listar(long n, struct stRegistro *reg);
long LeeNumero();
void Empaquetar(FILE **fa);
int main()
{
struct stRegistro reg;
FILE *fa;
int opcion;
long numero;
fa = fopen("alea.dat", "r+b");
// Este modo permite leer y escribir
if(!fa) fa = fopen("alea.dat", "w+b"); // si el fichero no existe, lo crea.
do {
opcion = Menu();
switch(opcion) {
case '1': // Aadir registro
Leer(&reg);
// Insertar al final:
fseek(fa, 0, SEEK_END);
fwrite(&reg, sizeof(struct stRegistro), 1, fa);
break;
case '2': // Mostrar registro
clrscr();
printf("Mostrar registro: ");
numero = LeeNumero();
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fread(&reg, sizeof(struct stRegistro), 1, fa);
Mostrar(&reg);
break;
case '3': // Eliminar registro
clrscr();
printf("Eliminar registro: ");
numero = LeeNumero();
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fread(&reg, sizeof(struct stRegistro), 1, fa);
reg.valido = 'N';
fseek(fa, numero*sizeof(struct stRegistro), SEEK_SET);
fwrite(&reg, sizeof(struct stRegistro), 1, fa);
break;
case '4': // Mostrar todo
rewind(fa);
numero = 0;
clrscr();
printf("Nombre
Datos\n");
while(fread(&reg, sizeof(struct stRegistro), 1, fa))
Listar(numero++, &reg);
getch();
break;
case '5': // Eliminar marcados
Empaquetar(&fa);
break;
}
} while(opcion != '0');
fclose(fa);
return 0;
}
// Muestra un men con las opciones disponibles y captura una opcin del usuario

86

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


int Menu()
{
char resp[20];
do {
clrscr();
printf("MENU PRINCIPAL\n");
printf("--------------\n\n");
printf("1- Insertar registro\n");
printf("2- Mostrar registro\n");
printf("3- Eliminar registro\n");
printf("4- Mostrar todo\n");
printf("5- Eliminar registros marcados\n");
printf("0- Salir\n");
fgets(resp, 20, stdin);
} while(resp[0] < '0' && resp[0] > '5');
return resp[0];
}
// Permite que el usuario introduzca un registro por pantalla
void Leer(struct stRegistro *reg)
{
int i;
char numero[6];
clrscr();
printf("Leer registro:\n\n");
reg->valido = 'S';
printf("Nombre: ");
fgets(reg->nombre, 34, stdin);
// la funcin fgets captura el retorno de lnea, hay que eliminarlo:
for(i = strlen(reg->nombre)-1; i && reg->nombre[i] < ' '; i--)
reg->nombre[i] = 0;
for(i = 0; i < 4; i++) {
printf("Dato[%1d]: ", i);
fgets(numero, 6, stdin);
reg->dato[i] = atoi(numero);
}
}
// Muestra un registro en pantalla, si no est marcado como borrado
void Mostrar(struct stRegistro *reg)
{
int i;
clrscr();
if(reg->valido == 'S') {
printf("Nombre: %s\n", reg->nombre);
for(i = 0; i < 4; i++) printf("Dato[%1d]: %d\n", i, reg->dato[i]);
}
getch();
}
// Muestra un registro por pantalla en forma de listado,
// si no est marcado como borrado
void Listar(long n, struct stRegistro *reg)
{
int i;
if(reg->valido == 'S') {
printf("[%6ld] %-34s", n, reg->nombre);
for(i = 0; i < 4; i++) printf(", %4d", reg->dato[i]);
printf("\n");
}
}

87

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


// Lee un nmero suministrado por el usuario
long LeeNumero()
{
char numero[6];
fgets(numero, 6, stdin);
return atoi(numero);
}
// Elimina los registros marcados como borrados
void Empaquetar(FILE **fa)
{
FILE *ftemp;
struct stRegistro reg;
ftemp = fopen("alea.tmp", "wb");
rewind(*fa);
while(fread(&reg, sizeof(struct stRegistro), 1, *fa))
if(reg.valido == 'S')
fwrite(&reg, sizeof(struct stRegistro), 1, ftemp);
fclose(ftemp);
fclose(*fa);
remove("alea.bak");
rename("alea.dat", "alea.bak");
rename("alea.tmp", "alea.dat");
*fa = fopen("alea.dat", "r+b");
}

88

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

ANEXOS

89

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


DATOS FORMATEADOS
i. E/S formateada
Se han visto ya algunos ejemplos de como C usa la E/S formateada. En esta seccin se revisarn con ms
detalle.
i.1 printf
El prototipo de la funcin esta definido como:

int printf( const char *formato, lista arg ...);

que muestra en stdout la lista de argumentos de acuerdo al formato especificado. La funcin devuelve el
nmero de caracteres impresos.
La cadena de formateo tiene dos tipos de objetos:

caracteres ordinarios -- estos son copiados a la salida.


especificadores de conversin -- precedidos por % y listados en la tabla 16.1.

Tabla 16.1: Caracteres de format printf/scanf


Especificador (%)

Tipo

Resultado

char

un slo caracter

i,d

int

nmero base diez

int

nmero base ocho

x,X

int

nmero base dieciseis


notacin mins/mays

int

char *

entero sin signo


impresin de cadena
terminada por nulo

f
e,E

double/float formato -m.ddd ...


"

Notacin Cientfica
-1.23e002

g,G

"

e f la que sea
ms compacta

%
90

caracter %
Pedro Nez Ypiz
Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo


Entre el % y el caracter de formato se puede poner:

- signo menos para justificar a la izquierda.


nmero entero para el ancho del campo.
m.d en donde m es el ancho del campo, y d es la precisin de dgitos despus del punto decimal o el
nmero de caracteres de una cadena.

Por lo tanto:

printf("%-2.3f\n",17.23478);

la salida en pantalla ser:

17.235

printf("VAT=17.5%%\n");

genera la siguiente salida:

VAT=17.5%

91

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

Anexo 2: MODO GRAFICO ALLEGRO V 5.


Referencia Oficial:
http://alleg.sourceforge.net/
Manual de referencia
https://www.allegro.cc/manual/5/index.html

Manual Allegro en espaol


http://artemisa.unicauca.edu.co/~wpantoja/web/graficos_
gcc/allegro/manual_allegro.pdf

92

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx

PROGRAMACION ESTRUCTURADA

/ Clave: 12125

UABC Facultad de Ingenieria Arquitectura y Diseo

BIBLIOGRAFIA:
COMO PROGRAMAR EN C/C++,Deitel & Deitel, Prentice Hall,
ISBN:9688804711
C/C++ CURSO DE PROGRAMACIN, Fco. Javier Ceballos, Alpha
Omega ISBN:978847897628
FUNDAMENTOS DE PROGRAMACIN, Jose Luis Joyanes A, ed.
McGrawhill, ISBN:9788448139865

http://alleg.sourceforge.net/
http://yepiz.webs.com

93

Pedro Nez Ypiz


Email: pedro_yepiz@uabc.edu.mx