Anda di halaman 1dari 181

INSTITUTO POLITCNICO NACIONAL

CENTRO DE INVESTIGACIN EN COMPUTACIN


No. 18

Serie: VERDE

Fecha: Junio 1999

Programacin en
Lenguaje C

Lic. Luis Hernndez Lara1

RESUMEN

En este trabajo se desarrollan los conceptos fundamentales del lenguaje de programacin ANSI
C. Se describen los objetos fundamentales, el control de flujo, los tipos de datos derivados, as
como: arreglos, apuntadores, estructuras, uniones y funciones. Tambin se incluyen diversos
programas que ejemplifican la utilizacin del lenguaje C para resolver problemas de diversa
ndole.

Palabras clave: Apuntadores, archivos, estructuras de datos, funciones, gestin dinmica de


memoria, lenguaje C, manejo de bits, programacin imperativa, recursividad.

Profesor del Centro de Investigacin en Computacin

NDICE

Pgina

INTRODUCCIN

1. ORACIONES, TIPOS DE DATOS Y CONSTANTES


1.1 Oraciones
1.2 Comentarios
1.3 Nombres de variables
1.4 Tipos de datos
1.5 Constantes
1.6 Ejercicios del captulo

3
3
3
4
5
7
11

2. OPERADORES
2.1 Operadores aritmticos
2.2 Operadores de incremento y decremento
2.3 Operadores a nivel de bits
2.4 Operadores relacionales y lgicos
2.5 Operadores de asignacin
2.6 Precedencia de operadores
2.7 Ejercicios del captulo

13
13
14
15
16
16
17
19

3. ENTRADA Y SALIDA
3.1 La funcin printf
3.2 La funcin scanf
3.3 La funcin putch
3.4 Las funciones getchar y getch
3.5 Ejercicios del captulo

22
22
23
25
26
28

4. EXPRESIONES CONDICIONALES Y CONTROL DE FLUJO


4.1 La oracin if
4.2 La oracin else
4.3 Expresin condicional con el operador "?:"
4.4 La oracin else-if
4.5 La oracin switch
4.6 La oracin break
4.7 La oracin while
4.8 La oracin for
4.9 La oracin do-while
4.10 La oracin continue

29
29
30
31
32
33
34
35
35
37
37

Pgina
4.11 la oracin goto
4.12 Ejercicios del captulo

39
40

5. CONVERSIN DE TIPOS DE DATOS


5.1 Operador sizeof
5.2 Conversin de tipos

47
47
47

6. MBITO DE LAS VARIABLES

49

7. ARREGLOS
7.1 Definicin
7.2 Inicializacin de arreglos
7.3 Uso de los operadores de incremento y decremento
para referenciar elementos en arreglos
7.4 Arreglos multidimensionales y arreglos de cadenas
7.5 Inicializacin de arreglos desde la entrada de datos
7.6 Ejercicios del captulo

51
51
52
54
54
57
58

8. FUNCIONES
8.1 Reglas de las funciones
8.2 Argumentos de funciones (llamada por valor)
8.3 Parmetros mltiples
8.4 La oracin return
8.5 Pasando y regresando expresiones
8.6 Paso de arreglos a funciones
8.7 Llamada por referencia
8.8 Recursividad
8.9 Ejercicios del captulo

65
65
66
68
69
70
70
72
73
75

9. APUNTADORES
9.1 Definicin
9.2 Apuntadores en expresiones
9.3 Aritmtica y comparacin de apuntadores
9.4 Paso de apuntadores a funciones
9.5 Apuntadores y arreglos
9.6 Indexado de apuntadores
9.7 Apuntadores a caracteres y funciones
9.7.1 Apuntadores a caracteres
9.7.2 Apuntadores a funciones
9.8 Arreglos de apuntadores y apuntadores a apuntadores
9.8.1 Arreglos de apuntadores

81
81
82
83
84
84
86
86
86
87
88
88

Pgina
9.8.2 Apuntadores a apuntadores
9.8.3 Usando apuntadores como arreglos (asignacin
dinmica de arreglos)
9.9 Paso de argumentos en la lnea de comandos
9.10 Ejercicios del captulo

89
90
92
95

10. EL PREPROCESADOR
10.1 Directivas
10.2 Macros
10.3 Inclusin de archivos fuente
10.4 Ejercicios del captulo

104
104
105
106
108

11. ESTRUCTURAS
11.1 Definicin
11.2 Arreglos de estructuras
11.3 Inicializacin de estructuras
11.4 Estructuras y funciones
11.5 Apuntadores a estructuras
11.6 Paso de apuntadores a estructuras a funciones
11.7 Paso de arreglos de estructuras a funciones
11.8 Ejercicios del captulo

109
109
111
111
114
115
115
117
119

12. CAMPO DE BITS Y UNIONES


12.1 Campo de bits
12.2 Uniones
12.3 Estructuras y uniones anidadas
12.4 Ejercicios del captulo

122
122
123
126
128

13. ENUMERACIONES Y RENOMBRE DE TIPOS EXISTENTES


13.1 Enumeraciones
13.2 Renombre de tipos existentes
13.3 Ejercicios del captulo

130
130
131
133

14. ARCHIVOS
14.1 Ejercicios del captulo

134
136

15. PROGRAMAS COMPLEMENTARIOS

150

BIBLIOGRAFA

177

Centro de Investigacin en Computacin

INTRODUCCIN.
Por sus caractersticas, el lenguaje de programacin C es considerado como una
herramienta muy poderosa para el desarrollo de aplicaciones, ya que permite crear
programas tan sencillos como el que calcula la media de "n" nmeros, hasta sistemas
completos como el que lleva el control de inventarios de una empresa.
Las caractersticas ms destacables del lenguaje son: (1) la portabilidad de los
programas entre diferentes arquitecturas de computadoras, (2) la flexibilidad que
tiene para crear tipos de datos derivados que permiten representar casi cualquier
entidad de informacin, y (3) la poderosa capacidad que tiene para comportarse como
un lenguaje de bajo nivel de propsito general.
"C" no contiene operaciones para trabajar con objetos compuestos como cadenas de
caracteres, conjuntos, listas, arreglos o vectores, considerados como un todo.
Asimismo no cuenta con operaciones de entrada-salida ni mtodos propios para el
acceso a archivos. Esto lo maneja a travs de funciones externas.
La estructura de un programa en C consiste de:
a) Un archivo conteniendo directivas al preprocesador, declaraciones de variables y
funciones.
b) Una funcin main.
c) El cuerpo de la funcin main.
d) Otras funciones.
El cuerpo de cada funcin, incluyendo a main, contiene expresiones y oraciones.
La ejecucin de todos los programas comienza en la funcin identificada como main().
La sintaxis de la funcin main() se muestra a continuacin.
main()
{
/* el cdigo va en este lugar */
}

El siguiente es un ejemplo de cdigo de un programa en "C":

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Directivas al preprocesador */
# include <stdio.h>
# define es_entero(x) ( (x >= 0 && x <= 9) ? 1 : 0 )

/* Declaracin de variables y funciones */


char password[] = X99TEST;
int al_cubo(int);
/* prototipo de la funcin al_cubo */
/* Funcin main y cuerpo de la funcin (una oracin { }) */
main(int argc, char *argv[])
{
char caracter;
int resultado;
if(argc < 2) exit(0);
if(strcmp(password,argv[1]))
{
printf(clave invlida );
getch();
exit(0);
}
printf(\nTeclee el digito a elevar al cubo _ );
caracter = getch();
if(es_entero(caracter))
{
resultado = al_cubo(caracter-0);
printf(\n %d al cubo es %d,caracter-0,resultado);
}
else
printf(\nEl carcter introducido no es digito);
getch();
} /* fin de main */

/*---------------------------------------------------------------------------------------*/
/* Otras funciones y su cuerpo */
int al_cubo(int y)
{
return (y*y*y);
} /* fin de al_cubo */

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

1. ORACIONES, TIPOS DE DATOS Y CONSTANTES.


1.1 Oraciones.
Las oraciones dentro de un programa en C son de dos tipos: (1) de lnea simple
oracin y (2) multilnea bloque de oraciones.
Una oracin simple debe terminar con punto y coma ';'.
oracin ;

printf("Bienvenidos a estudiar C");

Cuando una oracin condicional es usada como en el caso de la oracin if, pueden
existir mltiples oraciones condicionales anidadas. Sin embargo deben terminar con
una oracin y un punto y coma.
oracin condicional
oracin condicional
oracin;

if (x > 20)
if(x < 30)
x = x * 1.25;

En un bloque de oraciones, las llaves { } son usadas para unir mltiples oraciones a
una oracin condicional simple. La llave de apertura "{" indica el comienzo de un bloque
y la llave de cierre "}" indica el fin del bloque. Los bloques de oraciones no requieren un
punto y coma seguido de la ltima llave.
oracin condicional {
oracin;
oracin;
oracin;
}

if( anio == 2001){


impuesto = impuesto *1.50;
salario = salario * 1.13;
tenencia = tenencia * 1.25;
}

No hay un formato estricto, el programador puede usar tantos espacios como lo desee
entre oraciones o bloques de oraciones. Los espacios en blanco incluyen: nueva lnea,
espacio, tabulador.

1.2 Comentarios.
Los comentarios en un programa en C se establecen utilizando la combinacin de los
caracteres "/" y "*", de la forma /* y */. A estas combinaciones se les llama token.
/*

Comentarios

*/

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

El token /* comienza una lnea de comentario y


comentario puede abarcar ms de una lnea.

*/ finaliza el comentario. Un

Todo texto entre comentarios es ignorado por el compilador. No se pueden anidar


comentarios.
/* Este es un comentario bien escrito */
/* Comentario /* esto no es permitido! */ */ <- fin de comentario imprevisto
Existen seis clases de smbolos o TOKENS en el vocabulario del lenguaje "C":
identificadores, palabras clave, constantes, cadenas, operadores y separadores.

1.3 Nombres de variables.


Los nombres de variables en "C" pueden ser una secuencia de nmeros y letras,
comenzando con letra. El carcter para subrayar _ es permitido, pero debe ser
utilizado con cuidado en algunos sistemas que lo usan para indicar smbolos
especiales. Caracteres en maysculas y en minsculas son considerados diferentes .
"C" es sensitivo al contexto.
El siguiente ejemplo ilustra lo anterior, utilizando a y A como variables diferentes.
main()
{
char a;
char A;
}

A continuacin se muestran algunos nombres de variables correctos e incorrectos:


Nombres correctos
contador
pago_total
nombre_alumno
Bandera_tipo
_variable23
C45_nomina

Programacin en Lenguaje C

Nombres incorrectos
1_nombre
variable-3
pago$total
ultimo nombre
996
1999_fin

Luis Hernndez Lara

Centro de Investigacin en Computacin

1.4 Tipos de datos.


Los tipos fundamentales en el lenguaje C se listan a continuacin:
a) Tipo carcter (char). Lo suficientemente grande para almacenar el miembro ms
largo del conjunto de caracteres de la instalacin local. Por ejemplo: 'A'
main()
{
char caracter;
caracter = A;
printf(\nEl valor es %c,caracter);
caracter = \101;
/* valor en octal */
printf(\nEl valor es %c,caracter);
caracter = 65;
printf(\nEl valor es %c,caracter);
}
El programa imprime
El valor es A
El valor es A
El valor es A

b) Tipo entero (int). Los enteros vienen en una variedad de diferentes tamaos
dependiendo del sistema anfitrin. El entero puede contener slo nmeros de -n a n.
Donde n es dependiente del tamao del entero del sistema anfitrin.

main()
{
int var_entera;
var_entera = 10;
printf(\nEstos son los valores de %d, var_entera);
printf(\nEn decimal
= %d, var_entera);
printf(\nEn octal
= %o, var_entera);
printf(\nEn hexadecimal
= %x, var_entera);
}

Este programa imprime


Estos son los valores de 10

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

En decimal
En octal
En hexadecimal

= 10
= 12
=C

En "C" pueden mezclarse libremente los tipos carcter (char) y entero (int) en
expresiones aritmticas. Cada carcter en una expresin se convierte automticamente
a un entero.
Ver seccin 1.6, ejercicio 1.1.

c) Tipo punto flotante (float). A las variables en punto flotante se les puede asignar un
valor en formato numrico estndar (234.54) o en notacin cientfica (2.3454e2).
main()
{
float var_real1, var_real2;
var_real1 = 12.6e5;
var_real2 = 12.345;
printf(\nEl valor es %f, var_real1);
printf(\nEl valor es %e, var_real1);
printf(\nEl valor es %f, var_real2);
printf(\nEl valor es %e, var_real2);
}
Este programa imprime
El valor es 1260000.000000
El valor es 1.260000e+06
El valor es 12.345000
El valor es 1.234500e+1

d) Tipo doble precisin (double). Una variable en punto flotante de doble precisin es
esencialmente una variable en punto flotante larga.
Muchos compiladores colocan en memoria nmeros en punto flotante usando el
formato de doble precisin. El hecho de pensar que los tipos de datos son muy
similares no implica que deban usarse unos por otros. Existen problemas de
redondeo y truncamiento que pueden ocurrir al usarlos.

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

e) Tipo entero largo (long int). Cuando los enteros son de 16 bits, este tipo proporciona
32 bits para un entero.

f) Tipo entero corto (short int). Un entero pequeo. Cuando los enteros son de 32 bits,
este tipo proporciona 16 bits para un entero.

g) Tipo entero sin signo (unsigned int). El bit de signo es usado para almacenar un
entero positivo ms largo, los nmeros unsigned son siempre positivos.
main()
{
int var_entera1;
unsigned int var_entera2;
var_entera1 = 32768;
var_entera2 = 32768;
printf(\nEl valor de la variable entera es %d,var_entera1);
printf(\nEl valor de la variable unsigned es %u, var_entera2);
}
Este programa imprime:
El valor de la variable entera es -32768
El valor de la variable unsigned es 32768

Las palabras unsigned, long y short se consideran calificadores aplicables a enteros


por lo que al declararse una variable con uno de estos calificadores se puede omitir la
palabra int. Por ejemplo:
unsigned variable;
short variable;
long int variable;

en lugar de
en lugar de
en lugar de

unsigned int variable;


short int variable;
long int variable;

1.5 Constantes.
Las constantes son asignadas a variables en la forma de entero, entero largo, carcter,
punto flotante y cadena (string).
El tipo de la constante debe corresponder al tipo de la variable en la cual ser
almacenada. Sin embargo es posible almacenar una constante de carcter en una
variable entera ya que una constante de carcter consiste de un valor entero (ASCII).

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

main()
{
int a;
a='A';
}

/* 'A' es igual a una A en ASCII con un valor de 65 */

a) Constantes enteras. Son una secuencia de dgitos dndn-1 ... d1d0. Pueden ser
definidas en octal si van precedidas con un cero. Esto es extensivo a hexadecimal si
la secuencia de dgitos va precedida de un 0X o un 0x.

main()
{
int a, b;
a=11;
a=013;
a=0xb;
a=0XB;
}

/* base 10 (decimal) */
/* base 8 (octal) */
/* base 16 */
/* base 16 */

b) Constantes de carcter. Van encerradas entre comillas simples (apstrofes) y son


numricamente equivalentes al valor del carcter ASCII de la mquina anfitrin.
main()
{
char c;
c = 'A';
}

/* la variable c es igual al carcter 'A' */

Note que slo se permite un carcter entre apstrofes. Esto define un valor de ocho bits
el cual ser almacenado en una variable de carcter. Una forma de definir caracteres
especiales y valores enteros es utilizando el carcter diagonal invertida (backslash)
dentro de los apstrofes.

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

main()
{
char c;
c = '\n';
c = '\033';
c = '\0';

/* define carcter nueva lnea */


/* define el nmero octal 33 que ser
almacenado en la variable c */
/* c es igual al carcter nulo (NULL) el cual
es equivalente al valor decimal 0 */

Otros caracteres especiales son:


Significado

Carcter

Nueva lnea
Retroceso (backspace)
Avance de forma (form feed)
Comilla simple

'\n'
'\b'
'\f'
'\''

Significado
Tabulador horizontal
Retorno de carro
Diagonal invertida
Caracteres grficos

Carcter
'\t'
'\r'
'\\'
'\nnn'

Tabla 1.1. Caracteres Especiales

c) Constantes de punto flotante. Consisten de una porcin entera, un punto decimal, y


una fraccin. Ellas se pueden definir en notacin cientfica con las letras e o E
donde los valores son iguales a: valor * (10 con un exponente de E).
main()
{
float y;
y = 100.0;
y = 1.0e2;
y = 1.0E+2;
}

/* y = 100 */
/* y = 100 */
/* y = 100 */

d) Constantes de cadena. Se definen como una serie de caracteres encerrados entre


doble comilla. El compilador colocar automticamente un nulo (NULL) o decimal 0
como el ltimo byte de la cadena. Por lo tanto, las cadenas en el lenguaje C se
definen como una secuencia de caracteres terminando con nulo.

Programacin en Lenguaje C

Luis Hernndez Lara

Centro de Investigacin en Computacin

main()
{
static char a[] = "hola";
}

La variable arreglo 'a' ahora apunta a la cadena "hola" y debe contener los siguientes
datos:
a[0] = 'h'
a[1] = 'o'
a[2] = l
a[3] = a
a[4] = \0

Una categoria de variable permitida slo por compiladores en ANSI C es la constante.


La palabra const se coloca antes de la definicin de la variable e indica que la variable
no puede ser modificada durante la ejecucin del programa. Si se intenta modificar el
compilador marcar un error.

const int i = 100;


const float f = 3.14;
const float f1 = 1.414;

Programacin en Lenguaje C

/* la variable i no puede ser cambiada */

10

Luis Hernndez Lara

Centro de Investigacin en Computacin

1.6 Ejercicios del captulo.


Ejercicio 1.1.
/*
Archivo: ejer11.cpp
Objetivo: Mostrar la conversin de tipos de datos char e int
Funcin: Convertir una cadena de dgitos en su equivalente
numrico
*/
#include <stdio.h>

/* directiva al preprocesador */

main()
{
char cadena[10];
int numero,i;
printf("\nTeclee un entero: ");
gets(cadena);
numero=0;
for(i=0;cadena[i]>='0' && cadena[i]<='9';++i)
numero=10*numero+cadena[i]-'0';
printf("\nEl entero tecleado fu: %i \n ",numero);
return 0;
}/*fin de main */

Programacin en Lenguaje C

11

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 1.2.
/*
Archivo: ejer12.c Versin 2.
Objetivo: Mostrar la conversin de tipos de datos char e int
Funcin: Convertir una cadena de dgitos en su equivalente
numrico, utilizando una funcin de conversin
*/
#include <stdio.h>
atoi(char s[]);

/* directiva al preprocesador */
/* prototipo de funcin */

main()
{
char cadena[10];
int numero;
printf("\nTeclee un entero: ");
gets(cadena);
numero = atoi(cadena);
printf("\nEl entero tecleado fu: %i \n ",numero);
return 0;
}/*fin de main */

/* convierte una cadena de digitos en entero */


atoi(char s[])
{
int i,n;
n=0;
for(i=0;s[i]>='0' && s[i]<='9';++i)
n=10*n+s[i]-'0';
return n;
}

Programacin en Lenguaje C

12

Luis Hernndez Lara

Centro de Investigacin en Computacin

2. OPERADORES.
2.1 Operadores aritmticos.
Los operadores aritmticos en C son:
divisin (/) y mdulo (%).

suma (+), resta (-), multiplicacin (*),

La divisin entera trunca la parte fraccional.


Existe un (-) unario, pero no existe un (+) unario.
De acuerdo a la precedencia y asociatividad (ver Tabla 2.4) los operadores * / % sern
ejecutados primero cuando son colocados en una ecuacin junto con los operadores +
y -. Si ms de un * / % estn colocados en la misma ecuacin, los operadores se
ejecutarn de izquierda a derecha.
El operador % slo puede ser aplicado a variables de tipo entero. El resultado es el
residuo de una divisin entera. Si hay residuo el residuo ser el valor resultante si no
hay residuo el valor resultante ser cero.
y = 10 % 5 ;
y = 10 % 4 ;

/* y=0; donde 10/5 = 2 con residuo 0 */


/* y=2; donde 10/4 = 2 con residuo 2 */

Las ecuaciones son evaluadas siempre de izquierda a derecha, a menos que se


indique otra cosa a travs del uso de parntesis dentro de la ecuacin. En ese caso los
( ) se evaluan primero. A continuacin se ejemplifica lo anterior:
main()
{
int a, b, c;
a=1; b=2; c=8;
a = c - (a+b) ;
b = a * (c/b) ;
b = 9%3 ;
c = 25%7 ;
b = 1;
c = a*c-b;

/* a es 5 */
/* b es 20 */
/* b es 0 */
/* c es 4 */
/*c es 19 - recuerde las operaciones previas */
/* que modificaron a, b, y c */

Programacin en Lenguaje C

13

Luis Hernndez Lara

Centro de Investigacin en Computacin

Otro ejemplo para el operador mdulo: un ao es bisiesto si es divisible por 4 pero no


por 100, excepto los aos que son divisibles por 400 son aos bisiestos.
if(year%4==0 && year%100!=0 || year%400==0)
procesar ao bisiesto
else
procesar ao no bisiesto

2.2 Operadores de incremento y decremento.


Los operadores de incremento y decremento estn diseados para incrementar o
decrementar una variable especfica por el valor decimal 1. Pueden ser usados con
ecuaciones, expresiones o asignaciones.
main()
{
int
i++;
--i;

i=0;
/* i es igual a 1 */
/* i ahora es igual a 0 */
/* --i; es lo mismo que i = i - 1; */

}
Cuando el operador es colocado frente a la variable, la variable ser incrementada o
decrementada antes de su uso. Esto modifica el valor de la variable, entonces se usa
este nuevo valor con la oracin que se est ejecutando. Cuando el operador se coloca
despus de la variable, el valor de la variable ser usado tal como est, en la ejecucin
de la instruccin y despus se modificar.
main()
{
int i=10,r;
r= i--;
r= --i;
}

/* r es igual a 10 */
/* r es igual a 8*/

Ver seccin 2.7, ejercicio 2.1.

Programacin en Lenguaje C

14

Luis Hernndez Lara

Centro de Investigacin en Computacin

2.3 Operadores a nivel de bits.


Estos operadores pueden usarse cuando se requiera manipulacin de bits. Las
operaciones a nivel de bits se refieren a la comprobacin, asignacin, o desplazamiento
de los bits reales que componen un byte o una palabra, correspondientes a los tipos
char e int. Las operaciones se aplican a los bits individuales de los operandos. Los
operadores se muestran en la siguiente tabla:

Operador
Descripcin
corrimiento de la variable a la derecha un nmero especfico de bits
>>
<<

corrimiento de la variable a la izquierda un nmero especfico de bits

&

Y a nivel de bits

O inclusivo a nivel de bits

O exclusivo a nivel de bits

complemento a uno (operador unario, usado en un valor o variable)

Tabla 2.1. Operadores para el manejo de bits.

A continuacin se muestra el uso de los operadores lgicos de bit.


main()
{
int y, n=07;
y= n & 0177;
y= n | 0177;
y= n ^ 0177;
y= n & ~0177;
y= n>>1;
y= n<<2;

/* 07 & 0177 = 7; y = 7 */
/* 07 | 0177 = 0177; y = 0177 */
/* 07 ^ 0177 = 0170; y = 0170 */
/* ~0177=0177600, 07 & 0177600 es 0; y = 0 */
/* recuerde que la palabra es de 16 bits */
/* 000 111 se corre a la derecha 1 bit= 000 011
as, y = 3 */
/* 000 111 se corre a la izq. 2 bits= 011 100
as, y = 034 o 0x1c */

Ver seccin 2.7, ejercicios 2.2 y 2.3.

Programacin en Lenguaje C

15

Luis Hernndez Lara

Centro de Investigacin en Computacin

2.4 Operadores relacionales y lgicos.


Los operadores relacionales son usados en oraciones condicionales. Estos operadores
sern usados para determinar condiciones de verdad (TRUE) o falsedad (FALSE).
Verdadero es el resultado de una evaluacin cuyo resultado es un valor no cero,
mientras que Falso es un resultado con valor cero. Tambin es posible evaluar el valor
almacenado en una variable para una condicin de Verdadero o Falso.

Operador
>
<
<=
>=
==
!=
&&
||
!

Descripcin
Mayor que
Menor que
Menor que o igual a
Mayor que o igual a
Igual a
no igual a (diferente)
Y lgico
O lgico
"NO" lgico

Tabla 2.2. Operadores relacionales y lgicos.

2.5 Operadores de asignacin.


Las expresiones de asignacin permiten la simplificacin de las expresiones donde a
las variables que se les est asignando un valor, estn incluidas en la computacin.
La siguiente tabla muestra el uso de los operadores de asignacin:

Operador
=
*=
+=
-=
/=

Ejemplo 1

Ejemplo 2
----

a=b
a*=b
a+=b
a-=b
a/=b

a=a*b
a=a+b
a=a-b
a=a/b

Tabla 2.3. Uso de los operadores de asignacin.

Programacin en Lenguaje C

16

Luis Hernndez Lara

Centro de Investigacin en Computacin

Operador
&=
|=
%=
>>=
<<=
^=

Ejemplo 1

Ejemplo 2

a&=b
a|=b
a%=b
a>>=b
a<<=b
a^=b

a=a&b
a=a|b
a=a%b
a=a>>b
a=a<<b
a=a^b

Tabla 2.3. Uso de los operadores de asignacin (cont.).

El siguiente cdigo muestra lo anterior:


main()
{
int a,b=1,c=2;
a = a*(b+1);
a *= b+1;
a = a%(b+c);
a %= b+c;
a = a+(b+c);
a += b+c;
a = a-(b+c);
a -= b+c;
a = a/(b+c);
a /= b+c;
}

/* misma sintaxis que... */


/* misma sintaxis que... */
/* misma sintaxis que... */
/* misma sintaxis que... */
/* misma sintaxis que... */

2.6 Precedencia de operadores.


El orden en el cual los operadores son aplicados (precedencia) as como el orden en el
que los operadores de un mismo nivel sern evaluados (asociatividad) se muestra en
la tabla siguiente:

Programacin en Lenguaje C

17

Luis Hernndez Lara

Centro de Investigacin en Computacin

Tipo de Operador

Operador

Asociatividad

Expresin
Unario

() [ ] . ->
~ !
*
&
++
sizeof(tipo)
Multiplicativo
* / %
Aditivo
+ Corrimiento
<< >>
Relacional
< <= > >= == !=
Y para bit (AND)
&
O exclusivo para bit ^
(XOR)
O inclusivo para bit
(OR)
Y lgico (AND)
O lgico (OR)
Condicional
Asignacin
Evaluacin
secuencial

--

Izquierda a derecha
Derecha a izquierda
Izquierda a derecha
Izquierda a derecha
Izquierda a derecha
Izquierda a derecha
Izquierda a derecha
Izquierda a derecha

Izquierda a derecha

&&
||
?:
= *= /= %= +=
>>= &= |= ^=
,

Izquierda a derecha
Izquierda a derecha
Derecha a izquierda
Derecha a izquierda

-=

<<=

Izquierda a derecha

Tabla 2.4. Precedencia y asociatividad de operadores en C.

Programacin en Lenguaje C

18

Luis Hernndez Lara

Centro de Investigacin en Computacin

2.7 Ejercicios del captulo.


Ejercicio 2.1.
/*
Archivo:
Objetivo:
Funcin:

ejer21.c
Mostrar el uso de operadores de incremento y
decremento
Remover todas las ocurrencias de un carcter
de una cadena de caracteres

*/
#include <stdio.h>
#include <conio.h>
remueve(char s[],int c);
main()
{
char cadena[60];
char caracter;
printf("\nTeclee una cadena: ");
gets(cadena);
printf("\nTeclee el carcter a remover: ");
caracter=getchar();
remueve(cadena,caracter);
printf("\nLa cadena sin el carcter '%c' es: \n",caracter);
printf("%s\n",cadena);
return 0;
}/*fin de main*/
remueve(char s[],int c)
{
int i,j;
for(i=j=0;s[i]!='\0';i++)
if(s[i]!=c)
s[j++]=s[i];
s[j]='\0';
return 0;
}

Programacin en Lenguaje C

19

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 2.2.
/*
Archivo:
Objetivo:
Funcin:

ejer22.c
Mostrar el uso del operador O exclusivo a nivel de bits.
Intercambiar el valor de dos variables sin utilizar una
tercera variable de paso.

*/
#include <stdio.h>
main()
{
int x = 15, y = 20;
printf("Antes del intercambio\n");
printf("x es %d, y es %d\n", x, y);
x = x^y;
/* intercambia x, y */
y = y^x;
x = x^y;
printf("x is %d, y is %d\n", x, y);
printf("Despus del intercambio\n");
return 0;
}

Programacin en Lenguaje C

20

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 2.3.
/*
Archivo: ejer23.c
Objetivo: Mostrar el uso de operaciones sobre bits
Funcin: Visualizar los bits de un entero y ver el
funcionamiento de la funcin getbits
*/
#include <stdio.h>
#include <conio.h>
/*Obtiene n bits desde la posicin p
recuerde que la posicin de los bits va del 0 al 15 */
getbits(unsigned x,unsigned p, unsigned n)
{
return ((x >> (p+1-n)) & ~(~0 << n));
}
/* muestra en pantalla los bits del nmero */
visu(unsigned b)
{
unsigned int t;
printf("\nEl nmero en decimal es : %i\n",b);
for(t=32768;t>0;t=t/2)
if(b & t)
printf("1 ");
else
printf("0 ");
printf("\n");
return 0;
}
main()
{
unsigned x,p,n;
printf("\nTeclee un nmero entero sin signo: ");
scanf("%i",&x);
visu(x);
printf("\nTeclee el nmero de bits solicitados: ");
scanf("%i",&n);
printf("\nTeclee a partir de que posicin: ");
scanf("%i",&p);
visu(getbits(x,p,n));
return 0;
}

Programacin en Lenguaje C

21

Luis Hernndez Lara

Centro de Investigacin en Computacin

3. ENTRADA Y SALIDA.
La biblioteca estndar de "C" proporciona varias funciones para leer o escribir
informacin desde el teclado, ya sean cadenas de caracteres o caracteres simples. A
continuacin veremos las ms comunes.

3.1 La funcin printf.


Es la funcin estndar de la biblioteca de "C", utilizada para desplegar informacin
sobre la terminal del usuario. La sintaxis de la funcin es la siguiente:
printf(formato,variables);
La funcin printf permite al usuario desplegar informacin en una gran variedad de
formatos de salida y el parmetro variables es opcional y puede omitirse.
El parmetro formato contiene la informacin que instruir a la funcin printf para que
imprima las variables.
La informacin del formato ser encerrada entre comillas. Si se planea imprimir texto,
no se requieren formatos adicionales. La siguiente tabla muestra los formatos tpicos:
Formato
%f
%c
%d
%e
%u
%o
%x
%s
%%
\n
\t

Descripcin
imprime un valor en punto flotante
imprime un carcter
imprime un valor decimal
imprime en notacin exponencial
imprime entero sin signo
imprime un valor octal
imprime un valor hexadecimal
imprime una cadena (secuencia de caracteres finalizando con el carcter
nulo)
imprime un %
imprime un carcter nueva lnea (salto de lnea)
imprime un carcter de tabulacin horizontal

Tabla 3.1. Formatos de impresin.


Cuando un parmetro de formato es utilizado, es necesario colocar variables asociadas
a ese formato. Las variables se colocan a continuacin del parmetro formato.

Programacin en Lenguaje C

22

Luis Hernndez Lara

Centro de Investigacin en Computacin

Cuando ms de una variables ser impresa, las variables necesitan ser separadas por
comas.

main()
{
int a=1;
char b= 'Z';
float c= 1.992;
printf("Esto es un ejemplo\n");
printf("a es %d, b es %c, c es %f\n",a,b,c);
}
Este programa imprime:
a es 1, b es Z, c es 1.992000

3.2 La funcin scanf.


Es utilizada para introducir datos desde el teclado u otros dispositivos de entrada y
coloca el valor introducido en la variable o variables apropiadas. El formato de esta
funcin se muestra a continuacin:
scanf (lista_de_control, lista_ de_ variables );
La funcin se divide en tres partes principales: la palabra scanf, la lista de control y la
lista de variables. La lista de control contiene los identificadores del tipo de datos
asociados con las variables que estn siendo ledas. La lista de variables contiene la
lista de esas variables.
Los formatos tpicos para el tipo de datos, son:
Formato
%c
%d
%i
%e
%f
%h

Descripcin
Lee un carcter nico
Lee un entero decimal
Lee un entero decimal
Lee un nmero en punto flotante
Lee un nmero en punto flotante
Lee un entero corto

Tabla 3.2. Formatos de lectura.

Programacin en Lenguaje C

23

Luis Hernndez Lara

Centro de Investigacin en Computacin

Formato
%o
%s
%x
%p

Descripcin
Lee un nmero octal
Lee una cadena
Lee un nmero hexadecimal
Lee un apuntador

Tabla 3.2. Formatos de lectura (cont.).

Un ejemplo del uso de scanf, se muestra a continuacin:


main()
{
int anio, mes, dia;
printf("\nTeclee la fecha en el formato MM/DD/AAAA : );
scanf("%d/%d/%d, &mes, &dia, &anio);
printf(\nLa fecha es %d:%d:%d,mes,dia,anio);
}
Este programa imprime:
Teclee la fecha en el formato MM/DD/AA : 04/05/1999
La fecha es 04/05/1999

Todas las variables usadas para recibir los valores a travs de scanf() deben pasarse
por sus direcciones. Esto permite crear una llamada por referencia y permite a una
funcin alterar el contenido de un argumento. En la seccin de apuntadores se
ampliar sta definicin.
En el caso de cadenas, estas se leern en arreglos de caracteres y el nombre del
arreglo, sin ningn ndice, es la direccin del primer elemento del arreglo. Suponiendo
que la direccin es el nombre de un arreglo de caracteres, para leer una cadena en el
arreglo se hace de la siguiente manera:
char cadena[20];
scanf(%s,cadena);

En este caso, cadena ya es un apuntador y no necesita precederse por el operador &.

Programacin en Lenguaje C

24

Luis Hernndez Lara

Centro de Investigacin en Computacin

A continuacin se muestra un ejemplo:


main()
{
char nombre[15];
char apellido[15];
printf("\n Introduzca nombre y apellido : );
scanf("%s %s, nombre, apellido);
printf(\n Su nombre es %s, nombre);
printf(\n Su apellido es %s, apellido);
}

Los elementos de entrada de datos deben ser separados por espacios, tabuladores o
nuevas lneas. La puntuacin como comas, punto y coma y similares no cuentan como
separadores.
Esto significa que:

scanf(%d%d,&x,&y);

aceptar una entrada de 100 300, pero no aceptar 100,200.


Un * puesto detrs del % y antes del cdigo de formato leer datos del tipo
especificado, pero suprimir su asignacin. As,
scanf(%d%*c%d,&entero,&decimal);
dada la entrada 234.56, pondr el valor 234 en entero, descarta el punto y asigna a
decimal el valor de 56.
Las rdenes de formato pueden especificar un modificador mximo de campo. Por
ejemplo, si no se desean leer ms de 20 caracteres en la cadena nombre, entonces
se escribir:
scanf(%20s,nombre);

3.3 La funcin putch.


Se usa para mandar un carcter de salida a la pantalla. La funcin consiste de dos
partes: la palabra putch y la variable entera o constante entera conteniendo el valor
ASCII del carcter a ser impreso.
putch( valor_entero);

Programacin en Lenguaje C

25

Luis Hernndez Lara

Centro de Investigacin en Computacin

A continuacin veamos un ejemplo:

main()
{
int x;
x = 65;
putch(x);
putch(66);
}
El programa imprime:
AB

Otro ejemplo:
main()
{
char caracter;
caracter = Y;
putch(caracter);
putch(Z);
}

3.4 Las funciones getchar y getch.


La funcin getchar lee el siguiente carcter de entrada de una secuencia de texto y lo
devuelve como su valor. El formato de sta funcin es:
variable_entera = getchar();
una peculiaridad de getchar, es que puede conservar el valor que ley, de tal forma que
puede usarse en combinacin con otro tipo de instrucciones como se muestra a
continuacin:
if(getchar()=='A') print("Oprimiste la letra correcta ");
La funcin getch() es usada para tomar un carcter desde el teclado y colocar su valor
ASCII asociado en una variable entera. El formato de sta funcin es:
variable_entera = getch();

Programacin en Lenguaje C

26

Luis Hernndez Lara

Centro de Investigacin en Computacin

A continuacin, se ejemplifica su uso.


main()
{
int x;
x = getch();
putch(x);
}
Ver seccin 3.5, ejercicios 3.1 y 3.2.

Existen otras funciones para entrada y salida. Se recomienda que el estudiante realice
una exploracin de ellas en la versin del lenguaje C que est utilizando para
profundizar sobre el tema.

Programacin en Lenguaje C

27

Luis Hernndez Lara

Centro de Investigacin en Computacin

3.5 Ejercicios del captulo.


Ejercicio 3.1.
/*
Archivo: ejer31.c
Objetivo: Mostrar el uso de funciones de entrada/salida
Funcin: Contar los caracteres que se teclean desde la entrada, ver
el funcionamiento de la funcin getchar.
*/
#include <stdio.h>
main()
{
int contador;
contador = 0;
while(getchar() != EOF)
contador++;
printf("\nEl no. de caracteres tecleados fue de: %d",contador);
return 0;
}

Ejercicio 3.2.
/*
Archivo: ejer32.c
Objetivo: Mostrar el uso de funciones de entrada/salida
Funcin: Convierte la entrada de datos (por teclado) de minsculas
a maysculas
*/
#include <stdio.h>
main()
{
int car;
while((car = getchar()) != '0')
if(car >= 'a' && car <= 'z')
putchar(car-32);
else
putchar(car);
return 0;
}

Programacin en Lenguaje C

28

Luis Hernndez Lara

Centro de Investigacin en Computacin

4. EXPRESIONES CONDICIONALES Y CONTROL DE FLUJO.


Las expresiones condicionales se usan de la siguiente forma:
expresin condicional
oracin;
Si la expresin es verdadera (TRUE, no cero), permitir la ejecucin de la oracin. Si la
expresin es evaluada falsa (FALSE, cero), la oracin no se ejecutar.

4.1 La oracin if.


La oracin if en el lenguaje "C" evala la expresin condicional y ejecuta la oracin
asociada slo cuando la expresin es evaluada verdadera (TRUE). Su sintaxis es:
if (expresin)
oracin
donde "oracin" puede ser una oracin simple terminada con punto y coma (;), o un
bloque de oraciones encerradas entre llaves { }. En las siguientes definiciones
usaremos "oracin" como sinnimo de bloque de oraciones.
main()
{
int a=0, b=1;
if( a < b )
a=1;
}

/* a ahora es igual a 1 ya que es "menor que" b */

Bloques de oraciones pueden ser ejecutadas usando las llaves {}.


main()
{
int a=0,b=1,c;
if( a < b )
{
/* cada oracin se ejecuta ya que a es "menor que " b */
a=1;
b=2;
c=3;
}
/* bloques de oraciones no requieren un punto y coma final */
}

Programacin en Lenguaje C

29

Luis Hernndez Lara

Centro de Investigacin en Computacin

4.2 La oracin else.


La oracin else caso contrario puede ser opcionalmente usada para ejecutar una
oracin simple o bloque de oraciones si la oracin if evala falso (FALSE). La sintaxis
asociada es la siguiente:
if (expresin)
oracin-1
else
oracin-2
Lo cual se muestra en el cdigo siguiente:
main()
{
int a=5,b=1;
if( a < b )
a=1;
else
a=2;
/* a es colocada a 2 ya que no fu menor que b */
}

Todas las condiciones en una oracin if son evaluadas a una condicin no cero. Esto
significa que la(s) oracin(es) son ejecutadas a continuacin de la oracin if cuando la
condicin o expresin es evaluada como verdadera (no igual a cero).
main()
{
int a=5,b=1;
if( a )
b=10;
/* a es Verdadera ya que no es igual a cero; por lo
tanto, b ser igual a 10 */
else
b=20;
}

Usando los operadores relacionales, las condiciones pueden ser combinadas usando
parntesis (), para formar una condicin Verdadera o Falsa.

Programacin en Lenguaje C

30

Luis Hernndez Lara

Centro de Investigacin en Computacin

main()
{
int a=5, b=6, c=8, d=7, e;

if( (a < b) && (c > d) )


e=10;

/* si a es "menor que" b Y c es "mayor que" d,


asignar el valor 10 a la variable e */
/* evalua a Verdadero */
/* e es ahora asignado a 10 */

4.3 Expresin condicional con el operador "?:".


La oracin if-else presenta otra forma de uso. La forma enigmtica, la cual se usa en
lugares no legales para la forma normal de la oracin. El operador ternario "?:" es la
base de este tipo de oraciones.
La sintaxis es la siguiente:
(expresin1) ? expresin2 : expresin3;
Si la expresin1 es verdadera se hace la expresin2, en caso contrario se hace la
expresin3. Por ejemplo:
main()
{
int a=0, b=1, c;
c = ( a < b ) ? 1 : 2;
/* a es "menor que" b; por lo tanto c es igual a 1 */
}

"C" permite que la oracin enigmtica sea usada en lugares donde un if-else normal no
puede ser usado. El paso de un parmetro a una funcin es un ejemplo de ello:
main()
{
int a=3,b=1;
printf("%d\n",(a < b)?1:100);
/* a no es "menor que" b; por lo tanto, el valor 100 es pasado
a printf() e impreso en la pantalla del usuario */
}

Programacin en Lenguaje C

31

Luis Hernndez Lara

Centro de Investigacin en Computacin

Otro ejemplo sera convertir letras maysculas en minsculas:


c = (letra>=65 && letra<=90) ? letra+32 : letra;

4.4 La oracin else- If.


Para evaluar ms de una condicin, hay una oracin condicional con la sintaxis: else
if(). La cual permite varias evaluaciones seguidas de una oracin if. La oracin if puede
usar una o ms oraciones else if() y puede opcionalmente usar al final la oracin
else.
Una vez que una oracin else if() evale verdadero, ninguna otra oracin else if()
ser evaluada.
main()
{
int a=1,b=1;
if( a < b )
a=1;
else if( a == b )
a=0;

/* a es colocada a 0 */
/* otro ejemplo */

if( a < b )
a=1;
else if( a == b )
a=0;
else
a=2;

/* a es colocada a 1 */

/* otro ejemplo */
if( a < b )
a=1;
else if( a == b )
a=2;
else if( a > b )
a=3;

/* a es colocada a 2 */

Programacin en Lenguaje C

32

Luis Hernndez Lara

Centro de Investigacin en Computacin

4.5 La oracin switch.


La oracin switch es usada para evaluar una variable entera, expresin o variable de
carcter la cual ser comparada con un nmero de casos dado.
Cuando un caso coincide, la ejecucin del programa comienza en ese punto y contina
hasta encontrar una oracin break o hasta que el fin del switch es alcanzado.
Cada caso debe contener el valor de una constante entera, constante de carcter o
expresin.
Cuando ningn caso coincida, el caso de la etiqueta default se ejecuta.
El caso por omisin (default) es opcional y no tiene una constante asociada.
Ejemplo:
main()
{
int c=10;
switch(c) {
case 1:
case 3:
case 3+3:
case 'a':
case 'b':
case 10:
/* caso 10 coincide */
printf("coincide\n");
default:
printf("valor de omisin\n");
}
}
Este programa imprime:
coincide
valor de omisin

Cada caso dentro del switch debe ser nico y debe ser definido como una constante
(las variables no son permitidas).
"C" tambin permite la posibilidad de anidar oraciones switch, veamos:

Programacin en Lenguaje C

33

Luis Hernndez Lara

Centro de Investigacin en Computacin

switch (tipo) {
case 1:
switch(figura) {
case 0: printf("Dibujar Cuadro");
break;
case 1: printf("Dibujar Circulo");
}
break;
case 2:
switch(objeto) {
case 0: printf("Dibujar Cubo");
break;
case 1: printf("Dibujar Esfera");
}
}

4.6 La oracin break.


La oracin break puede ser usada en la oracin switch para terminar la ejecucin del
switch y salir de l. Si un break no es usado entre los casos, todas las oraciones a
continuacin del caso sern ejecutadas. La oracin break tambin puede ser usada
para terminar uno de los ciclos while, for o do while. A continuacin veamos un
ejemplo:
main()
{
int c=6;
switch(c) {
case 1:
break;
case 3:
case 3+3:

/* empata 6 */
printf("coincide\n");

case 'a':
case 'b':
case 10:
printf("diez\n");
break;

/* sale del switch */

default:
printf("valor de omisin\n");
}
}

Programacin en Lenguaje C

34

Luis Hernndez Lara

Centro de Investigacin en Computacin

Este programa imprime:


coincide
diez

4.7 La oracin while.


La oracin while evala una expresin, entonces ejecuta la oracin siguiente o bloque
de oraciones si la expresin evala verdadero (no cero).
main()
{
int a=1;
/* Incrementar a hasta que a=100 */
while( a<100 )
a++;
printf("a es %d\n",a);
}
El programa imprime:
a es 100
Ver seccin 4.12, ejercicio 4.1.

4.8 La oracin for.


La oracin for es til cuando la inicializacin e incremento de variables se requiere. La
oracin for ejecuta la primera oracin antes del punto y coma (1), entonces evala la
segunda expresin para verdadero o falso (2). Si la expresin es verdadera, la oracin
asociada o bloque de oraciones se ejecuta (3). Si la expresin evala falso, las
oraciones no se ejecutan y la ejecucin del programa contina despus de la oracin
for.
Cuando la expresin condicional evala verdadero (2), la(s) oracin(es) (3) son
ejecutadas. Entonces la ltima oracin (4) se ejecuta finalmente, la expresin
condicional (2) una vez ms es probada y el ciclo contina. Note que la primer oracin
(1) solamente se ejecuta una vez.
Estructura de la oracin for:
1
2
4
3
for(oracin; expresin condicional; oracin ) oracin;

Programacin en Lenguaje C

35

Luis Hernndez Lara

Centro de Investigacin en Computacin

Cuando la condicin es verdadera la secuencia es:


1 2 3 4 2 3 4 2 3 4...
Cuando es falsa:
12
Ejemplo:
main()
{
int a;
for(a=1; a < 100; a++)
printf("a es ahora %d\n", a);
}
El programa imprime:
a es ahora 1
a es ahora 2
...
a es ahora 99
Es posible tener mltiples oraciones en las posiciones 1 y 4 usando el operador coma
(,) para separar las oraciones. Recuerde que tambin es posible usar un bloque de
oraciones en la posicin (3).
for(oracin,oracin; condicional; oracin, oracin)
{
oracin;
oracin;
oracin;
}
En forma ms general la oracin for puede tener la siguiente forma:
for(expresin1; expresin2; expresin3) oracin;

Ver seccin 4.12, Ejercicios 4.2 , 4.3 y 4.4.

Programacin en Lenguaje C

36

Luis Hernndez Lara

Centro de Investigacin en Computacin

Las partes que componen el for son opcionales, de tal forma que podemos tener las
siguientes posibilidades:
a) Un for sin cuerpo:
for(i=0; i<=10000 ; i++) ;
b) Un for sin partes:
for( ; ; )
{
/* las oraciones que aqu se coloquen se ejecutarn en forma infinita */
}

4.9 La oracin do-while.


La oracin do while ejecuta la oracin o bloque de oraciones, entonces evala la
expresin. Si la expresin es verdadera, la ejecucin del ciclo contina.
main()
{
int
a=1;
do {
printf("a es ahora %d\n", a); a++;
} while( a < 100 );
}
El programa imprime:
a es ahora 1
a es ahora 2
...
a es ahora 99

4.10 La oracin continue.


La oracin continue es usada para hacer que la siguiente iteracin de un ciclo while, do
while o for se ejecute. Esto es, que el ciclo inicie otra vez.
Despus de que la oracin continue es ejecutada dentro de las oraciones while() y do
while(), la oracin de condicin del ciclo es ejecutada. Cuando se trata de una oracin
for, la oracin (4) es ejecutada a continuacin de la ejecucin de la oracin continue.

Programacin en Lenguaje C

37

Luis Hernndez Lara

Centro de Investigacin en Computacin

En esencia cuando una oracin continue se encuentra, su ejecucin remite el flujo del
programa antes de la llave que termina el for(), while() o do while() respectivo.
Entonces la siguiente iteracin del ciclo contina.
main()
{
int i=0, a=100;
while( i<3 ) {
printf("-- tope del loop\n");
if((a+i)==100)
a++;
else if((a+i)==101)
{
a++;
printf("** contina ejecucin \n");
continue; /* comienza el loop otra vez */
}
else
i++;
printf("\ta=%d...i=%d\n",a,i);
} /* fin del while */
}
El programa imprime:
-- tope del loop
a=101...i=0
-- tope del loop
** contina ejecucin
-- tope del loop
a=102...i=1
-- tope del loop
a=102...i=2
-- tope del loop
a=102...i=3

4.11 La oracin goto.


La oracin goto ocasiona que se modifique el flujo de ejecucin de un programa al
estipular cual es la siguiente instruccin a ejecutar fuera de la secuencia original.
Permite saltar a cualquier lugar dentro de una funcin especfica. Su abuso puede

Programacin en Lenguaje C

38

Luis Hernndez Lara

Centro de Investigacin en Computacin

ocasionar programas poco eficientes y sobre todo rompe con el esquema de la


programacin estructurada.
main()
{
int a;
for(a=1; a<10000;a*=10)
{
/* recuerde que a*=10 es lo mismo que a = a*10 */
if( a==1000 )
goto salto; /* brinca a la etiqueta salto */
}
salto:
printf("Hemos usado un goto!\n");
}

Programacin en Lenguaje C

39

Luis Hernndez Lara

Centro de Investigacin en Computacin

4.12 Ejercicios del captulo.


Ejercicio 4.1.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer41.c
Mostrar el uso de las oraciones if y while
Convierte nmeros arbigos a romanos de 1 a 3999

#include <stdio.h>
#include <conio.h>
main()
{
int num;
clrscr ();
/* sta funcin limpia la pantalla, no es de ANSI C */
printf("Dar un nmero entero <= 3999"
" para convertirlo a nmero romano ");
scanf("%d",&num);
if(num <= 3999)
{
if(num>=1000){
while(num>=1000){
printf("M");
num=num-1000;}
}
if(num>=900){
printf("CM");
num=num-900;}
if(num>=600){
printf("D");
num=num-500;}
if(num>=500){
printf("D");
num=num-500;}
if(num>=400){
printf("CD");
num=num-400;}
if(num>=100){
while(num>=100){
printf("C");
num=num-100;}
}
if(num>=90){
printf("XC");
num=num-90;}
if(num>=60){
printf("L");
num=num-50;}

Programacin en Lenguaje C

40

Luis Hernndez Lara

Centro de Investigacin en Computacin

if(num>=50){
printf("L");
num=num-50;}
if(num>=40){
printf("XL");
num=num-40;}
if(num>=10) {
while(num>=10){
printf("X");
num = num-10;
}
}
if(num>=9){
printf("IX");
num=num-9;}
if(num>=6){
printf("V");
num=num-5;}
if(num>=5){
printf("V");
num=num-5;}
if(num>=4){
printf("IV");
num=num-4;}
if(num>=1){
while(num>=1){
printf("I");
num=num-1;}
}
}else printf("Este nmero no se puede convertir, es > 3999 o < 1");
getch();
return 0;
}

Programacin en Lenguaje C

41

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 4.2.
/*
Archivo:
Objetivo:
Funcin:

ejer42.c
Mostrar el uso de las oraciones switch, while y for
Programa que cuenta letras minsculas, maysculas,
dgitos, operadores aritmticos, blancos y otros
caracteres introducidos por el usuario

*/
#include<stdio.h>
#include<conio.h>
main()
{
int c,i,nwhite,nope,nmay,nmin,nother,ndig[10];
nwhite=nope=nmay=nmin= nother=0;
for(i=0;i<10;i++)
ndig[i]=0;
printf("\nEscribe un texto:\n");
while((c=getche())!='\r')
{
if (c>='A' && c<='Z')
c='A';
else
if(c>='a' && c<='z')
c='a';
switch (c){
case 'A': nmay++;
break;
case 'a': nmin++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': ndig[c-'0']++;
break;
case ' ': nwhite++;
break;
case '+':
case '-':
case '*':
case '/': nope++;
break;

Programacin en Lenguaje C

42

Luis Hernndez Lara

Centro de Investigacin en Computacin

default: nother++;
break;
}
}
printf("\nOcurrencias de digitos: \n");
printf("0-1-2-3-4-5-6-7-8-9\n");
for(i=0; i<10; i++)
printf("%d ",ndig[i]);
printf("\n espacios en blanco=%d\nmaysculas=%d\n"
"minsculas=%d\noperadores=%d\notros=%d\n",
nwhite,nmay,nmin,nope, nother);
getch();
return 0;
}

Programacin en Lenguaje C

43

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 4.3.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer43.c
Mostrar el uso de la oracin for con expresiones como
parte de sus elementos
Leer caracteres y desplegarlos en pantalla

#include <stdio.h>
#include <conio.h>
mensaje();
lee();
imprime(int);
main()
{
char caracter;
for(mensaje(); (caracter=lee()) != '\r'; mensaje())
imprime(caracter);
return 0;
}
/* funcin que imprime leyenda */
mensaje()
{
printf("\nIntroducir carcter: ");
return 0;
}
/* funcin que lee un carcter y lo regresa */
lee()
{
char car;
car = getch();
return car;
}
/* funcin que imprime un carcter */
imprime(int carascii)
{
printf("\nEl carcter es: %c", carascii);
return 0;
}

Programacin en Lenguaje C

44

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 4.4.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer44.c
Mostrar el uso de la oracin for.
Muestra los nmeros primos entre el rango 1-100

#include <stdio.h>
#include <conio.h>
main()
{
int i, j, k,

primo;

clrscr();
for(i=1; i<=100; i++)
{
primo = 1;
for(j=2; j<i; j++)
{
k = i%j;
if (k == 0) primo = 0;
} /* fin del for interno */
if (primo) printf("%d ",i);
} /* fin del for externo */
getch();
return 0;
} /* fin de main */

Programacin en Lenguaje C

45

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 4.5.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer45.c
Mostrar el uso de la oracin for.
Descomposicin cannica de un nmero entero

#include <stdio.h>
#include <conio.h>
main()
{
int n, i;
char pausa;
printf("\nTeclee nmero para su descomposicin cannica : ");
scanf("%d",&n);
for(i=2; i<=n;)
if(!(n%i))
{
printf("%d *",i);
n/=i;
}
else
i++;
pausa = getch();
return 0;
}

Programacin en Lenguaje C

46

Luis Hernndez Lara

Centro de Investigacin en Computacin

5. CONVERSIN DE TIPOS DE DATOS.


5.1 Operador sizeof.
En tiempo de compilacin, este operador devuelve el tamao de la variable o tipo que
est como operando. La palabra clave "sizeof" precede a la variable o nombre del tipo
del operando. Si sizeof opera sobre un tipo de datos, entonces el tipo debe aparecer
entre parntesis.
bytes = sizeof(float);

bytes = sizeof variable;

5.2 Conversin de tipos.


Cuando se mezclan constantes y variables de diferentes tipos en una expresin, "C" las
convierte en el mismo tipo. El compilador convertir todos los operandos al tipo del
operando ms grande. Las reglas son las siguientes:
a) Todos los char y short se convierten a int. Todos los float a double.
b) char e int pueden mezclarse libremente en expresiones aritmticas, cada char en
una expresin se convierte a un int.
c) Para todo par de operandos:

si uno es long double el otro se convierte a long double,


si uno es double el otro se convierte en double,
si uno es long el otro se convierte en long,
si uno es unsigned el otro se convierte en unsigned.

Otro uso de la conversin automtica de tipos es en las expresiones relacionales como


i > j y las expresiones relacionales conectadas por && y ||. Las cuales tendran valores
1 si son verdaderas y 0 si son falsas. La siguiente expresin:
digito = c >= '0' && c <= '9';
coloca la variable dgito a 1 si c es un dgito y 0 si no lo es.
Para forzar la conversin de tipo en expresiones, se utiliza la construccin denominada
"cast" que tiene la siguiente forma:
(tipo) expresin;
la construccin fuerza a que la expresin quede del tipo descrito entre parntesis.

Programacin en Lenguaje C

47

Luis Hernndez Lara

Centro de Investigacin en Computacin

Por ejemplo:
resultado = (float) entero1/entero2;
resultado = 1.8

Programacin en Lenguaje C

si entero1 = 9 y entero2 = 5

48

Luis Hernndez Lara

Centro de Investigacin en Computacin

6. MBITO DE LA VARIABLES.
Las clases de almacenamiento en C son: automtico, esttico, externo y de
registro.
Las variables automticas son locales a cada bloque de oraciones y pierden sus
valores cuando se termina la ejecucin del bloque. Recuerde que un bloque de
oraciones consiste de oraciones entre llaves {}. Una funcin es un ejemplo de un
bloque de oraciones.
Las variables externas existen y conservan sus valores a travs de la ejecucin de
todas las funciones y pueden ser usadas o modificadas desde todas las funciones del
programa. Estas variables son consideradas globales.
Las variables estticas definidas dentro de una funcin son locales a la funcin. Las
variables estticas conservan sus valores hasta la siguiente ocasin que la funcin es
llamada.
Cuando el control regresa a una funcin la cual contiene una variable esttica, la
variable contiene el valor de la llamada previa.
Cuando se inicializa al momento de declararse una variable esttica, el valor de inicio
slo ser vlido para la primera invocacin de la funcin que contiene la variable. Las
siguientes ocasiones que se invoque la funcin, la variable esttica ya no se inicializar
sino que conservar el ltimo valor de la ltima llamada a la funcin.
Las variables estticas externas permanecen locales al mdulo de cdigo fuente en el
cual fueron definidas. Esto es un factor interesante cuando un proyecto se desarrolla
mediante el uso de archivos de cdigo fuente los cuales son compilados por separado y
encadenados juntos para crear un archivo ejecutable.
Esto significa, que las variables estticas externas sern globales a todas las funciones
en el archivo de cdigo fuente especifico en el cual fueron definidas.
Las variables de registro son variables las cuales usan los registros de mquina
existentes en el sistema local. Esto slo cuando el compilador y el uso de los registros
lo permita. Tienen las mismas caractersticas que las variables automticas, pero no se
puede tener su direccin en una variable tipo apuntador a travs del uso del operador
de direccin &.
El siguiente ejemplo ilustra el uso de una variable esttica:

Programacin en Lenguaje C

49

Luis Hernndez Lara

Centro de Investigacin en Computacin

main()
{
ejemplo();
ejemplo();
}
ejemplo()
{
static char
register int
char a='z';

d='0';
indice;

for(indice=0; indice<100; indice++) ;


printf("d is %c\n",d);
d='d';
}

En el ejemplo anterior, la variable d es igual al carcter 0 cuando se compila. La


primera vez que la funcin ejemplo() se ejecuta, el programa imprime el carcter 0. La
segunda vez que ejemplo() se ejecuta, el programa imprime el carcter d. Esto se
debe a que la variable esttica retiene su valor desde la primera llamada a la funcin
ejemplo().

Programacin en Lenguaje C

50

Luis Hernndez Lara

Centro de Investigacin en Computacin

7. ARREGLOS.
7.1 Definicin.
El formato general para la declaracin de un arreglo unidimensional es:
tipo nombre_variable[tamao];
donde: tipo
- determina el tipo de datos de cada elemento del arreglo,
tamao - define cuntos elementos guardar el arreglo.
Para un arreglo unidimensional, se calcula el tamao del total del arreglo en bytes, as:
Bytes Totales = sizeof(tipo) * longitud del arreglo
A continuacin veamos la de claracin de un arreglo:
int datos[7];
La definicin anterior asigna el nombre de la variable datos a un arreglo de siete
enteros. Cada entero puede ser accesado usando la siguiente sintaxis :

datos[2]

datos[3]

datos[4] datos[5]

datos

datos[0]...entero #1

datos[1]...entero #2 ...... datos[6]...entero #7

Los arreglos en C comienzan con el elemento [0]. Por lo tanto para la definicin
anterior no existe el elemento [7]. Un ejemplo sencillo es el siguiente:

Programacin en Lenguaje C

51

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Calcular la media de diez nmeros enteros */


main() {
int ejemplo[10],i;
float prom;
for(i=0; i<10; i++)
{
printf("\nIntroducir el nmero-%d: ", i);
scanf("%d", &ejemplo[i]);
}
prom = 0;
/* Se hace la sumatoria */
for(i=0; i<10; i++) prom = prom + ejemplo[i];
/* Se calcula el promedio y se imprime, -Note la divisin entera- */
printf("\nLa media es %f\n", prom/10);
}

7.2 Inicializacin de arreglos.


Cabe aclarar que en "C" las variables externas y estticas tendrn inicialmente el valor
de cero. Las variables automticas (locales) y de registro tiendrn valores indefinidos
("basura").
Cuando un arreglo se define, hay dos formas de inicializarlo. La primera inicializar en
tiempo de compilacin. La segunda es colocar datos en el arreglo en tiempo de
ejecucin del programa.
Cuando un arreglo de caracteres es inicializado como una cadena, el compilador
inicializar los elementos del arreglo y agregar un carcter nulo ('\0' or 0) para
determinar el fin de la cadena.
El siguiente ejemplo define un arreglo de caracteres y un arreglo de enteros. Utilizando
las comillas , una cadena es definida, lo cual causa que el compilador convierta todos
los datos dentro de las comillas a caracteres ASCII.
Cuando las llaves son usadas {}, el compilador toma cada constante especificada y
coloca su valor dentro del arreglo.

Programacin en Lenguaje C

52

Luis Hernndez Lara

Centro de Investigacin en Computacin

La primer forma de inicializar un arreglo es la siguiente:


char cadena[] = "Hola";
char cadena[] = {'H','o','l','a','\0'};
int numeros[] = { 1,2,3};

/* si la declaracin es local o global */


/* definicin equivalente a la primera */
/* si la declaracin es global */

cadena[0]='H' cadena[1]='o' cadena[2]='l' cadena[3]=a


numeros[0]=1 numeros[1]=2 numeros[2]=3

cadena[4]=\0

Cuando no se define el tamao del arreglo al momento de su definicin e inicializacin,


el compilador slo proporcionar memoria suficiente para contener el dato
especificado. Estos arreglos se denominan arreglos no delimitados. La ventaja de
este tipo de arreglos es que se pueden agregar o eliminar elementos del arreglo sin
necesidad de definir el tamao del mismo. Veamos un ejemplo:
char cadena[] = "Hola";
/* arreglo global */
void main()
{
int numeros[] = {1,2,3};
/* arreglo local */
int i,j;
for(i=0; cadena[i] != '\0'; i++) {
printf("el carcter es: %c\n",cadena[i]);
printf("el arreglo de nmeros tiene de longitud: %d\n",sizeof numeros);
}
}

La segunda forma de inicializar un arreglo es cuando el programa se ejecuta. El


siguiente ejemplo inicializa cada entero en el arreglo con un valor decimal -1. Entonces
cada entero dentro del arreglo es impreso.
void main()
{
int arreglo[10], i;
for( i=0; i<10; i++)
arreglo[i] = -1;
for( i=0; i<10; i++)
printf("%d\n", arreglo[i]);
}

Programacin en Lenguaje C

53

Luis Hernndez Lara

Centro de Investigacin en Computacin

7.3

Uso de los operadores de incremento y decremento para referenciar


elementos en arreglos.

Los operadores de incremento y decremento pueden ser utilizados muy eficientemente


cuando son usados en arreglos. El siguiente ejemplo muestra como valores especficos
dentro del arreglo pueden ser referenciados utilizando los operadores ++ y -- antes o
despus del nombre de la variable que sirve como ndice.
void main()
{
int i=0;
char arreglo[]="En curso";
printf("%c",arreglo[++i]); /* imprime el carcter 'n' */
printf("%c",arreglo[i--]);
/* imprime el carcter 'n' */
printf("%c",arreglo[i]);
/* imprime el carcter 'E' */
i=3;
printf("%c",arreglo[i++]); /* imprime el carcter 'c' */
printf("%c",arreglo[i]);
/* imprime el carcter 'u' */
printf("%c",arreglo[--i]); /* imprime el carcter 'c' */
}

Ver seccin 7.6, ejercicio 7.1.

7.4 Arreglos multidimensionales y arreglos de cadenas.


7.4.1 Arreglos Multidimensionales.
Un arreglo multidimensional puede ser usado para almacenar cualquier tipo de datos
definido. En esencia es un arreglo de arreglos unidimensionales. La definicin de un
arreglo multidimensional se muestra a continuacin:
tipo nombre[fil] [col];
donde:
tipo:
nombre:
fil:
col:

Programacin en Lenguaje C

es el tipo de datos que contendr el arreglo


es el nombre del arreglo
es el nmero de filas del arreglo
es el nmero de columnas del arreglo

54

Luis Hernndez Lara

Centro de Investigacin en Computacin

Arreglo Bidimensional "nombre"


f
i
l
a
s

0
1
2
3
...
...
...
fil-1
0

...

...

...

col-1

columnas
Para hacer referencia a un elemento del arrgelo se hace de la siguiente manera:
nombre[fila][columna]
arreglo.

por ejemplo

nombre[3][2] se refiere al elemento 3,2 del

El parmetro columna es incrementado para accesar cada uno de los elementos de


una fila especfica. El parmetro fila es incrementado para accesar el siguiente grupo
de columnas.
El siguiente ejemplo ilustra la diferencia entre un arreglo unidimensional y uno
multidimensional:
char cadena[] = "En clase";
char arreglo[3][10];
El arreglo multidimensional llamado arreglo puede contener tres copias del arreglo
unidimensional llamado cadena. Ejemplo:
void main()
{
char cadena[] = "En clase";
char arreglo[3][10];
int i,j;
for(i=0; i<3; i++){
for(j=0; cadena[j] != '\0'; j++)
arreglo[i][j] = cadena[j];
arreglo[i][j] = cadena[j];
/* Copia el carcter Nulo */
}
}

Programacin en Lenguaje C

55

Luis Hernndez Lara

Centro de Investigacin en Computacin

El ejemplo, copia cadena en arreglo tres veces, resultando:


arreglo[0] = "En clase"

arreglo[1] = "En clase"

arreglo[2] = "En clase"

A continuacin veamos un ejemplo de inicializacin de un arreglo bidimensional:

Arreglo Delimitado
int cuadrados[5][2] = { 1, 1,
2, 4,
3, 9,
4, 16,
5, 25
};

Arreglo No Delimitado
int cuadrados [][2] = { 1, 1,
2, 4,
3, 9,
4, 16,
5, 25,
};

Ver seccin 7.6, ejercicio 7.2.

7.4.2 Arreglos de Cadenas.


Lo visto anteriormente nos indica que para crear un arreglo de cadenas, se usa un
arreglo de caracteres de dos dimensiones, en el que el tamao del ndice izquierdo
determina el nmero de cadenas y el tamao del ndice derecho especfica la longitud
mxima de cada cadena.
Por ejemplo, la siguiente lnea
char cadenas[100][80];
declara un arreglo que puede contener 100 cadenas cada una de ellas de una longitud
de 80 caracteres como mximo.
Para hacer ms simple el uso de cadenas, ANSI "C" incluye algunas rutinas para su
manejo. Por lo sencillas que son, su uso se ver en los ejercicios de la seccin 7.6.
Para profundizar sobre el tema, consulte la ayuda en lnea del compilador de "C" que
est utilizando.
Ver seccin 7.6, ejercicios 7.3 y 7.4.

Programacin en Lenguaje C

56

Luis Hernndez Lara

Centro de Investigacin en Computacin

7.5 Inicializacin de arreglos desde la entrada de datos.


El siguiente ejemplo usa la funcin getchar() para obtener un carcter como entrada
desde el teclado, entonces almacena el carcter en un arreglo.
void main()
{
int i=0;
char arreglo[30];
do{
arreglo[i]= getchar();
}while(arreglo[i++] != '\n' && i<29);
/* Termina la cadena con un nulo */
arreglo[i]='\0';
printf("el arreglo es: %s\n",arreglo);
}

7.6 Ejercicios del captulo.

Programacin en Lenguaje C

57

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 7.1.
/*
Archivo: ejer71.c
Objetivo: Mostrar el uso de un arreglo unidimensional
funcin: Ordenar ascendentemente un conjunto de nmeros enteros
en un arreglo unidimensional.
Se incluyen algunas funciones de Turbo C, slo para efecto de mejorar la
lectura y despliegue de resultados pero que no interfieren en el ordenamiento
(clrscr(), gotoxy()). Las funciones gets() y atoi son de ANSI C.
Se utiliz el mtodo de Insercin Directa para ordenar.
*/
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int nele,vect1[51];
lectura();
main()
{
int vect2[51];
int i,j,acum,k;

/* variable y arreglo global que se inicializa


a 0's */
/* prototipo de funcin */

/* arreglo local no se inicializa a 0's*/

for(i=0;i<=50;i++)
vect2[i] = 0;

/* inicializacin a ceros del arreglo vect2 */

lectura();

/* se invoca rutina que lee datos de entrada */

/* RUTINA DE ORDENAMIENTO */
acum = 0;
vect2[1] = vect1[1];
for(j=2;j<=nele;j++)
{
for(i=j-1;i>=1;i--)
if (vect1[j] < vect2[i]) acum += 1;
if (acum != 0)
for(i=j-1;i>=j-acum;i--)
vect2[i+1] = vect2[i];
vect2[j-acum] = vect1[j];
acum = 0;
}

/* IMPRESIN DE VECTORES */

Programacin en Lenguaje C

58

Luis Hernndez Lara

Centro de Investigacin en Computacin

clrscr();
gotoxy(23,2);
printf("*** ORDENAMIENTO POR INSERCIN ***");
gotoxy(12,4);
printf("VISUALIZACION DE ARREGLOS UTILIZADOS Y RESULTADOS"
"OBTENIDOS");
gotoxy(1,7);
printf("ELEMENTOS DEL VECTOR DE ENTRADA");
printf("\n");
for(i=1;i<=nele;i++) printf("%5d ",vect1[i]);
printf("\n");
gotoxy(1,11);
printf("ELEMENTOS ORDENADOS");
printf("\n");
for (j=1;j<=nele;j++) printf("%5d ", vect2[j]);
getch();
return 0;
} /* fin de main */

/* Lectura de datos, se
lectura()
{
extern int nele;
/*
extern int vect1[];/*
char s[11];
/*
int i,j;

guardan en arreglo vect1 */


Estas dos declaraciones son redundantes ya */
que las variables son globales puede */
quitar las dos lineas extern y probar */

while(nele <= 0)
{
clrscr();
gotoxy(26,2);
printf("ORDENAMIENTO POR INSERCIN");
gotoxy(20,5);
printf("DAME EL NMERO DE ELEMENTOS A ORDENAR = ");
gets(s);
nele = atoi(s);
if(nele > 50)
{
for(j=1;j<20;j++)
{
gotoxy(20,10);
printf("*** ERROR *** MXIMO NMERO DE ELEMENTOS 50");
}
nele = 0;
}
}

for(i=1;i<=nele;i++)

Programacin en Lenguaje C

59

Luis Hernndez Lara

Centro de Investigacin en Computacin

{
gotoxy(27,8);
printf("DAME EL ELEMENTO [%d] = ",i);
gets(s);
vect1[i] = atoi(s);
gotoxy(27,8);
printf("

");

}
return 0;
}

Ejercicio 7.2.

Programacin en Lenguaje C

60

Luis Hernndez Lara

Centro de Investigacin en Computacin

Generar e imprimir un arreglo bidimensional como se muestra en la siguiente figura:


num [t] [i] donde "t" son filas e "i" columnas

1
5
9
/*
Archivo:
Objetivo:
Funcin:

2 3 4
6 7 8
10 11 12

ejer72.c
Mostrar el uso de un arreglo bidimensional
Crear un arreglo bidimensional, llenarlo con una
secuencia de nmeros e imprimirlo

*/
#include <stdio.h>
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;
/* ahora imprimimos el arreglo */
for(t=0; t<3; ++t)
{
for(i=0; i<4; ++i)
printf("%3d ",num[t][i]);
printf("\n");
}
return 0;
}

Ejercicio 7.3.

Programacin en Lenguaje C

61

Luis Hernndez Lara

Centro de Investigacin en Computacin

/*
Archivo: ejer73.c
Objetivo: Mostrar el uso de algunas funciones de la biblioteca
estndar para manejo de cadenas
Funcin: Mostrar el uso de las funciones gets, strcpy, strcat,
strcmp, strlen.
*/
#include <stdio.h>
#include <string.h>
lee();
copia();
concatena();
compara();
longitud();
main()
{
printf("\n\nLee una cadena desde el teclado: ");
lee();
printf("\n\nCopia cadena");
copia();
printf("\n\nConcatena cadena");
concatena();
printf("\n\nCompara cadena");
compara();
printf("\n\Devuelve longitud de cadena");
longitud();
getch();
return 0;
}
/* Usa la funcin gets: lee una cadena del teclado, automticamente
le agrega el fin de cadena */
lee()
{
char cadena[80];
gets(cadena);
printf("\n%s",cadena);
return 0;
}
/* Usa la funcin strcpy: copia la cadena s2 en s1, strcpy(s1,s2) */
copia()
{
char cadena[80];
strcpy(cadena, "hola");
printf("\n%s",cadena);
return 0;
}

/* Usa la funcin strcat: concatena la cadena s2 a s1, strcat(s1,s2).

Programacin en Lenguaje C

62

Luis Hernndez Lara

Centro de Investigacin en Computacin

Slo deja un fin de cadena activo, el de la cadena resultante */


concatena()
{
char primero[20], segundo[20];
strcpy(primero, "hola");
strcpy(segundo, " amigos");
strcat(primero,segundo);
printf("\n%s",primero);
return 0;
}
/* Usa la funcin compara: compara dos cadenas strcmp(s1,s2)
- Si s1 y s2 son iguales devuelve 0 (falso)
- Si s1 es lexicogrficamente mayor que s2, devuelve no. positivo
- Si s1 es menor que s2, devuelve un nmero negativo
*/
compara()
{
char cadena[80];
printf("\nIntroducir clave de acceso: ");
gets(cadena);
if(strcmp(cadena,"ER65"))
{
printf("\nPassword invlido");
return 0;
}
printf("\nPassword correcto");
return 1; /* devuelve 1 a la funcin llamadora */
}
/* Usa la funcin strlen: devuelve la longitud de una cadena, no
cuenta el fin de cadena */
longitud()
{
char cadena[80];
printf("\nIntroducir una cadena: ");
gets(cadena);
printf("\nSu longitud es de %d caracteres\n",strlen(cadena));
return 0;
}

Ejercicio 7.4.

Programacin en Lenguaje C

63

Luis Hernndez Lara

Centro de Investigacin en Computacin

/*
Archivo: ejer74.c
Objetivo: Mostrar el uso de arreglos de cadenas.
Funcin: Lee cadenas de entrada y despliega la cadena ms
larga introducida.
*/
#include <stdio.h>
#include <string.h>
main()
{
int i, j, mayor, pos;
char cadenas[10][80];
for(i=0; i<10; i++)
{
printf("\nCadena %d : ",i+1);
gets(cadenas[i]);
if(cadenas[i][0]=='\0') break; /* sale con lnea en blanco */
}
mayor = 0;
/* longitud de la cadena */
pos = 0;
/* posicin de la cadena en el arreglo */
for(i=0; i<10; i++)
{
j = strlen(cadenas[i]);
if(j>mayor)
{
mayor = j;
pos = i;
}
}
printf("\nLa cadena ms larga es: %s", cadenas[pos]);
getch();
return 0;
} /* fin de main */

8. FUNCIONES.

Programacin en Lenguaje C

64

Luis Hernndez Lara

Centro de Investigacin en Computacin

Las funciones son una forma de estructurar un programa en bloques organizados de


cdigo. Esto permite al programador desarrollar programas bien estructurados y de fcil
depuracin.

8.1 Reglas de las funciones.


Cada funcin tiene la forma:
nombre (declaracin de argumentos, si existen)
{
declaraciones y oraciones simples o compuestas, si existen
}
Las funciones pueden contener cero o ms lneas de cdigo.
/* Una funcin mnima */
nada()

{}

Un programa en "C" es un conjunto de definiciones de funciones. La comunicacin


entre las funciones se efecta a travs de argumentos y valores devueltos por la
funcin. Tambin se puede realizar mediante variables externas.
Las funciones aparecen en cualquier orden en el archivo fuente, y el programa fuente
puede estar dividido en varios archivos. Sin embargo las funciones son indivisibles.
Las funciones pueden regresar solamente un valor. Esto puede ser una limitante, pero
C permite pasar apuntadores a funciones lo cual hace ms flexible su uso.
Por valor de omisin (default) las funciones regresan enteros. Sin embargo, otros tipos
de datos pueden regresarse, por lo que deben especificarse cuando se define la
funcin.
En el ANSI C estndar, todas las funciones deben ser definidas usando prototipos de
funcin. Estos le dicen al compilador cules tipos de datos pueden ser pasados a la
funcin y que tipos de datos sern regresados por la funcin.

8.2 Argumentos de funciones (llamada por valor).

Programacin en Lenguaje C

65

Luis Hernndez Lara

Centro de Investigacin en Computacin

Los parmetros son pasados a las funciones por valor. Por lo tanto, la funcin recibe
slo una copia del valor de la variable. La variable original no puede ser modificada por
la funcin a menos que se use un apuntador.
El tipo de las variables debe ser definido despus de la definicin del nombre de la
funcin y antes de la primer llave { del bloque. Adicionalmente los nombres de las
variables debern identificarse dentro de los parntesis () de la funcin en el orden en
que los valores son pasados a la funcin (todos los parmetros son pasados a la
funcin de izquierda a derecha).
Recuerde que las variables de la funcin son automticas, a menos que se especfique
de otra manera y sus nombres son locales a la funcin. Esto significa que los nombres
de variables son nicos a la funcin en la cual fueron definidos. Ejemplo:
main()
{
char newline='\n';
int nuevalinea(), cuenta();
int i=10, h;
/* pasa una copia de newline a nuevalinea */
printf("Hola"); nuevalinea(newline);
/* pasa una copia de i a cuenta, regresa un valor desde cuenta() en h
*/
h=cuenta(i);
/* h es 100, i es an 10 */
printf("h=%d, i=%d",h,i);
}
int nuevalinea( i)
char i;
{
printf("%c",i);
}

/* primera forma de declarar parmetros */

int cuenta(j)
int j;
{
while(j<100) j+=10;
return(j);
}

El programa imprime:

Programacin en Lenguaje C

66

Luis Hernndez Lara

Centro de Investigacin en Computacin

Hola
h=100, i=10

Ver seccin 8.9, ejercicio 8.1.

En "ANSI C", los prototipos de funcin se definen para que el compilador verifique que
los tipos de datos que estn siendo pasados a la funcin son del mismo tipo que los
que recibe la funcin.
Los prototipos son usados de la siguiente manera:
Ejemplo:
void nuevalinea(char);
double cuadrado(int);

/* define prototipo de funcin */


/* define prototipo de funcin */

void main()
{
char newline='\n';
int x;
double y;
x = 4;
y = cuadrado(x);
printf("x=%d, y=%f",x,y); nuevalinea(newline);
}

void nuevalinea(char i)
{
printf("%c",i);
}
double cuadrado(int j)
{
double b;
b = j * j;
return (b);
}

/* segunda forma de declarar parmetros */


/* define la funcin, que no regresa valor */

/* calcula el cuadrado de x y regresa el valor */

En adelante usaremos sta forma de declaracin.

Programacin en Lenguaje C

67

Luis Hernndez Lara

Centro de Investigacin en Computacin

Los nuevos compiladores de C aceptan ambas versiones de declaracin de


parmetros (de acuerdo a los dos ejemplos anteriores). Aunque depende la versin que
usted use podra encontrar algunos errores de sintaxis.
Note que void, se requiere para indicar al compilador que la funcin no regresar valor
de ningn tipo.

8.3 Parmetros mltiples.


Mltiples variables pueden ser pasadas a una funcin especificando el tipo y nombre de
cada variable. Cuando ms de una variable es pasada a una funcin, los parmetros
van separados por comas. Por ejemplo:

numeros(int,int,int,int,int,int,int,int,int,int); /* prototipo de funcin */


void main()
{
int codigo, i=10, j=20, k=30, l=40;
codigo=numeros(i,j,k,l,50,60,70,80,90,100);
if( codigo < 0 )
printf("no coinciden\n");
}
numeros(int a, int b, int c, int d, int e, int f, int g, int h, int i, int k)
{
if(a==b && c==d && e==f && g==h && i==k){
printf("los argumentos coinciden en pares\n");
return(0);
}
else
return(-1);
}
El programa imprime:
no coinciden

8.4 La oracin return.

Programacin en Lenguaje C

68

Luis Hernndez Lara

Centro de Investigacin en Computacin

La oracin return permite al programador regresar un valor. La oracin return puede


usarse para pasar el resultado de una expresin o para regresar un valor desde la
funcin.
La oracin return no es requerida para regresar desde una funcin. Por valor de
omisin la ejecucin de la funcin finaliza cuando la llave "}" final es alcanzada y se
regresa el control a la funcin que la llam.
A continuacin, veamos un ejemplo:
void main()
{
int i=10,h=100;
int result;
result=prueba(i,h);
printf("el resultado es %d\n",result);
} /* fin de main */
prueba(int a, int b)
{
if(a==b)
return(a*b);
else
return(0);
}
El programa Imprime:
el resultado es 0

Como se ha visto las funciones pueden regresar valores en otros tipos que no sea el
tipo entero, indicando el tipo a ser regresado en la declaracin de la funcin.
Ejemplo en "ANSI C":
float area_c(float);

/* Prototipo de la funcin el cual le dice al


compilador el tipo a ser pasado y el tipo
a ser regresado por la funcin area_c() */

void main()

Programacin en Lenguaje C

69

Luis Hernndez Lara

Centro de Investigacin en Computacin

{
float area, radio=99.99;
area=area_c(radio);
printf("El rea del crculo es %.2f \n", area);
} /* fin de main */
float area_c(float val)
{
val = 3.1414 * val * val;
return(val);
}

8.5 Pasando y regresando expresiones.


Las expresiones pueden ser usadas para pasar un parmetro a una funcin y regresar
un valor simple desde una funcin. La expresin debe ser resuelta antes de que el valor
resultante sea pasado a la funcin y utilizado localmente dentro de la funcin.
A continuacin se muestra como se regresa el valor resultante de una expresin:
void main()
{
int val;
val=test(10*100/20+3);
printf("el valor de retorno es %d\n",val);
} /* fin de main */
test(int i)
{
printf("el valor es %d\n",i);
return(100/20*20+1);
}

8.6 Paso de arreglos a funciones.


Cuando se pasa un arreglo como argumento de una funcin, se pasa slo la direccin
del arreglo y no una copia del arreglo entero. Cuando se llama a una funcin con un
nombre de arreglo, se pasa un apuntador al primer elemento en el arreglo de la
funcin.

Programacin en Lenguaje C

70

Luis Hernndez Lara

Centro de Investigacin en Computacin

En "C" un nombre de arreglo sin ningn ndice, es un apuntador al primer elemento del
arreglo. Esto significa que la declaracin de un parmetro debe ser de un tipo
apuntador compatible. Hay tres formas de declarar un parmetro que se recibir como
un apuntador de arreglo.
Si tenemos la siguiente funcin main() comn a los tres casos, entonces:
/* Guarda e imprime 100 nmeros nones */
main()
{
int i, j, arreglo[100];
for(i=0,j=1 ; i<100; i++, j=j+2)
arreglo[i] = j;
imprime(arreglo);
}

a) La primer forma es declarar un parmetro como un arreglo de enteros:


imprime(int recibe[100])
{
int i;
for(i=0; i<100; i++)
printf("%d ", recibe[i]);
}

b) La segunda forma es declarar un arreglo de enteros de tamao desconocido:


imprime(int recibe[])
{
int i;
for(i=0; i<100; i++)
printf("%d ", recibe[i]);
}

c) La tercera forma es declarar un apuntador (forma ms comn en "C"):

Programacin en Lenguaje C

71

Luis Hernndez Lara

Centro de Investigacin en Computacin

imprime(int *recibe)
{
int i;
for(i=0; i<100; i++)
printf("%d ", recibe[i]);
}

En la primer forma, el compilador convertir automticamente "recibe" a un apuntador


entero porqu ningn parmetro puede recibir un arreglo entero.
En la segunda forma el tamao del arreglo es irrelevante para el parmetro, pero no
para el programa, es obligacin del programador comprobar los lmites de los arreglos
en los que trabaja, ya que "C" no proporciona comprobacin de lmites de arreglos
(contornos).
En la tercera forma, se declara un apuntador ya que como se haba mencionado
anteriormente, un nombre de arreglo sin ndices es la direccin al primer elemento del
arreglo, por lo que s es una direccin, la funcin receptora lo recibir en un apuntador.

Ver seccin 8.9, ejercicios 8.2 y 8.3.

8.7 Llamada por referencia.


Se puede hacer una llamada por referencia, pasando un apuntador al argumento, en
lugar de pasar el propio argumento. Como lo que se pasa es la direccin del
argumento, el cdigo de la funcin llamada puede cambiar el valor del argumento
exterior de la funcin. Veamos un ejemplo sencillo:
/* Intercambia los valores de dos variables */
void intercambia(int *var1, int *var2);
void main(void)
{
int i, j;
i= 100;
j= 200;
intercambia(&i, &j);
printf("\nAhora los valores son i= %d, j= %d ",i,j);
}
/* Funcin que intercambia los valores de las variables apuntadas
por var1 y var2 */

Programacin en Lenguaje C

72

Luis Hernndez Lara

Centro de Investigacin en Computacin

void intercambia(int *var1, *var2)


{
int tempo;
tempo = *var1; /* rescata el valor al que apunta la direccin */
*var1 = *var2; /* coloca var2 en var1 */
*var2 = tempo; /* coloca var1 en var2 */
}

8.8 Recursividad.
En "C" las funciones pueden llamarse a s mismas. Si una expresin en el cuerpo de
una funcin llama a la propia funcin, se dice que sta es recursiva. La recursividad es
el proceso de definir algo en trminos de s mismo y a veces se le denomina "definicin
circular".
Para ilustrar lo anterior, calculemos el factorial de un nmero entero.
El factorial de un nmero entero se expresa por:
0! = 1
N! = N x (N-1)! si N>0

En notacin de programacin tendramos:


FACTORIAL(0) = 1;
FACTORIAL(N) = N * FACTORIAL(N-1) si N>0
Transformemos lo anterior a un programa en "C":

Programacin en Lenguaje C

73

Luis Hernndez Lara

Centro de Investigacin en Computacin

int factorial(int N);


void main()
{
int fac, n;
char resp;
do{
printf("\nTeclee un nmero entero positivo: ");
scanf("%d",&n);
fac = factorial(n);
printf("\n\nEl factorial de %d es %d",n,fac);
printf("\n(S)i para continuar _");
resp = getch();
}while(resp == 'S');
}
int factorial(int N)
{
if ( N == 0) return 1;
else
return (N*factorial(N-1));
}

Ver seccin 8.9, ejercicio 8.4 y 8.5.

Programacin en Lenguaje C

74

Luis Hernndez Lara

Centro de Investigacin en Computacin

8.9 Ejercicios del captulo.


Ejercicio 8.1.
/*
Archivo:
Objetivo:
Funcin:

ejer81.c
Mostrar el paso de parmetros de una funcin por valor
A travs de una funcin elevar un nmero positivo a
una potencia positiva

*/
#include <stdio.h>
#include <conio.h>
int potencia(int , int );
void main()
{
int num, pot;
printf("\nTeclea el nmero a elevar _ ");
scanf("%d", &num);
printf("\n"Teclea la potencia _ ");
scanf("%d", &pot);
printf("\n %d elevado a la potencia %d es %d\n",
num, pot, potencia(num,pot));
getch();
} /* fin de funcin main */
/* Funcin que eleva un nmero entero a una potencia entera */
int potencia(int x, int y)
{
int i, p;
p=1;
for(i=1; i<= y; ++i)
p = p * x;
return p;
} /* fin de funcin potencia */

Programacin en Lenguaje C

75

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 8.2.
/*
Archivo:
Objetivo:
Funcin:

ejer82.c
Mostrar el paso de arreglos como argumento de funcin
Convertir a maysculas una cadena, pasando el arreglo
como un argumento de funcin que lo recibe como un
apuntador

*/
#include <stdio.h>
#include <conio.h>
void mayusculas(char *);
void main()
{
char cadena[80];
gets(cadena);
mayusculas(cadena);
getch();
} /* fin de funcin main */
/*convierte a maysculas e imprime carcter por carcter*/
void mayusculas(char *letras)
{
int i;
for(i=0; letras[i]; ++i)
{
letras[i] = toupper(letras[i]);
printf("%c", letras[i]);
}
} /* fin de funcin mayusculas */

Programacin en Lenguaje C

76

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 8.3.
/*
Archivo:
Objetivo:
Funcin:

ejer83.c
Mostrar el paso de arreglos a una funcin
Multiplicar dos matrices de orden mxp y oxn,
donde n = o

*/
#include <stdio.h>
#include <conio.h>
/* prototipo de funcin */
void imprime(int fil, int col, int matriz[11][11]);
/* funcin principal */
void main()
{
int a[11][11], b[11][11], c[11][11];
int m, n, o, p;
int i, j, k, s;
int decide;
/* validacin de la entrada de datos */
do{
decide = 0;
printf("\nTeclee no. filas
de matriz A__");
scanf("%d",&m);
printf("\nTeclee no. columnas de matriz A__");
scanf("%d",&p);
printf("\nTeclee no. filas
de matriz B__");
scanf("%d",&o);
printf("\nTeclee no. columnas de matriz B__");
scanf("%d",&n);
if(m > 10 || n > 10 || o > 10 || p > 10) decide = 1;
if(m < 1 || n < 1 || o < 1 || p < 1) decide = 1;
if(p != o) decide = 1;
}while(decide == 1);
/* entrada de datos por matriz, por fila */
printf("\nTeclee la matriz A ");
for(i=1; i<=m; i++)
for(k=1; k<=p; k++)
{
printf("\nElemento(%d,%d) = ",i,k);
scanf("%d",&a[i][k]);
}
printf("\nTeclee la matriz B ");
for(k=1; k<=o; k++)
for(j=1; j<=n; j++)
{
printf("\nElemento(%d,%d) = ",k,j);
scanf("%d",&b[k][j]);
}

Programacin en Lenguaje C

77

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Clculo de la matriz producto c = a x b


de orden m x n
*/
for(i=1; i<=m; i++)
for(j=1; j<=n; j++)
{
s = 0;
for(k=1; k<=p; k++)
s = s + a[i][k] * b[k][j];
c[i][j] = s;
}
/* Mostrar resultados finales */
printf("\nMatriz A\n");
imprime(m,p,a);
printf("\nMatriz B\n");
imprime(p,n,b);
printf("\nMatriz C\n");
imprime(m,n,c);
getch();
} /* fin de main() */
/* Funcin que imprime matrices, recibe como argumentos
no. filas, no. de columnas y matriz (arreglo) */
void imprime(int fil, int col, int matriz[11][11])
{
int x, y;
for(x=1; x<=fil; x++)
{
for(y=1; y<=col; y++) printf("
%4d", matriz[x][y]);
printf("\n");
}
} /* fin de imprime() */

Programacin en Lenguaje C

78

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 8.4.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer84.c
Mostrar el manejo de la Recursividad
Calcular la serie de Fibonacci para un nmero n

#include <stdio.h>
#include <conio.h>
int fibonacci(int N);
void main()
{
int fib, n, i;
char resp;
printf("\nSerie de Fibonacci\n");
do{
printf("\nTeclee el nmero de elementos de la serie: ");
scanf("%d",&n);
printf("\n\n");
for(i=1;i<=n;i++)
{
fib = fibonacci(i);
printf("%d ",fib);
}
printf("\n\n(S)i para continuar _");
resp = getch();
}while(resp == 'S');
}
/* Funcin que calcula el nmero n-simo de la serie de fibonacci */
int fibonacci(int N)
{
if (N == 1) return 0;
else
if(N == 2) return 1;
else
return(fibonacci(N-1)+fibonacci(N-2));
}

Programacin en Lenguaje C

79

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 8.5.
/*
Archivo:
Objetivo:
Funcin:

ejer85.c
Mostrar el manejo de la Recursividad
Descompone un nmero entero positivo en sus factores
primos

*/
#include <stdio.h>
int primo(int, int);
void main()
{
int i,num,y;
printf("Introduzca un nmero: ");
scanf("%d",&num); printf("\n%d=",num);
if(num==1)
/* si el nmero fue 1 */
printf("1*%d\n",num);
else
if(num)
{
i=primo(num,2);
if( i==num )
printf("1*%d\n",num); /* el nmero no tuvo factores*/
else
printf("%d*1\n",i);
/* el ltimo factor */
}
else
printf("Usted introdujo cero\n");
getch();
}
/* Funcin recursiva que calcula el nmero primo */
int primo(int y, int i)
{
if(i>=y)
return(i);
else
if(!(y%i))
{
printf("%d*",i);
return(primo(y/i,i));
}
else
return(primo(y,i+1));
}

Programacin en Lenguaje C

80

Luis Hernndez Lara

Centro de Investigacin en Computacin

9. APUNTADORES.
9.1 Definicin.
Un apuntador es una variable que contiene la direccin de otra variable. Esto permite
que la variable apuntada pueda ser accesada a travs de la variable apuntador, es
decir "en forma indirecta".
Los siguientes pasos son requeridos cuando se usa un apuntador:

1) Declarar: un apuntador a una variable entera


int *ip;
int x;
2) Inicializar: ip = la direccin de x, ip es un apuntador
ip= &x;
x= 10;
La DIRECCIN en donde reside la variable x en memoria (indicada por el uso del
operador unario & antes del nombre de la variable), es almacenada en la variable ip
de tipo apuntador a carcter.
3) Usar: imprimir contenido de x
printf("%d\n", *ip);
Cuando el operador * es colocado en frente del nombre de la variable apuntador, el
contenido de la variable (de quin la direccin reside en la variable apuntador) puede
ser accesado.

En "ANSI C" existe un apuntador a void el cual permite al programa inicializar un


apuntador simple para que apunte a cualquier tipo de variable.
Cuando un apuntador se define, este apunta a un tipo de variable. Sin embargo, un
apuntador a void no se limita por esta regla.
void *ptr;
int *xyz;

/* puede contener la direccin de cualquier tipo de variable */


/* slo puede contener la direccin de una variable entera */

A continuacin veamos, dos ejemplos:

Programacin en Lenguaje C

81

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejemplo(1):
main()
{
int valor1, valor2;
int *dir_valor;
valor1 = 50;
dir_valor = &valor1;
valor2 = *dir_valor;
printf("%d", valor2);

/* toma la direccin de la variable valor1 */


/* el valor contenido en la direccin apuntada
por dir_valor es colocado en valor2 */
/* imprime el valor 50 */

Ejemplo(2):
main()
{
int x;
int *ap1, *ap2;
ap1 = &x;
ap2 = ap1;
printf("%p", ap2);

/* imprime el valor hexadecimal de la direccin


de x (no el valor de la variable x) */

9.2 Apuntadores en expresiones.


Los apuntadores pueden ser colocados dentro de expresiones para representar el valor
al cual indirectamente se hace referencia va el apuntador.
Colocando el apuntador del lado izquierdo del operador de asignacin, el valor
apuntado por el apuntador ser modificado. Esto modifica la variable original la cual
est siendo referenciada por la variable apuntador.

Programacin en Lenguaje C

82

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejemplo:
void main()
{
int *loc;
int x=20, y=30, z;
loc=&x;
z = *loc + x + y;
*loc = 100;
printf("x is %d\n",x);
}

/* 20+20+30; z es 70 */
/* esto modifica la variable 'x' */
/* imprime: x es 100 */

9.3 Aritmtica y comparacin de apuntadores.


En "C" se pueden usar slo dos operaciones aritmticas sobre apuntadores: + y -.
Sea ap un apuntador a un entero con el valor actual de 1000. Despus de la expresin
ap++; el contenido de ap ser de 1002 y no de 1001!. Cada vez que la computadora
incrementa ap, ste apuntar al siguiente entero en memoria. Lo mismo sucede para
los decrementos, por ejemplo, ap-- causar que ap tenga el valor de 998, si
previamente tena 1000.
En el caso de apuntadores a caracteres, la aritmtica de apuntadores frecuentemente
trabajar como aritmtica normal (ya que un carcter es de un byte de longitud). Sin
embargo el resto de los apuntadores se incrementarn o decrementarn de acuerdo a
la longitud del tipo de datos a los que apunten.
Tambin es posible comparar dos apuntadores en una expresin relacional. Por
ejemplo, dados los apuntadores ap1 y ap2, son perfectamente vlidas las siguientes
oraciones:
if(ap1 < ap2) printf("la direccin a la que apunta ap1 es < que la apuntada por ap2");

Ver seccin 9.10, ejercicio 9.1.

Programacin en Lenguaje C

83

Luis Hernndez Lara

Centro de Investigacin en Computacin

9.4 Paso de apuntadores a funciones.


La direccin de una variable puede ser pasada a una funcin lo cual permitir que la
funcin pueda modificar su contenido usando un apuntador (debemos usar un *
enfrente del nombre de la variable apuntador). Por ejemplo:
void main()
{
int x=100;
/* x es igual a 100 */
/* se pasa la direccin de x a modifica() */
/* x es ahora igual a 200 */
printf("contenido despus: x es %d\n", x);
} /* fin de main */
modifica(&x);

void modifica(int *a) /* recibe la direccin de x en un apuntador */


{
/* a es igual a la direccin de x , *a es igual al contenido de x */
printf("contenido antes: x es %d\n", *a);
*a += 100;
}
El programa imprime:
contenido antes: x es 100
contenido despus: x es 200

9.5 Apuntadores y arreglos.


Es importante establecer que un apuntador y un arreglo son dos formas para
referenciar una pieza de datos en forma indirecta. La diferencia est en que un arreglo
aloja espacio para contener datos y un apuntador slo aloja espacio para contener una
direccin. En esencia el nombre de un arreglo sin corchetes [ ], hace referencia a la
direccin del primer elemento del arreglo.
Si tenemos que:
int cadena[5], dato, *p;
p = &dato;
-

p contiene la direccin de dato


*p hace referencia al contenido de dato

cadena[0] hace referencia al contenido del primer entero

Programacin en Lenguaje C

84

Luis Hernndez Lara

Centro de Investigacin en Computacin

*(cadena+0) hace referencia al contenido del primer entero y es lo mismo que


cadena[0].

A continuacin veamos la relacin que existe entre apuntadores y arreglos, mediante la


conversin de una cadena a minsculas y su impresin.
/* Versin con arreglo */
void main()
{
char cadena[80];
int i;
printf("Introduce una cadena en maysculas: ");
gets(cadena);
printf("\nLa cadena en minsculas es: ");
for(i=0; cadena[i]; i++)
printf("%c", tolower(cadena[i]));
}

/* Versin con apuntador */


void main()
{
char cadena[80], *p;
printf("Introduce una cadena en maysculas: ");
gets(cadena);
printf("\nLa cadena en minsculas es: ");
p = cadena;
/* se asigna a p la direccin del arreglo cadena */
while(*p)
/* mientras el contenido a donde apunte p no sea '\0' */
printf("%c", tolower(*p++));
}
Qu pasara con un while cmo el que se muestra a continuacin?
while(*p)
{
printf("%c", tolower(++(*p)));
p++;
}
Analice el caso y de una respuesta. Use la cadena "cic-ipn" como ejemplo.

Programacin en Lenguaje C

85

Luis Hernndez Lara

Centro de Investigacin en Computacin

9.6 Indexado de apuntadores.


En "C" se puede indexar un apuntador como si fuera un arreglo. Por ejemplo, el
siguiente fragmento de cdigo es vlido e imprime las letras A, B, C, D, E.
main()
{
char arreglo[5] = { 'A', 'B', 'C', 'D', 'E' };
char *ap;
int i;
ap = arreglo;
for(i=0; i<5; i++)
printf("%c", ap[i]);
}

Ver seccin 9.10, ejercicio 9.2

9.7 Apuntadores a caracteres y funciones.


9.7.1 Apuntadores a caracteres.
A una variable declarada como apuntador a caracteres, se le puede asignar una
cadena de caracteres. Lo cual significa que la variable apuntador, contendr un
apuntador al arreglo de caracteres. Por ejemplo:
Si la variable "mensaje" se declara como
char *mensaje;
entonces la proposicin
mensaje = "esta es una cadena";
asigna a "mensaje" un apuntador al arreglo de caracteres. sta no es una copia de una
cadena; y slo se usa en apuntadores.
A continuacin, veamos la diferencia entre dos tipos de definiciones:
char mensaje[] = "esta es una cadena";
/* versin arreglo */
char *ap_mensaje = "esta es una cadena"; /* versin apuntador */
En este caso, el significado sera:

Programacin en Lenguaje C

86

Luis Hernndez Lara

Centro de Investigacin en Computacin

mensaje es un arreglo suficientemente grande para contener la secuencia de


caracteres ms el carcter '\0' que lo finaliza. La variable "mensaje"
siempre se referir a la misma localidad de almacenamiento.
ap_mensaje es un apuntador inicializado para apuntar a una cadena constante; el
apuntador puede modificarse para que apunte a otro lado, pero el
resultado es indefinido si se trata de modificar el contenido de la
cadena.

ap_mensaje:

esta es una cadena\0

mensaje:

esta es una cadena\0

Un ejemplo sencillo, se muestra a continuacin:


char *ap = "Apuntador a carcter";
void main(void)
{
int i;
/* imprimiremos la cadena hacia delante y hacia atrs */
printf(ap); /* imprime la cadena apuntada por ap */
for(i=strlen(ap)-1; i>-1; i++)
printf("%c", ap[i]);
}

9.7.2 Apuntadores a funciones.


Una caracterstica muy til en "C" es el apuntador a funcin. Aunque una funcin no es
una variable, tiene una posicin fsica en memoria, la cual puede asignarse a un
apuntador. Esto significa que la direccin de la funcin es el punto de entrada de la
funcin. Por ello se puede usar un apuntador a una funcin para invocar a la funcin.
La direccin de la funcin se obtiene utilizando el nombre de la funcin sin parntesis ni
argumentos.

Programacin en Lenguaje C

87

Luis Hernndez Lara

Centro de Investigacin en Computacin

Por ejemplo, para obtener la direccin de la funcin que compara cadenas, tendramos:
int (*ap) (const char *, const char *);
ap = strcmp;
donde:
ap - es un apuntador a una funcin que devuelve entero
(const char *, const char *) - es el prototipo de paso de parmetros de la funcin
strcmp, el cual pede ser el mismo para diferentes funciones, esto depender de su
construccin.
strcmp - funcin que compara cadenas de caracteres.

Ver seccin 9.10, ejercicios 9.3 y 9.4.

9.8 Arreglos de apuntadores y apuntadores a apuntadores.


9.8.1 Arreglos de apuntadores.
Los apuntadores pueden estructurarse en arreglos como cualquier otro tipo de datos.
Veamos una secuencia artificial como ejemplo de ello:
1) Declaramos un arreglo de apuntadores a reales (float) de tamao 100:
float *numeros[100];
2) Asignamos la direccin de una variable llamada "dato" al cuarto elemento 4 del
arreglo de apuntadores:
numeros[3] = &dato;
3) Asignamos el valor de la variable "dato" a la variable "valor":
valor = *numeros[3];
Si se desea pasar un arreglo de apuntadores a una funcin, se puede utilizar el mismo
mtodo utilizado para pasar arreglos, llamando a la funcin con el nombre del arreglo
sin ndices. La funcin que recibe la direccin del arreglo de apuntadores, debe
declarar como parmetro un arreglo de apuntadores al tipo de datos del arreglo.

Programacin en Lenguaje C

88

Luis Hernndez Lara

Centro de Investigacin en Computacin

Esto es:
void imprime(float *numeros[])
{
int i;
for(i=0; i<10; i++) printf("%f", *numeros[i]);
}
Un uso comn de los arreglos de apuntadores, es el de mantener apuntadores a
mensajes de error.
void errores(int num_error)
{
static char *errs[] = {
"Clave de acceso invlida\n",
"Nombre de archivo desconocido\n",
"Sin privilegios de escritura\n",
"No se puede abrir el archivo\n"
};
printf("%s", errs[num_error]);
}

Ver seccin 9.10, ejercicios 9.5 y 9.6.

9.8.2 Apuntadores a apuntadores.


En "C" un apuntador puede apuntar a otro apuntador que apunte a un valor. sta
situacin tambin se denomina indireccin mltiple. Asimismo a la situacin en la que
un apuntador apunta a un valor se le conoce como indireccin simple.
Para declarar una variable que ser un apuntador a apuntador, se hace anteponiendo
dos asteriscos al nombre de la variable. Por ejemplo:

Programacin en Lenguaje C

89

Luis Hernndez Lara

Centro de Investigacin en Computacin

int **valor; /* se declara un apuntador a apuntador a int */


main()
{
int *ap, **app;
valor = 50;
ap = &valor;
/* la direccin de "valor" se pasa a "ap" */
app = &ap;
/* la direccin del apuntador "ap" se pasa a "app" */
printf("%d", **ap); /* imprimir el valor de la variable "valor" */
}
9.8.3 Usando apuntadores como arreglos (asignacin dinmica de arreglos).
En "C" se puede declarar una variable como un apuntador y despus de asignarle una
direccin, se puede usar el apuntador como un arreglo de dimensin "n".
Lo anterior sin duda hace ms flexible el uso de arreglos, quienes en su definicin
formal son obligados a ser constantes en su longitud. Esto se muestra a continuacin,
con dos definiciones tpicas:
float arreglo[200];

#define TAM 400


...
float arreglo[TAM];

La definicin de un arreglo dinmico, se muestra a continuacin:


main()
{
char *ap;
int i;
ap = (char *) malloc(80);
/* gestiona espacio para 80 bytes */
if(!ap)
printf("No se pudo gestionar la memoria\n");
else
{
gets(ap);
for(i=strlen(ap)-1; i>=0; i--) /* imprime la cadena al revs */
putchar(ap[i]);
free(ap);
/* libera la memoria gestionada con malloc */
}
}

La asignacin dinmica de memoria est compuesta por las funciones malloc() y free(),
la primera gestiona la memoria y la segunda la libera.

Programacin en Lenguaje C

90

Luis Hernndez Lara

Centro de Investigacin en Computacin

El prototipo de malloc() es: void *malloc(size_t nmero_de_bytes);


En dicha definicin, nmero de bytes es la cantidad de bytes de memoria que se
quieren gestionar, el tipo size_t est definido en stdlib.h como un entero sin signo.
La funcin malloc() devuelve un apuntador de tipo void, lo que significa que se puede
asignar a cualquier tipo de apuntador.
La funcin free() devuelve al sistema la memoria previamente gestionada y asignada.
El prototipo de free() es: void free(void *p);
Aqu, p es un apuntador a memoria, previamente asignado con malloc().
En el siguiente ejemplo, se gestiona memoria para 100 nmeros reales de precisin
sencilla, y despus se libera la memoria:
float *ap;
ap = (float *) malloc(100*sizeof(float));
free(ap);
Supngase que se requiere crear un arreglo bidimensional con nmero de filas y
columnas proporcionadas por el usuario en tiempo de ejecucin, y utilizarlo para
almacenar nmeros en punto flotante de doble precisin. Esto se puede hacer
utilizando una variable de tipo apuntador a apuntador a double, la variable fungir como
el arreglo deseado.
Para este caso, primero se tiene que gestionar memoria para cada uno de los m
apuntadores (filas). Entonces, en un ciclo, a cada uno de estos apuntadores se le
asigna la direccin inicial de un rea de memoria para n valores (columnas) de tipo
double.
matrix
0

n-1

matrix[i][j]

Programacin en Lenguaje C

91

Luis Hernndez Lara

Centro de Investigacin en Computacin

La figura anterior muestra como el apuntador matrix es usado como un arreglo


bidimensional.

Ver seccin 9.10, ejercicio 9.7.

9.9 Paso de argumentos en la lnea de comandos.


Los argumentos en la lnea de comandos son un mtodo para que un programa en C
reciba parmetros desde el sistema operativo en uso (DOS, UNIX, etc). La sintaxis
desde DOS debe ser:
A>programa.exe parmetro1 parmetro2 parmetro3 ...
Dos parmetros son pasados al programa del usuario. Uno es el parmetro que
cuantifica el nmero de parmetros pasados en la lnea de comandos (argc), el
segundo es un apuntador a un arreglo de apuntadores a carcter (argv), que hace
referencia a los parmetros pasados como cadenas de caracteres.
Cuando no se pasan parmetros el parmetro contador vale 1, lo cual indica que el
nico parmetro pasado es el nombre del programa en ejecucin.
Parmetros
Contador: 1

A> programa.exe parmetro1 parmetro2 parmetro3

Ejemplo:
main(int argc, char *argv[])
A>programa.exe
El sistema operativo asigna lo siguiente:
argc=1, argv[0] apunta a "programa.exe"
Cuando los parmetros son pasados, el sistema operativo asigna lo siguiente:
A>programa.exe parmetro1 parmetro2 parmetro3

Programacin en Lenguaje C

92

Luis Hernndez Lara

Centro de Investigacin en Computacin

argc=4, argv apunta a "programa.exe"


"parmetro1"
"parmetro2"
"parmetro3"

El arreglo se construye como:

programa.exe

argv[0]

parmetro1

argv[1]

parmetro2

argv[2]
argv[3]

parmetro3
argc = 4

La variable argv es definida como un arreglo multidimensional apuntador a apuntador.


Note que el delimitador entre argumentos es el espacio en blanco y que argc y argv
son nombres de variables que pueden ser cambiados a cualquier nombre deseado. Sin
embargo, el tipo de las variables y el orden de paso a main() no puede ser cambiado.
Otra importante caracterstica del paso de parmetros a main() es que cada arreglo
contiene caracteres ASCII con un carcter nulo al final (una cadena).
El siguiente ejemplo imprime cada uno de los parmetros pasados a main() usando
printf():
main(int argc, char *argv[])
{
int i;
/* argv[0] apunta a la cadena programa.exe */
for(i=0; i<argc; i++)
printf("%s\n",argv[i]);
}
Para que el comentario del programa sea vlido, usted debe asignar a su archivo de
programa el nombre programa.

Programacin en Lenguaje C

93

Luis Hernndez Lara

Centro de Investigacin en Computacin

El siguiente ejemplo imprime cada uno de los parmetros pasados a main() usando
printf() para imprimir carcter por carcter de cada parmetro a un tiempo:

main(int argc, char *argv[])


{
int i,j;
/* argv[0] apunta a la cadena programa.exe */
for(i=0; i<argc; i++)
for(j=0; argv[i][j] != '\0'; j++)
printf("%c\n",argv[i][j]);
}

Ambos ejemplos imprimen cada carcter de todos los parmetros pasados, incluyendo
el nombre del programa (argv[0]).

Programacin en Lenguaje C

94

Luis Hernndez Lara

Centro de Investigacin en Computacin

9.10. Ejercicios del captulo.


Ejercicio 9.1.
/*
Archivo:
Objetivo:
Funcin:

ejer91.c
Mostrar la aritmtica y comparacin de apuntadores
Visualiza los contenidos de la memoria a partir de
una direccin especfica, introducida por el usuario

*/
#include <stdio.h>
#include <conio.h>
/* protoipo de la funcin */
dump(unsigned long inicio);
void main()
{
unsigned long principio;
printf("Introducir direccin de comienzo. Se sugiere ");
printf("\nmuy grande, para evitar bloqueo de memoria: ");
scanf("%lu", &principio);
dump(principio);
printf("\nFin");
getch();
} /* fin de main() */
dump(unsigned long inicio)
{
char far *p;
/* un apuntador far permite acceder a reas
de memoria ms all del programa mismo */
int i;
p = (char far*) inicio; /*
for(i=0 ;; i++,p++)
/*
{
if(!(i%16)) printf("\n");
printf("%2X ", *p);
if(_kbhit()) return 0;

convierte la variable a apuntador */


ciclo infinito */
/*
/*
/*
/*

cada 16 bytes salta de lnea */


visualiza en hexadecimal */
para carcter, sustituya por %c */
para cuando se pulsa una tecla */

}
}

Programacin en Lenguaje C

95

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.2.
/*
Archivo:
Objetivo:
Funcin:

ejer92.c
Mostrar la indexacin de apuntadores
Lee nmeros introducidos por teclado y los guarda en una
pila si no son cero (push), cuando se introduce cero
pop) saca un valor de la pila.

*/
#include <stdio.h>
#define MAX 5
int pila[MAX];
int *p1, *tos;

/* toma parte de la memoria para la pila */

int push(int i);


int pop();

/* prototipos de funcion */

void main(void)
{
int value, regreso;
p1 = pila;
tos = p1;
/* tos guarda la parte alta de la pila */
do{
scanf("%d",&value);
if(value != 0)
{
if((regreso = push(value)) == -2)
printf("\nDesborde de pila\n");
}
else
if((regreso = pop()) == -2)
printf("\nPila vacia\n");
else
printf("\nEl valor sacado es: %d\n",regreso);
}while(value != -1);
}
/* funcion push */
int push(int i)
{
p1++;
if(p1==(tos+MAX))
{
p1--;
return -2;
}
*p1=i;
return 1;
}

Programacin en Lenguaje C

96

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* funcion pop */
int pop()
{
if((p1)==tos)
return -2;
p1--;
return *(p1+1);
}

Programacin en Lenguaje C

97

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.3.
/*
Archivo:
Objetivo:
Funcin:

ejer93.c
Mostrar el uso de apuntadores a funcin
Imprime una cadena, invocando la funcin de
biblioteca printf a travs de un apuntador a la funcin

*/
#include <stdio.h>
#include <string.h>
void main(void)
{
char cadena[80];
int (*ap)(const char *, char *);
/* dependiendo del nmero de argumentos a imprimir, se
debern agregar en la definicin anterior, segn el
prototipo de la funcin printf
int printf(const char *format [, argument, ...]); */
ap = printf;

/* La direccin de la funcin printf se coloca en ap */

strcpy(cadena,"Esta es una cadena de prueba");


/* ahora imprimimos la cadena a travs del apuntador */
(*ap)("\n%s\n",cadena);
getch();
}

Programacin en Lenguaje C

98

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.4.
/*
Archivo:
Objetivo:
Funcin:

ejer94.c
Mostrar el uso de apuntadores a funcin
Compara dos cadenas, invocando la funcin de
biblioteca strcmp a travs de un apuntador a la funcin

*/

#include <stdio.h>
#include <string.h>
#include <conio.h>
void main(void)
{
char cadena1[80], cadena2[80];
int (*ap)(const char *,const char *);
ap = strcmp; /* La direccin de la funcin strcmp se coloca en ap */
printf("\nTeclee la primer cadena: ");
gets(cadena1);
printf("\nTeclee la segunda cadena: ");
gets(cadena2);
if(!(*ap)(cadena1,cadena2))
printf("\nLas cadenas son IGUALES");
else
printf("\nLas cadenas son DIFERENTES");
getch();
}

Programacin en Lenguaje C

99

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.5.
/*
Archivo:
Objetivo:
Funcin:

ejer95.c
Mostrar el uso de arreglos de apuntadores
Traduce palabras ingls-espaol. Las palabras en ingls
y su traduccin al espaol se guardan en un arreglo de
apuntadores a carcter.

*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* Se declara e inicializa arreglo de apuntadores a cadenas */
char *trad[][2] = {
"able\0",
"hbil\0",
"beak\0",
"pico\0",
"cake\0",
"pastel\0",
"devirly\0", "diablura\0",
"enjoy\0",
"disfrutar\0",
"\0","\0", /* a propsito para terminar el arreglo */
};
int busca_palabra(char *s);

/* prototipo de funcin */

void main(void)
{
char palabra_ing[20];
int i, longi;
printf("\nDiccionario ingls-espaol\n");
printf("\nTeclee la palabra a traducir: ");
gets(palabra_ing);
longi = strlen(palabra_ing);
for(i=0;i<=longi-1;i++)
palabra_ing[i] = tolower(palabra_ing[i]);
i = busca_palabra(palabra_ing);
if(i != -1)
printf("\nSu traduccin es: %s", trad[i][1]);
else
printf("\nPalabra no encontrada");
getch();
}
/* Funcin busca_palabra, que busca en el arreglo si existe la
palabra cargada en el arreglo de equivalencias */
int busca_palabra(char *s)
{
int pos;
for(pos=0; *trad[pos][0]; pos++)
if(!strcmp(trad[pos][0],s))
return pos;
return -1;
}

Programacin en Lenguaje C

100

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.6.
/*
Archivo:
Objetivo:
Funcin:

ejer96.c
Mostrar el uso de apuntadores a funcin y arreglos de
apuntadores
Ejecuta funciones matemticas a travs de un apuntador a
funcin. Las direcciones de comienzo de las funciones
estn almacenadas en un arreglo de apuntadores.

*/
#include
#include
#include
#include

<stdio.h>
<math.h>
<string.h>
<conio.h>

/* prototipos de funciones a utilizar */


double funcion_mat(double dato, double (*apunta) (double));
void menu(int *opcion);
/* declaracin del arreglo de apuntadores a funcin */
double (*funciones[]) (double) = {sin,cos,tan};
void main(void)
{
double param, resultado;
double (*funcion)(double); /* apuntador a funcin double */
int opcion;
do{
menu(&opcion);
if(opcion != 4)
{
funcion = funciones[opcion-1];
printf("\nTeclee el valor en grados _ ");
scanf("%lf",&param);
resultado = funcion_mat(param,funcion);
printf("\nEl resultado es: %lf",resultado);
}
}while(opcion != 4);
}
/* Ejecuta la funcin matemtica */
double funcion_mat(double dato, double(*apunta) (double))
{
return ((*apunta) ((dato*2.0*3.141592)/360.0));
}

Programacin en Lenguaje C

101

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Men de opciones */
void menu(int *opcion)
{
int op = 0;
while(op<1 || op > 4)
{
printf("\nCalcula funciones matemticas\n");
printf("(1) Funcin seno\n");
printf("(2) Funcin coseno\n");
printf("(3) Funcin tangente\n");
printf("\n(4) Fin de programa\n");
printf("\n\nElija una opcin _ ");
scanf("%d",&op);
*opcion = op;
}
}

Programacin en Lenguaje C

102

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 9.7.
/*
Archivo:
Objetivo:

Funcin:

ejer97.c
Mostrar el uso de apuntadores a apuntadores con gestin
dinmica de memoria.
Apuntadores a apuntadores, usados como arreglos
bidimensionales
Genera un arreglo de dos dimensiones a travs del manejo
de un apuntador a apuntador como un arreglo de
apuntadores

*/
#include <stdio.h>
#include <stdlib.h>
/* Funcin que gestiona memoria y devuelve apuntador de tipo void */
void *gestiona_mem(int n)
{
void *p = malloc(n); /* declara apuntador y gestiona memoria */
if(p==NULL) puts("No se gestion memoria"), exit(1);
return p;
}
/* Funcin que llena el arreglo bidimensional, calcula valores */
void llena_matriz(double **matriz, int fil, int col)
{
int i,j;
for(i=0; i<fil; i++)
for(j=0; j<col; j++)
matriz[i][j] = i+0.01*j;
}
/* Funcin main */
void main(void)
{
int i,j,fil,col;
double **matrix;
printf("\nCuntas filas ? ");
scanf("%d",&fil);
printf("\nCuntas columnas ? ");
scanf("%d",&col);
matrix = (double **) gestiona_mem(fil*sizeof(double *));
for(i=0; i<fil; i++)
matrix[i] = (double *) gestiona_mem(col*sizeof(double));
llena_matriz(matrix,fil,col);
printf("\nContenido de la matriz\n");
for(i=0; i<fil; i++)
{
for(j=0; j<col; j++)
printf("%5.2f",matrix[i][j]);
printf("\n");
}
}

Programacin en Lenguaje C

103

Luis Hernndez Lara

Centro de Investigacin en Computacin

10. EL PREPROCESADOR.
10.1 Directivas.
El preprocesador de C permite al programador extender el lenguaje a travs del uso
de sustitucin de macros. La sustitucin de macros utiliza las definiciones establecidas
por el programador cuando el programa es compilado.
En tiempo de compilacin, el preprocesador reemplaza todas las ocurrencias del
nombre definido, identificado por el uso de una directiva del preprocesador, con la
macro definida.
Las directivas al preprocesador se identifican comenzando con el signo #. Cuando el
preprocesador analiza esa lnea, el signo # indicar una directiva:
#define - define una macro o un valor a ser sustituido.
En el siguiente ejemplo, la directiva #define es usada para reemplazar las secuencias
de caracteres que empaten con los valores identificados por la directiva.
Note el uso de las letras maysculas. Aunque no son necesarias, son extremadamente
tiles para identificar una macro o un nombre a sustituir de una variable o nombre de
funcin. Por ejemplo:

#define
NEWLINE '\n'
#define
NULL '\0'
#define
MAX 80
#define
ESC '\033'
void main()
{
char arreglo[MAX];
int i=0;
do{
arreglo[i]=getchar();
if(arreglo[i]==ESC)
printf("El carcter ESC ha sido introducido\n");
}while(arreglo[i] != NEWLINE && i++ < MAX );
arreglo[--i]=NULL;
}

El cdigo anterior se modifica por el preprocesador y se presenta al compilador como:

Programacin en Lenguaje C

104

Luis Hernndez Lara

Centro de Investigacin en Computacin

void main()
{
char arreglo[80];
int
i=0;
do{
arreglo[i]=getchar();
if(arreglo[i]=='\033')
printf("El carcter ESC ha sido introducido\n");
}while(arreglo[i] != '\n' && i++ < 80 );
arreglo[--i]='\0';
}

10.2 Macros.
Las macros se definen para que las variables reales sean colocadas dentro de la macro
en tiempo de compilacin. El siguiente ejemplo define una macro con un parmetro de
prueba (dummy) x el cual es reemplazado con la variable a en tiempo de compilacin:
#define PRUEBA(x) if(x<0) x = -100
main()
{
int a;
for(a=10; a>= -10; --a){
PRUEBA(a);
/* modificado a: if(a<0) a = -100; en tiempo de compilacin */
printf("a es %d\n",a);
}
}

El uso de macros incrementa el tamao del cdigo fuente en tiempo de compilacin,


pero el cdigo fuente original no es modificado por el compilador.
Ver seccin 10.4, ejercicio 10.1.

Programacin en Lenguaje C

105

Luis Hernndez Lara

Centro de Investigacin en Computacin

10.3 Inclusin de archivos fuente.


Existe otra directiva que causa que el cdigo fuente se expanda con el contenido de un
archivo especfico. Esto es muy til cuando los prototipos de funcin, y la definicin de
estructuras entre otros, son definidos en un archivo de texto por separado.
La directiva es:

#include <nombre_archivo> o #include "nombre_archivo".

Usando <> causar que el compilador busque el archivo en la ruta definida, mientras
que con el uso de el compilador buscar en el directorio de trabajo (actual). Esta
definicin vara dependiendo del compilador especfico en uso. Por ejemplo:

Archivo fuente: estructura.h


struct ABCD {
int a, b, c, d;
};
Archivo fuente: programa.c
#include "estructura.h"
main()
{
struct ABCD cuatro;
}
El ejemplo anterior incluye el archivo estructura.h dentro del archivo programa.c en
tiempo de compilacin para formar el siguiente archivo fuente a ser compilado:
struct ABCD {
int a, b, c, d;
};
main()
{
struct ABCD cuatro;
}
Existen muchas directivas del preprocesador pero son dependientes del compilador en
uso. Algunas proporcionan mtodos para incluir cdigo en ensamblador directamente
en el programa fuente. El siguiente es un ejemplo de ello:

Programacin en Lenguaje C

106

Luis Hernndez Lara

Centro de Investigacin en Computacin

void main()
{
int a;
#asm
mov #1, d0
#endasm
a=5;
printf("%d\n",a);
}

Programacin en Lenguaje C

107

Luis Hernndez Lara

Centro de Investigacin en Computacin

10.4 Ejercicios del captulo.


Ejercicio 10.1.
/*
Archivo:
Objetivo:
Funcin:

ejer101.c
Mostrar el uso de Directivas al preprocesador y paso de
parmetros en la lnea de comandos
Eleva al cubo un dgito entre 0 y 9. Hace uso de una
macro para verificar si es dgito y se pasa al programa
en lnea de comandos una clave de acceso que es validada

*/
/* Directivas al preprocesador */
# include <stdio.h>
# define es_entero(x) ( (x >= '0' && x <= '9') ? 1 : 0 )
/* MACRO */
/* la macro es para saber si una variable es digito */
/* Declaracin de variables y funciones */
char password[] = "X99TEST";
int al_cubo(int);
/* Funcin main */
void main(int argc, char *argv[])
{
char caracter;
int resultado;
if(argc < 2) exit(0);
if(strcmp(password,argv[1]))
{
printf("clave invlida ");
getch();
exit(0);
}
printf("\nTeclee dgito a elevar al cubo _ ");
caracter = getch();
if(es_entero(caracter))
{
resultado = al_cubo(caracter-'0');
printf("\nEl resultado de elevar %d al cubo es %d",
caracter-'0',resultado);
}
else
printf("\nEl carcter introducido no es dgito");
getch();
} /* fin de main */
/* Funcin que eleva al cubo un dgito */
int al_cubo(int y)
{
return (y*y*y);
}

Programacin en Lenguaje C

108

Luis Hernndez Lara

Centro de Investigacin en Computacin

11. ESTRUCTURAS.
11.1 Definicin.
Las estructuras se utilizan en C para organizar una coleccin de variables en un
grupo definido. Este grupo es llamado estructura y es similar a los registros en otros
lenguajes. Mientras que los registros contienen campos, las estructuras contienen
miembros.
Un ejemplo clsico es una estructura nomina usada para una aplicacin de negocios.
Esta estructura debe contener miembros como nombre, nmero de seguro social, y
salario. C tambin permite la creacin de estructuras que contienen estructuras
(estructuras anidadas). Por ahora slo examinaremos una estructura sencilla con
caracteres y enteros.
Hay tres pasos bsicos al trabajar con estructuras:
1) Definir el tipo de estructura, organizar los miembros deseados y asignar un
nombre a la estructura. Este paso no reserva espacio en memoria para la
estructura.
2) Reservar espacio para la estructura asignando un nombre de variable al tipo de
estructura. Esta puede ser una estructura, un apuntador a una estructura, o un
arreglo de estructuras.
3) Usar la estructura.

Haciendo referencia a la estructura de ejemplo nomina, aplicaremos los tres pasos:


Paso 1. Definir la estructura.
struct nomina {
char nombre[40];
long int imss_no;
long int salario;
};
Paso 2. Reservar espacio para la estructura.
struct nomina empleado;

Programacin en Lenguaje C

109

Luis Hernndez Lara

Centro de Investigacin en Computacin

Paso 3. Usar la estructura definida. La sintaxis para su uso es:


<variable de estructura>.<miembro>

Para la estructura definida, esto debe ser:


empleado.nombre
empleado.imss_no
empleado.salario
Note que un miembro de la estructura es referenciado usando el nombre de la
estructura con un punto colocado antes del nombre del miembro.
Para acceder a cada carcter del nombre a travs de la estructura, tendramos:
empleado.nombre[0] = primer carcter, empleado.nombre[1], ect.
Un ejemplo sencillo es el siguiente:
struct
nomina {
char nombre[40];
long int imss_no;
long int salario;
};
void main()
{
struct nomina empleado;
empleado.salario = 10000;
empleado.imss_no = 98030001;
empleado.nombre = Pepe Casas;
printf(\n%s\n,empleado.nombre);
printf("%ld %ld\n",empleado.salario, empleado.imss_no);
}

En el ejemplo anterior la definicin de la estructura se hiz fuera de las funciones. Esto


obedece a que es preferible que la estructura sea una definicin global y que en cada
funcin que se requiera se reserve espacio para alojar la estructura.

Programacin en Lenguaje C

110

Luis Hernndez Lara

Centro de Investigacin en Computacin

11.2 Arreglos de estructuras.


Cuando ms de una estructura se requiere, un arreglo de estructuras puede crearse. El
ejemplo siguiente reserva espacio para cinco estructuras nomina. Cada estructura se
referenciar usando un desplazamiento dentro del arreglo, mientras que para
referenciar a los miembros se usa la sintaxis antes vista:

struct nomina empleado[5];


empleado[0].salario = 10000; /* hace referencia al salario del primer empleado */
El siguiente ejemplo inicializa cada estructura con cero para los miembros de tipo
entero largo y con nulo para cada carcter de cada miembro del arreglo de tipo
carcter.
struct nomina {
char nombre[40];
long int imss_no;
long int salario;
};
void main()
{
int i,j;
struct nomina empleado[5];
for(i=0; i<5 ; i++){
empleado[i].imss_no = 0;
empleado[i].salario = 0;
for(j=0; j<40 ; j++)
empleado[i].nombre[j] = '\0';
}
}

11.3 Inicializacin de etructuras.


Una vez que una estructura ha sido definida, su inicializacin puede ser hecha en
tiempo de compilacin, como se muestra a continuacin:
struct banderas {
int tipo;
int edo_actual;
int edo_previo;
};

Programacin en Lenguaje C

111

Luis Hernndez Lara

Centro de Investigacin en Computacin

void main()
{
struct banderas arreglo[] = {
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11

/* arreglo [0] */
/* arreglo [1] */
/* arreglo [2] */
/* arreglo [3] */

};
}
Cada miembro es inicializado de izquierda a derecha, la inicializacin del arreglo queda
as:

arreglo[0]
arreglo[0].tipo = 0 arreglo[0].edo_actual = 1 arreglo[0].edo_previo = 2
arreglo[1]
arreglo[1].tipo = 3 arreglo[1].edo_actual = 4 arreglo[1].edo_previo = 5
arreglo[2]
arreglo[2].tipo = 6 arreglo[2].edo_actual = 7 arreglo[2].edo_previo = 8
arreglo[3]
arreglo[3].tipo = 9 arreglo[3].edo_actual = 10 arreglo[3].edo_previo = 11
Para clarificar el concepto se pueden usar llaves adicionales dentro de la parte de
inicializacin para inicializar cada elemento del arreglo. Por ejemplo:
struct banderas {
int tipo;
int edo_actual;
int edo_previo;
};
void main()
{
static struct banderas arreglo[] = {
{ 0,1,2 },
{ 3,4,5 },
{ 6,7,8 },
{ 9,10,11 }
};
}

Programacin en Lenguaje C

112

Luis Hernndez Lara

Centro de Investigacin en Computacin

Otra forma de definir y reservar espacio para estructuras, adems de inicializarlas, se


muestra a continuacin. Aqu tambin se nota que la definicin de una estructura puede
hacerse dentro de una funcin y slo esa funcin la conocer:
void main()
{
struct info{
char *nombre;
int no_empleado;
} persona[] = {
"Anita", 111,
"Juan", 222,
"Karina", 333,
"Manuel", 444,
"", 0
};
}

/* Nota: persona[4].nombre[0] = 0 */

El siguiente ejemplo imprime los datos de inicializacin:


void main()
{
int i;
struct info{
char *nombre;
int no_empleado;
} persona[] = {
"Anita", 111,
"Juan", 222,
"Karina", 333,
"Manuel", 444,
"", 0
};
for(i=0; persona[i].nombre[0] != '\0'; i++) {
printf("Nombre: %s\n", persona[i].nombre);
printf("Nmero de Empleado: %d\n", persona[i].no_empleado);
}
}

Programacin en Lenguaje C

113

Luis Hernndez Lara

Centro de Investigacin en Computacin

11.4 Estructuras y funciones.


El estndar ANSI permite el paso de estructuras a funciones. Esto se logra en tiempo
de ejecucin, en el cual una copia de la estructura se pasa a la funcin. Tambin se
puede pasar un apuntador a la estructura para permitir que la funcin modifique
cualquier miembro de la estructura.
Las estructuras del mismo tipo pueden ser copiadas usando un simple operador de
asignacin (=). Lo mismo sirve para copiar cada uno de los miembros de la estructura.
Ejemplo:
struct temp {
int at;
int bt;
};
struct temp acceso(struct temp);

/* definicin de estructura */

/* prototipo de funcin */

void main()
{
struct temp test, test2;

/* reserva espacio */

test.at=5; test.bt=10;
/* inicializa miembros */
test2=test;
/* copia la estructura */
test2.at=test.at;
/* o copia miembro a miembro */
test2.bt=test.bt;
/* pasa una copia de test a acceso() y regresa una
copia modificada desde acceso() en test2 */
test2=acceso(test);
printf("%d %d\n",test.at, test.bt);
/* imprime: 5 10 */
printf("%d %d\n",test2.at,test2.bt);
/* imprime: 100 200 */
}
/* Una copia de la estructura tipo temp es colocada en la variable v. */
struct temp acceso(struct temp v)
{
v.at=100; v.bt=200;
return(v);
/* regresa la estructura a la funcin de llamada */
}

Programacin en Lenguaje C

114

Luis Hernndez Lara

Centro de Investigacin en Computacin

11.5 Apuntadores a estructuras.


Una sintaxis diferente se debe usar para referenciar apuntadores a estructuras. Es
necesario utilizar la indireccin. A continuacin se declaran una variable de tipo
estructura y una variable apuntador al mismo tipo de estructura.
struct temp{
int a;
int b;
};
struct temp ab, *p;
Usando la estructura:
ab.a=100; ab.b=200;
Usando el apuntador, primeramente el apuntador debe ser inicializado:
p = &ab;

/* la direccin de la estructura ab se pasa a p */

Entonces el apuntador puede ser usado para referenciar los miembros almacenados
dentro de ab utilizando la sintaxis de indireccin:
printf("%d %d\n", (*p).a, (*p).b );

/* imprime: 100 200 */

Una forma ms corta de referenciar a la estructura a travs de apuntadores es utilizar el


operador flecha (->), como se muestra a continuacin.
printf("%d %d\n", p->a, p->b );

/* imprime: 100 200 */

11.6 Paso de apuntadores a estructuras a funciones.


Las estructuras pueden ser referenciadas por funciones por medio del uso de
apuntadores. El siguiente ejemplo ilustra como un apuntador a una estructura es
pasado a una funcin. La funcin puede modificar el contenido de la estructura original
definida en la funcin de llamada. En el siguiente ejemplo la funcin de llamada es
main().

Programacin en Lenguaje C

115

Luis Hernndez Lara

Centro de Investigacin en Computacin

struct temp{
/* declara una estructura */
int a;
int b;
};
void acceso(struct temp *);
/* prototipo de funcin */
void main()
{
struct temp prueba;
acceso(&prueba);
/* pasa la direccin de prueba a acceso() */
printf("%d %d\n", prueba.a, prueba.b);
/* imprime: 100 200 */
} /* fin de main */
void acceso(struct temp *v) /* recibe apuntador a la estructura prueba */
{
v->a=100;
v->b=200;
}

El siguiente ejemplo muestra como se puede hacer lo mismo a travs del uso de la
sintaxis de apuntadores.
struct temp{
int a;
int b;
};
void acceso (struct temp *);
void main()
{
struct temp prueba, *ap;
acceso(&prueba);
ap=&prueba;
printf("%d %d", (*ap).a, (*ap).b);
} /* fin de main */
void acceso(struct temp *v)
{
(*v).a=100;
(*v).b=200;
} /* fin de acceso */

Programacin en Lenguaje C

116

Luis Hernndez Lara

Centro de Investigacin en Computacin

11.7 Paso de arreglos de estructuras a funciones.


El siguiente ejemplo pasa la direccin de comienzo del arreglo de estructuras clases a
la funcin muestra() donde se imprime.
struct nombres{
char *alumno;
int calif;
};
void muestra(struct nombres lista[]);

/* prototipo de funcin */

void main()
{
static struct nombres clases[] = {
"Bertha", 1,
"Ral", 2,
"Joaquin", 3,
"Gaby", 4,
"", 0
/* "" apunta al carcter nulo para indicar el fin del arreglo */
};
muestra(clases);
} /* fin de main */
void muestra(struct nombres lista[])
{
int i,j;
for(i=0; lista[i].alumno[0] != '\0'; i++){
printf("Nombre:%s ",lista[i].alumno);
printf("Calificacin:%d",lista[i].calif);
}
/* Imprime cada carcter del nombre */
for(i=0,j=0; lista[i].alumno[j] != '\0';j=0,i++){
while(lista[i].alumno[j] != '\0'){
printf("%c",lista[i].alumno[j]);
j++;
}
printf("\n");
}
} /* fin de muestra */

Programacin en Lenguaje C

117

Luis Hernndez Lara

Centro de Investigacin en Computacin

El programa imprime:
Nombre: Bertha Calificacin:1
Nombre: Ral Calificacin:2
Nombre: Joaquin Calificacin:3
Nombre: Gaby Calificacin:4
Bertha
Ral
Joaquin
Gaby

Ver seccin 11.8, ejercicio 11.1.

Programacin en Lenguaje C

118

Luis Hernndez Lara

Centro de Investigacin en Computacin

11.8 Ejercicios del captulo.


Ejercicio 11.1.
/*
Archivo:
Objetivo:
Funcin:

ejer111.c
Mostrar el uso de estructuras, arreglos de apuntadores
a estructuras y paso a funciones.
Crear una pequea base de datos en memoria que contenga
estructuras predefinidas. Las estructuras para almacenar
los datos se gestionan dinmicamente. Los apuntadores a
las estructuras se guardan en un arreglo de apuntadores.

*/
#include
#include
#include
#include
#include

<stdio.h>
<conio.h>
<ctype.h>
<stdlib.h>
<string.h>

void altas( struct datos *informacion[], int *elem);


void consultas( struct datos *informacion[],int elem), limpia();
menu();
/* Declaracin de la estructura a utilizar */
struct datos{
char nombre[40];
char laboratorio[50];
char especialidad[60];
long ext;
char correo[30];
};
void main()
{
char opcion;
struct datos *informacion[20];

/* arreglo de apuntadores
a estructuras */

int elem=0;
limpia();
/* no usamos clrscr() porque no es de ANSI C */
do
{
opcion = menu();
switch(opcion)
{
case 'a': altas(informacion,&elem);
break;
case 'c': consultas(informacion,elem);
break;
}
}while(opcion != 's');
} /* fin de main */

Programacin en Lenguaje C

119

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Visualiza el menu y espera la respuesta */


menu()
{
char ch;
do
{
printf("\n(A)adir, (C)onsultar, o (S)alir: ");
ch = tolower(getche());
printf("\n");
}while(ch != 's' && ch != 'a' && ch != 'c');
return ch;
}
/* Agregar un nombre y un nmero al directorio */
void altas( struct datos *informacion[], int *elem)
{
char numeros[8];
int i;
i = *elem;
if((informacion[i] =
(struct datos *) malloc(sizeof(struct datos))) == NULL)
{
printf("\nProblemas de Gestin de Memoria \n");
getch();
exit(0);
}
printf("\nIntroducir nombre: ");
gets(informacion[i]->nombre);
printf("\nIntroducir laboratorio: ");
gets(informacion[i]->laboratorio);
printf("\nIntroducir especialidad: ");
gets(informacion[i]->especialidad);
printf("\nIntroducir extensin: ");
gets(numeros);
informacion[i]->ext = atol(numeros);
/* ascii to long */
printf("\nIntroducir correo electrnico: ");
gets(informacion[i]->correo);
*elem+=1;
}
/* limpia la pantalla */
void limpia()
{
int j;
for(j=1;j<=25;j++) printf("\n");
}

Programacin en Lenguaje C

120

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Encuentra la informacin dando un nombre */


void consultas( struct datos *informacion[],int elem)
{
char nom1[40];
int n;
printf("\nTeclee el Nombre del investigador ?_ ");
gets(nom1);
/* Consulta los datos */
for(n=0; n<=elem-1; n++)
{
if(!strcmp(nom1,informacion[n]->nombre))
{
printf("\nLaboratorio: %s",informacion[n]->laboratorio);
printf("\nEspecialidad: %s",informacion[n]->especialidad);
printf("\nExtensin: %5ld",informacion[n]->ext);
printf("\nE-mail: %s",informacion[n]->correo);
break;
}
}
}

Programacin en Lenguaje C

121

Luis Hernndez Lara

Centro de Investigacin en Computacin

12. CAMPO DE BITS Y UNIONES.


12.1 Campo de bits.
El lenguaje C permite acceder a un nico bit en un byte para necesidades especiales.
El mtodo utilizado es definir un campo de bits como un miembro de una estructura.
Los campos de bits slo pueden ser definidos como enteros sin signo y es ilegal
asignar la direccin del miembro de la estructura campo de bits a un apuntador. El
siguiente ejemplo muestra la defincin de campo de bits:
#define ON 1
#define OFF 0
#define TRUE 7
struct bandera{
unsigned int pband:1;
/* pband puede contener 1 bit */
unsigned int sband:1;
/* sband puede contener 1 bit */
unsigned int jband:3;
/* jband puede contener 3 bits */
} estado;
/* reserva espacio para la estructurar global bandera llamada "estado" */
void main()
{
/* los campos de bit pueden ser usados como enteros normales */
estado.pband = ON;
estado.sband = OFF;
estado.jband = TRUE;
}

A continuacin se ilustra como los valores de los miembros de una estructura campo
de bits pueden ser probados usando una oracin if. Tambin ilustra como un valor
ser truncado cuando el ancho del campo de bits es excedido.
Por ejemplo: si el campo de bits puede contener 3 bits, el valor ms largo que puede
almacenar es 7. Para cualquier valor mayor que 7, slo los bits ms significativos del
valor sern usados.
#define ON 1
#define OFF 0
#define TRUE 7

Programacin en Lenguaje C

122

Luis Hernndez Lara

Centro de Investigacin en Computacin

struct bandera{
unsigned int pband:1;
unsigned int sband:1;
unsigned int jband:3;
} estado;
void main()
{
estado.pband = ON;
estado.sband = OFF;
estado.jband = TRUE;
if(estado.pband)
printf("bandera en ON\n");
else
printf("bandera en OFF\n");
estado.pband = 7;
printf("%d\n", estado.pband);
}
El programa imprime:
1 "ya que pband slo puede contener 1 bit"

12.2. Uniones.
Las uniones se parecen mucho a las estructuras, debido a que sus miembros se
referencian usando la misma sintaxis. Las uniones pueden ser colocadas dentro de
uniones o de estructuras, y los apuntadores a las uniones son permitidos. Pero las
uniones son usadas para contener un miembro simple en cualquier tiempo. Un
miembro simple puede ser una estructura o un arreglo de estructuras.
Por lo tanto, la principal diferencia entre estructuras y uniones es la cantidad de espacio
alojado cuando la memoria es reservada. Por ejemplo:
union abc{
int i;
char b;
};

struct abc{
int i;
char b;
};

union abc a;
a.i=100;
a.b='Z';

struct abc a;
a.i=100;
a.b='Z';

La union abc reserva slo espacio suficiente para que la unin a contenga el tipo del
miembro ms grande. En el ejemplo anterior, el entero i es el miembro ms largo. Sin

Programacin en Lenguaje C

123

Luis Hernndez Lara

Centro de Investigacin en Computacin

embargo la estructura abc reserva espacio para que la estructura a pueda contener
tanto al entero i como al carcter b.
En trminos ms simples, una unin sirve para alojar en un mismo espacio de memoria
diferentes tipos de datos, pero slo uno a la vez. Los tipos de datos sern los miembros
de la unin. Por ejemplo:
#define INT 1
#define CHAR 2
#define FLOAT 3
void main()
{
union utipo{
int i;
char c;
float f;
} valor;

/* se declara una estructura tipo union */

int typ;
valor.i=1009;
typ=INT;
if(typ==INT)
printf("%d\n",valor.i);
else if(typ==CHAR)
printf("%c\n",valor.c);
else if(typ == FLOAT)
printf("%f\n",valor.f);
}
El programa imprime: 1009

El siguiente ejemplo ilustra el uso de una unin dentro de una estructura. Un ejemplo
sencillo que guarda la pista del tipo de la variable, dependiendo de los datos ASCII de
entrada. Muestra como usar la sintaxis correcta para referenciar apropiadamente los
miembros de la unin.

Programacin en Lenguaje C

124

Luis Hernndez Lara

Centro de Investigacin en Computacin

#define INT 1
#define CHAR 2
#define MAX 10
struct prueba{
int tipo;
union {
int ival;
int cval;
} valor;
}tabla[MAX];
void main()
{
int i,v;
/* colecciona valores de tipos int o char */
for(i=0; i<MAX; i++)
{
v=getchar();
/* espera hasta retorno de carro (carriage return) */
while((getchar()) != '\n');
/* Es un nmero? */
if( v<= '9' && v >= '0')
{
tabla[i].valor.ival= v - '0';
tabla[i].tipo=INT;
}
/* sino, debe ser un carcter */
else
{
tabla[i].valor.cval= v ;
tabla[i].tipo=CHAR;
}
}
/* ahora se imprimen */
for(i=0; i<MAX; i++){
if( tabla[i].tipo == INT)
printf("%d\n",tabla[i].valor.ival);
else if( tabla[i].tipo == CHAR)
printf("%c\n",tabla[i].valor.cval);
}
}

Programacin en Lenguaje C

125

Luis Hernndez Lara

Centro de Investigacin en Computacin

Otra caracterstica de las uniones es que permiten al programador accesar el mismo


dato usando diferentes tipos de datos. Esto es, los datos almacenados dentro de la
variable unin pueden referenciarse usando cualquiera de los tipos de datos definidos
en la unin. El siguiente ejemplo ilustra esto:

/* definicin de la unin XYZ */


union XYZ {
int i;
char a[2];
};
void main()
{
/* aloja espacio para la variable "abc" */
union XYZ abc;
/* almacena un entero en i - asume entero de 16 bits */
abc.i=0xfaaf;
/* imprime un byte a la vez */
printf("%x %x\n",abc.a[0], abc.a[1] );
}

Ver seccin 12.4, ejercicio 12.1.

12.3 Estructuras y uniones anidadas.


Cuando una estructura o unin se define dentro de una estructura o unin, se usa la
referencia simple a un miembro determinado usando los nombres de los miembros
separados por un punto. Cuando se usan apuntadores se separan los miembros
utilizando caracteres flecha (->).

Programacin en Lenguaje C

126

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejemplo:
struct A {
int i,j,k;
};

/* definicin de la estructura A */

struct B {
char a,b,c;
};

/* definicin de la estructura B */

struct C {
struct A ijk;
struct B abc;
struct A *ptr;
};

/* definicin de la estructura C, estructuras anidadas */

void main()
{
/* aloja espacio para estructuras */
struct A prueba; struct C ejemplo;
/* inicializa prueba */
prueba.i=1; prueba.j=2; prueba.k=3;
/* inicializa apuntador a estructura */
ejemplo.ptr = &prueba;
/* imprime prueba.i, prueba.j, prueba.k usando apuntador */
printf("%d %d %d ",ejemplo.ptr->i, ejemplo.ptr->j, ejemplo.ptr->k);
/* inicializa estructuras ijk y abc con ceros */
ejemplo.ijk.i=ejemplo.ijk.j=ejemplo.ijk.k=0;
ejemplo.abc.a=ejemplo.abc.b=ejemplo.abc.c=0;
}

No existen limitaciones para anidar estructuras o uniones siempre que se haga de


manera correcta.

Programacin en Lenguaje C

127

Luis Hernndez Lara

Centro de Investigacin en Computacin

12.4 Ejercicios del captulo.


Ejercicio 12.1.
/*
Archivo
Objetivo
Funcin

: ejer121.C
: Mostrar el uso combinado de campo de bits y uniones
: Dado un nmero entero largo , el programa lo
codifica en binario.

*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct codigo
/* un entero largo lo consideramos de 4 bytes */
{
int bit_1_1:1; int bit_1_2:1; int bit_1_3:1; int bit_1_4:1;
int bit_1_5:1; int bit_1_6:1; int bit_1_7:1; int bit_1_8:1;
int bit_2_1:1; int bit_2_2:1; int bit_2_3:1; int bit_2_4:1;
int bit_2_5:1; int bit_2_6:1; int bit_2_7:1; int bit_2_8:1;
int bit_3_1:1; int bit_3_2:1; int bit_3_3:1; int bit_3_4:1;
int bit_3_5:1; int bit_3_6:1; int bit_3_7:1; int bit_3_8:1;
int bit_4_1:1; int bit_4_2:1; int bit_4_3:1; int bit_4_4:1;
int bit_4_5:1; int bit_4_6:1; int bit_4_7:1; int bit_4_8:1;
};
union bits
{
long int num;
struct codigo bit;
};
/*union bits byte;*/
void lee_num(union bits *);
void codifica(union bits);
void main()
{
union bits byte;
char salir;
do
{
lee_num(&byte);
codifica(byte);
printf("\n\n Para terminar teclee 'f' _");
}while((salir=getch()) != 'f');
}

Programacin en Lenguaje C

128

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que lee el nmero */


void lee_num(union bits *byte)
{
printf("Codifica un nmero entero largo ");
printf("a su binario de 4 bytes\n");
printf("Introduzca un nmero entero largo: ");
scanf("%ld",&byte->num);
}
/* Funcin que muestra en binario el nmero introducido.
Hay que recordar que la computadora guarda un nmero entero (o
largo)en forma inversa, es decir; si la estructura se declar
byte1 byte2 byte3 byte4 debe inspeccionarse como
byte4 byte3 byte2 byte1
Los nmeros negativos se guardan por complemento a 2.
Ej. si el nmero es 76 sera:
0000 0000 0100 1100
se le aplica complemento a 1, queda: 1111 1111 1011 0011
al sumarle 1, queda:
-76
1111 1111 1011 0100
El resultado de este proceso se visualiza si se introducen negativos.
*/
void codifica(union bits b)
{
printf("%d",b.bit.bit_4_8?1:0);
printf("%d",b.bit.bit_4_7?1:0);
printf("%d",b.bit.bit_4_6?1:0);
printf("%d",b.bit.bit_4_5?1:0);
printf("%d",b.bit.bit_4_4?1:0);
printf("%d",b.bit.bit_4_3?1:0);
printf("%d",b.bit.bit_4_2?1:0);
printf("%d ",b.bit.bit_4_1?1:0);
printf("%d",b.bit.bit_3_8?1:0);
printf("%d",b.bit.bit_3_7?1:0);
printf("%d",b.bit.bit_3_6?1:0);
printf("%d",b.bit.bit_3_5?1:0);
printf("%d",b.bit.bit_3_4?1:0);
printf("%d",b.bit.bit_3_3?1:0);
printf("%d",b.bit.bit_3_2?1:0);
printf("%d ",b.bit.bit_3_1?1:0);
printf("%d",b.bit.bit_2_8?1:0);
printf("%d",b.bit.bit_2_7?1:0);
printf("%d",b.bit.bit_2_6?1:0);
printf("%d",b.bit.bit_2_5?1:0);
printf("%d",b.bit.bit_2_4?1:0);
printf("%d",b.bit.bit_2_3?1:0);
printf("%d",b.bit.bit_2_2?1:0);
printf("%d ",b.bit.bit_2_1?1:0);
printf("%d",b.bit.bit_1_8?1:0);
printf("%d",b.bit.bit_1_7?1:0);
printf("%d",b.bit.bit_1_6?1:0);
printf("%d",b.bit.bit_1_5?1:0);
printf("%d",b.bit.bit_1_4?1:0);
printf("%d",b.bit.bit_1_3?1:0);
printf("%d",b.bit.bit_1_2?1:0);
printf("%d",b.bit.bit_1_1?1:0);
}

Programacin en Lenguaje C

129

Luis Hernndez Lara

Centro de Investigacin en Computacin

13. ENUMERACIONES Y RENOMBRE DE TIPOS EXISTENTES.


13.1 Enumeraciones.
Una enumeracin es un conjunto de constantes enteras con nombre que especfica
todos los valores vlidos que una variable de ese tipo puede tener. Su definicin es
parecida a la de las estructuras. La palabra clave enum seala el comienzo del tipo
enumerado. Por ejemplo:
enum nombre { lista de enumeraciones (smbolos)} lista de variables;
Tanto el nombre de la enumeracin como la lista de variables son opcionales. Como
en las estructuras, se usa el nombre de la etiqueta para declarar variables de ese tipo.
Por ejemplo:
enum vehiculo { vw_sedan, corvette, porshe, mustang, tsuru, explorer };
enum vehiculo automovil;
Aqu, la declaracin de la enumeracin se llama vehiculo y declara automovil de ese
tipo. Las siguientes son operaciones permitidas:
automovil = porshe;
if (automovil == corvette) printf("Es un auto deportivo");
Cada uno de los smbolos de la enumeracin corresponde a un valor entero. De tal
forma, que pueden usarse en cualquier expresin entera. Cada smbolo recibe un valor
que es mayor en una unidad al smbolo que le precede. El valor del primer smbolo de
la enumeracin es 0.
La siguiente oracin
printf("%d %d", vw_sedan,mustang);
muestra los valores 0 y 3 en la pantalla.
Se puede especificar el valor de uno o ms smbolos utilizando un inicializador.
enum vehiculo { vw_sedan, corvette, porshe, mustang = 50, tsuru, explorer };
los valores que toman los smbolos son:
vw_sedan = 0, corvette = 1, porshe = 2, mustang = 50, explorer = 51

Programacin en Lenguaje C

130

Luis Hernndez Lara

Centro de Investigacin en Computacin

A veces se puede declarar un arreglo de cadenas y utilizar el valor de la enumeracin


como ndice para traducir un valor de enumeracin en su cadena correspondiente:
char nombre[][9]{
"vw_sedan",
"corvette",
"porshe",
"mustang",
"explorer"
};
printf("%s",nombre[automovil]);

13.2 Renombre de tipos existentes.


En "C" se permite definir explcitamente nuevos nombres para los tipos de datos,
usando la palabra clave typedef. No se crea un nuevo tipo de datos, sino que se define
un nuevo nombre para un tipo existente.
La forma general de uso de la palabra typedef es:

typedef tipo nuevo_nombre;

Por ejemplo, si escribimos:


typedef float tipo_salario;
tipo_salario sueldo_mensual;

/* tipo_salario es el nuevo nombre de float */


/* sueldo_mensual es una variable real tipo
tipo_salario */
typedef tipo_salario prestacion; /* prestacion es otro nombre de tipo_salario,
que es otro nombre de float */
Veamos un ejemplo con estructuras:
struct datos{
unsigned x;
int y;
float z;
};
struct datos xyz;
/* se declara xyz como una variable tipo datos */

Si usamos typedef:

Programacin en Lenguaje C

131

Luis Hernndez Lara

Centro de Investigacin en Computacin

typedef struct datos{


unsigned x;
int y;
float z;
} s_datos;
s_datos xyz;

/* s_datos es el nuevo nombre de "struct datos" */


/* se declara xyz como una variable tipo datos */

La misma tcnica puede usarse en uniones y enumeraciones.

Programacin en Lenguaje C

132

Luis Hernndez Lara

Centro de Investigacin en Computacin

13.3 Ejercicios del captulo.


Ejercicio 13.1.
/*
Archivo:
Objetivo:
Funcin:

ejer131.c
Mostrar el uso de typedef
Lee nmeros del teclado y construye una lista ligada
para almacenarlos (versin mnima)

Una lista ligada se expresa como:


start
*/

elemento head

elemento

...

elemento tail

NULL

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct Node{
int num;
struct Node *next;
}nodo;
/* se declara una variable apuntador al tipo nodo (estructura) */
nodo *start = NULL;
/* inserta x en la lista */
void insercion(int x)
{
nodo *p = start; /* declara e inicializa apuntador */
start = (nodo *) malloc (sizeof(nodo));
if(start==NULL) puts("No se gestion memoria"), exit(1);
start->num = x;
start->next = p;
}
void main(void)
{
int x;
nodo *p;
puts("Teclea una secuencia de enteros,"
"seguidos por un caracter no numrico");
while(scanf("%d",&x)==1) insercion(x);
puts("En orden inverso los siguientes nmeros han"
" sido leidos: ");
for(p=start; p!=NULL; p=p->next)
printf("%5d\n",p->num);
getch();
}

Programacin en Lenguaje C

133

Luis Hernndez Lara

Centro de Investigacin en Computacin

14. ARCHIVOS.
En el lenguaje "C", un archivo puede ser desde un archivo en disco hasta una terminal
o una impresora. Mediante una operacin de apertura se asocia una secuencia a un
archivo especfico. Una vez que el archivo est abierto, se puede intercambiar
informacin entre ste y el programa.
Las funciones ms comunes del sistema de archivos de ANSI "C" se muestran a
continuacin:

Funcin
fopen()
fclose()
putc()
fputc()
getc()
fgetc()
fseek()
fprintf()
fscanf()
feof()
ferror()
rewind()
remove()
fflush()

Actividad
Abre un archivo
Cierra un archivo
Escribe un carcter en un archivo
Escribe un carcter en un archivo
Lee un carcter de un archivo
Lee un carcter de un archivo
Busca un byte especfico de un archivo
Hace lo mismo en archivos que printf() en la consola
Hace lo mismo en archivos que scanf() en la consola
Devuelve cierto si se llega al final del archivo
Devuelve cierto si se ha producido un error
Coloca el indicador de posicin del archivo al principio del mismo
Borra un archivo
Vaca un archivo

Tabla 14.1. Funciones del sistema de archivos en ANSI "C".

Para la apertura de archivos existen diferentes modos que se pueden utilizar. A


continuacin se muestran:
Modo
r
w
a
rb
wb

Descripcin
Abre un archivo de texto de lectura
Crea un archivo de texto de escritura
Abre un archivo de texto para aadir informacin
Abre un archivo binario de lectura
Crea un archivo binario de escritura

Tabla 14.2. Modos de apertura de un archivo.

Programacin en Lenguaje C

134

Luis Hernndez Lara

Centro de Investigacin en Computacin

Modo
ab
R+
w+
a+

Descripcin
Abre un archivo binario para aadir informacin
Abre un archivo de texto de lectura/escritura
Crea un archivo de texto de lectura/escritura
Abre o crea un archivo de texto en modo lectura/escritura para aadir
informacin

Tabla 14.2. Modos de apertura de un archivo (cont.).

El manejo de archivos es fundamental en las aplicaciones de programacin, sin


embargo, dado el alcance de este trabajo, se ha considerado conveniente no
introducirnos mucho en explicaciones detalladas, y mejor nos proponemos mostrar
cdigo que hace uso de algunas de las funciones. El lector deber profundizar en un
estudio ms minucioso de ellas.

Programacin en Lenguaje C

135

Luis Hernndez Lara

Centro de Investigacin en Computacin

14.1 Ejercicios del captulo.


Ejercicio 14.1.
/*
Archivo: ejer141.c
Objetivo: Mostrar el uso de funciones de entrada/salida fopen y putc
Funcion: Crea un archivo en disco, a imagen de como se teclea, hasta
que se de el fin de archivo EOF (CTRL Z), para ambiente
consola
La ejecucin se hace a travs de la lnea de comandos:
==> ejer141 nombre_archivo
Usa fopen para abrir un archivo como buffer para efectuar
operaciones de entrada/salida
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(int argc, char *argv[])
{
FILE *fp;
/* apuntador a archivo */
char ch;
if(argc != 2){
printf("olvid introducir el nombre del archivo\n");
getch();
exit(1);
}
if((fp=fopen(argv[1],"w")) == NULL){
/* abre de escritura */
/* si existe, se destruye su contenido*/
printf("no puedo abrir el archivo\n");
exit(1);
}
do{
ch = getchar();
if(ch!=EOF)
putc(ch,fp);
/* escribe un carcter a un archivo abierto como
buffer de salida */
} while (ch != EOF);
fclose(fp);
/* cierra un archivo */
} /* fin de main */

Programacin en Lenguaje C

136

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 14.2.
/*
Archivo:
Objetivo:
Funcin:

ejer 142.c
Mostrar el uso de funciones de entrada/salida fopen y getc
Abre un archivo de disco y lo lee carcter por carcter,
hasta encontrar el fin de archivo EOF.
Usa fopen() para abrir un archivo de slo lectura, si el
archivo no existe falla la operacin, el archivo funciona
como buffer de entrada/salida.
El programa se ejecuta:
===> ejer142 nombre_archivo

*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(int argc, char *argv[])
{
FILE *fp;
/* apuntador a archivo */
char ch;
if(argc != 2){
printf("olvid introducir el nombre del archivo\n");
exit(1);
}
if((fp=fopen(argv[1],"r")) == NULL){ /* abre de lectura */
printf("\nNo puedo abrir el archivo\n");
getch();
exit(1);
}
ch = getc(fp);
/*lee un carcter de un archivo abierto
como buffer de entrada */
while (ch != EOF){
/* detecta fin de archivo */
putchar(ch);
/* despliega en pantalla*/
ch=getc(fp);
}
fclose(fp);
/* cierra el archivo */
} /* fin de main */

Programacin en Lenguaje C

137

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 14.3.
/*
Archivo: ejer143.cpp
Objetivo: Mostrar el uso de las funciones fread() y fwrite().
Escribir datos a un buffer de salida y volverlo a abrir de
lectura
Funcin: Abre un archivo para operaciones de escritura binarias
(modo wb)
Escribe en un archivo en disco con fwrite(), lo cierra y lo
lee con la funcin fread().
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
char linea[80] = "Prueba de escritura con fwrite\n"
"Y de lectura con fread.\n";
void main()
{
FILE *out, *in;
/* apuntadores a archivo */
int car_escritos, car_leidos;
char nombre_archivo[80];
printf("\nEscriba el nombre del archivo a crear y leer: ");
gets(nombre_archivo);
/* Abrir archivo para escritura binaria, si existe su contenido se
destruye */
if((out=fopen(nombre_archivo,"wb")) == NULL)
{
printf("\nFall la apertura del archivo\n");
getch();
exit(0);
}
/* Se escribe en el archivo el contenido del buffer linea[], 80
caracteres */
car_escritos = fwrite((void *)linea,sizeof(char),80,out);
/* Se despliega el no. de caracteres grabados al archivo */
printf("\n%d caracteres grabados en %s\n",car_escritos,
nombre_archivo);
/* Se cierra el archivo */
fclose(out);

Programacin en Lenguaje C

138

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Abrimos el archivo para leerlo en forma binaria*/


if((in=fopen(nombre_archivo,"rb")) == NULL)
{
printf("\nFall la apertura del archivo\n");
getch();
exit(0);
}
/*

Se leen 80 caracteres del archivo y se despliega el buffer */


car_leidos = fread((void *)linea,sizeof(char),80,in);
printf("\nLe estos %d caracteres:\n%s\n",car_leidos,linea);
fclose(in);
getch();

} /* fin de main */

Programacin en Lenguaje C

139

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 14.4.
/*
Archivo: ejer144.c
Objetivo: Mostrar el uso de estructuras combinadas con archivos
Funcin: Crear y consultar un pequeo directorio permanente
*/
#include
#include
#include
#include
#include

<stdio.h>
<conio.h>
<ctype.h>
<stdlib.h>
<string.h>

void altas(), consultas(), limpia();


menu();
/* Declaracin de la estructura a utilizar */
struct datos{
char nombre[40];
char laboratorio[50];
char especialidad[60];
long ext;
char correo[30];
}informacion;
void main()
{
char opcion;
limpia();
/* no usamos clrscr() porque no es de ANSI C */
do
{
opcion = menu();
switch(opcion)
{
case 'a': altas();
break;
case 'c': consultas();
break;
}
}while(opcion != 's');
} /* fin de main */
/* Visualiza el men y espera la respuesta */
menu()
{
char ch;
do
{
printf("\n(A)adir, (C)onsultar, o (S)alir: ");
ch = tolower(getche());
printf("\n");
}while(ch != 's' && ch != 'a' && ch != 'c');
return ch;
}

Programacin en Lenguaje C

140

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Agregar un nombre y un nmero al directorio */


void altas()
{
FILE *fp;
char numeros[8];
/* Abre para agregar */
if((fp=fopen("profes.dat","ab")) == NULL){
printf("\nNo puedo abrir archivo de escritura\n");
getch();
exit(1);
}
printf("\nIntroducir nombre: ");
gets(informacion.nombre);
printf("\nIntroducir laboratorio: ");
gets(informacion.laboratorio);
printf("\nIntroducir especialidad: ");
gets(informacion.especialidad);
printf("\nIntroducir extensin: ");
gets(numeros);
informacion.ext = atol(numeros);
/* ascii to long */
printf("\nIntroducir correo electrnico: ");
gets(informacion.correo);
/* escribe en archivo */
fwrite(&informacion,sizeof(struct datos),1,fp);
fclose(fp);
}

Programacin en Lenguaje C

141

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Encuentra la informacin dando "nombre" como llave */


void consultas()
{
FILE *fp;
char nom1[40];
/* Abre para leer */
if((fp=fopen("profes.dat","rb")) == NULL){
printf("\nNo puedo abrir archivo de lectura\n");
getch();
exit(1);
}
rewind(fp);
/* rebobina el archivo al principio */
printf("\nTeclee el Nombre del investigador ?_ ");
gets(nom1);
/* Consulta los datos */
while(!feof(fp))
{
fread(&informacion,sizeof(struct datos),1,fp);
if(!strcmp(nom1,informacion.nombre))
{
printf("\nLaboratorio: %s",informacion.laboratorio);
printf("\nEspecialidad: %s",informacion.especialidad);
printf("\nExtensin: %5ld",informacion.ext);
printf("\nE-mail: %s",informacion.correo);
break;
}
}
fclose(fp);
}
/* limpia la pantalla */
void limpia()
{
int j;
for(j=1;j<=25;j++) printf("\n");
}

Programacin en Lenguaje C

142

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 14.5.
/*
Archivo: ejer145.c
Objetivo: Mostrar un ejemplo completo de manejo de archivos
Funcin: Crear y consultar un directorio permanente en disco,
las operaciones de carga de datos y consultas se hacen en
memoria.
*/
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#define TAM 100
struct tipo_lista {
char nombre[25];
char tel[10];
char calle[20];
char ciudad[10];
char estado[3];
char codigo[10];
} lista[TAM],temporal;
/* PROTOTIPOS DE FUNCIN

/* arreglo de estructuras de 100 elementos

*/

*/

int menu(void);
void inicializa_lista(void), intro(void);
void mostrar(void), salvar(void);
void cargar(void);
void reporta(void);
void borra(void);
void busca(void);
password();

Programacin en Lenguaje C

143

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* FUNCIN MAIN

*/

void main(void)
{
int entrada;
char opcion;
do {
entrada=password();
if(entrada==3) exit(0);
} while(entrada!=10);

inicializa_lista();
for(;;)
{
opcion=menu();
switch(opcion){
case 'i': intro();
break;
case 'm': mostrar();
break;
case 's': salvar();
break;
case 'c': cargar();
break;
case 'r': reporta();
break;
case 'b': borra();
break;
case 'e': busca();
break;
case 't': exit(0);
} /* fin de switch
*/
} /* fin de for
*/
/* fin de main
*/

/*
FUNCIN PASSWORD
*/
password()
{
static int intentos=0;
char pass[80];
clrscr();
printf("\n Teclee password: ");
gets(pass);
intentos++;
if(!strcmp(pass,"curso c")) return 10;
return intentos;
} /* fin de password */

Programacin en Lenguaje C

144

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* FUNCIN QUE INICIALIZA LA LISTA EN MEMORIA */


void inicializa_lista(void)
{
int t;
for(t=0; t<TAM; t++)
*lista[t].nombre='\0';
/* una longitud de nombre igual a cero significa vaco
} /* fin de inicializa_lista */

*/

/* INTRODUCIR NOMBRES A LA LISTA


*/
void intro(void)
{
int i;
for(i=0; i<TAM; i++)
if(! *lista[i].nombre) break;
if(i==TAM)
printf("Lista llena \n");
else
{
printf("\n Nombre: ");
gets(lista[i].nombre);
printf("\n Telfono: ");
gets(lista[i].tel);
printf("\n Calle: ");
gets(lista[i].calle);
printf("\n Ciudad: ");
gets(lista[i].ciudad);
printf("\n Estado: ");
gets(lista[i].estado);
printf("\n Codigo: ");
gets(lista[i].codigo);
}
} /* fin de intro */

Programacin en Lenguaje C

145

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* MOSTRAR LA LISTA */
void mostrar(void)
{
int t;
clrscr();
for(t=0; t<TAM; t++)
{
if(*lista[t].nombre)
{
printf("%s \n", lista[t].nombre);
printf("%s \n", lista[t].tel);
printf("%s \n", lista[t].calle);
printf("%s \n", lista[t].ciudad);
printf("%s \n", lista[t].estado);
printf("%s \n", lista[t].codigo);
} /*
fin de if
*/
} /* fin de for */
printf("\n Presione cualquier tecla para continuar");
getch();
} /* fin de mostrar */
/* SALVAR LA LISTA
*/
void salvar(void)
{
FILE *fp;
int i;
if((fp=fopen("correo","wb"))==NULL)
printf("No se puede abrir el archivo. \n");
else
{
for(i=0; i<TAM; i++)
if(*lista[i].nombre)
if(fwrite(&lista[i],sizeof(struct tipo_lista),1,fp)!=1)
printf("Error de escritura en el archivo \n");
fclose(fp); /* se cierra el archivo */
}
} /* fin de salvar */

Programacin en Lenguaje C

146

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* CARGAR EL ARCHIVO */
void cargar(void)
{
FILE *fp;
int i;
if((fp=fopen("correo","rb"))==NULL)
printf("No se puede abrir el archivo");
else
{
inicializa_lista();
for(i=0; i<TAM; i++)
if(fread(&lista[i],sizeof(struct tipo_lista),1,fp)!=1)
{
if(feof(fp)) break;
printf("Error en la lectura del archivo \n");
}
/*
fin de if
*/
fclose(fp);
}
/*
fin de else */
} /* fin de cargar
*/
/* REPORTE DE REGISTROS. Crea una imagen en disco de un reporte
void reporta(void)
{
FILE *fp;
int j;

*/

if((fp=fopen("correo.lst","w"))==NULL)
printf("No se puede abrir el archivo de salida");
else
{
fprintf(fp,"
NOMBRE
TELEFONO
CALLE
");
fprintf(fp,"
CIUDAD
EDO
CODIGO\n\n");
for(j=0; lista[j].nombre[0]; ++j)
{
fprintf(fp,"\n%-25s ",lista[j].nombre); /* - justifica a la izq */
fprintf(fp,"%-10s ",lista[j].tel);
fprintf(fp,"%-20s ",lista[j].calle);
fprintf(fp,"%-10s ",lista[j].ciudad);
fprintf(fp,"%-3s ",lista[j].estado);
fprintf(fp,"%-10s",lista[j].codigo);
}
/* fin de for
*/
}
fclose(fp);
printf("\nSe cre archivo en disco a imagen de reporte..correo.lst");
printf("\nPresione una tecla para continuar_");
getch();
} /* fin de reporte
*/

Programacin en Lenguaje C

147

Luis Hernndez Lara

Centro de Investigacin en Computacin

/*
FUNCIN BORRAR
*/
void borra(void)
{
char nombre[20];
int j,k;
clrscr();
printf("\n Teclee nombre a eliminar: ");
gets(nombre);
for(j=0; j<TAM; ++j)
{
if (strcmp(nombre, lista[j].nombre)==0)
{
printf("\n Nombre: %s", lista[j].nombre);
printf("\n Telfono: %s", lista[j].tel);
printf("\n Calle: %s", lista[j].calle);
printf("\n Ciudad: %s", lista[j].ciudad);
printf("\n Estado: %s", lista[j].estado);
printf("\n Codigo: %s", lista[j].codigo);
for(k=j; k<TAM; ++k)
lista[k]=lista[k+1];
lista[TAM]=temporal;
/*
TAM--;
*/
break;
} /* fin de if */
} /* fin de for
*/
printf("\n Presione cualquier tecla para continuar");
getch();
} /*
fin de borra
*/
/*
FUNCIN BUSCAR (ENCONTRAR)
*/
void busca(void)
{
char nombre[20];
int j;
clrscr();
printf("\n Teclee el nombre de la persona:
");
gets(nombre);
for(j=0; j<TAM; ++j)
{
if(strcmp(nombre, lista[j].nombre)==0)
{
printf("\n Nombre:%s", lista[j].nombre);
printf("\n Telfono:%s", lista[j].tel);
printf("\n Calle:%s", lista[j].calle);
printf("\n Ciudad:%s", lista[j].ciudad);
printf("\n Estado:%s", lista[j].estado);
printf("\n Codigo:%s", lista[j].codigo);
break;
} /* fin de if
*/
} /* fin de for
*/
printf("\n presione cualquier tecla para continuar");
getch();
} /* fin de busca()
*/

Programacin en Lenguaje C

148

Luis Hernndez Lara

Centro de Investigacin en Computacin

/*
MEN
*/
int menu(void)
{
char s[50];
do {
clrscr();
printf("(I)ntroducir datos en memoria\n");
printf("(M)ostrar Lista de memoria \n");
printf("(C)argar de disco a memoria \n");
printf("(S)alvar de memoria a disco \n");
printf("(R)eporte
\n");
printf("(B)orrar
\n");
printf("(E)ncontrar
\n");
printf("(T)erminar \n");
printf("Elija una opcin: ");
gets(s);
} while(!strchr("imcsrbet",tolower(*s)));
return tolower(*s);
} /* fin de men */

Programacin en Lenguaje C

149

Luis Hernndez Lara

Centro de Investigacin en Computacin

15. PROGRAMAS COMPLEMENTARIOS.


Una vez hecho un recorrido por las caractersticas y la programacin del lenguaje de
"C", procedemos a
mostrar el cdigo de algunos programas sencillos que
probablemente interesarn al lector an ms en el lenguaje.
Los ejemplos se circunscriben al alcance del texto estudiado, sin adentrarse en
caractersticas avanzadas de programacin (listas, colas, rboles, etctera), manejo de
otras capacidades como lo son las funciones grficas incluidas en muchas versiones de
"C", o tcnicas para solucin de algoritmos.
Los programas son absolutamente perfectibles, se dejan as para efecto de que el
lector los modifique o los destruya y genere sus propios programas. La intencin es
slo ilustrativa.

Programacin en Lenguaje C

150

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.1.
/*
Archivo:
Objetivo:
Funcin:

ejer151.c
Ejemplo complementario
Calcula el ms grande comn divisor de dos nmeros enteros
positivos > 0, por el mtodo de Euclides

*/
#include <stdio.h>
int mcd(int u, int v)
{
int t;
while(u>0)
{
if(u<v)
{
t = u;
u = v;
v = t;
}
u = u - v;
}
return v;
}
void main()
{
int x, y;
do{
printf("\nTeclea el primer nmero entero positivo > 0 _");
scanf("%d",&x);
printf("\nTeclea el segundo nmero entero positivo > 0 _");
scanf("%d",&y);
if(x>0 && y>0)
{
printf("\nEl m.c.d. de %d y %d es: %d\n",x,y, mcd(x,y));
}
}while (x > 0 && y > 0);
}

Programacin en Lenguaje C

151

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.2.
/*
Archivo:
Objetivo:
Funcin:

ejer152.c
Ejemplo complementario
Calcula el viaje del caballo en un tablero de ajedrez
Recorre todo el tablero sin repetir una casilla
Simula la recursividad

*/
/*
PROGRAMA RECORRIDO DEL CABALLO, ESTE PROGRAMA CONSTRUYE EL VIAJE DE UN
CABALLO DENTRO DE UN TABLERO DE AJEDREZ, USANDO LA ESTRATEGIA DE MOVIMIENTO
EN EL SENTIDO DE LAS MANECILLAS DEL RELOJ, PARA MOVERSE A UNA NUEVA
POSICIN. LA POSICIN INICIAL DEL CABALLO SE LEE DEL TECLADO. CUANDO EL
CABALLO AGOTA LAS POSIBILIDADES DE MOVIMIENTO EN 'UNA' DIRECCIN
DETERMINADA, REGRESA A LA LTIMA POSICIN DE MOVIMIENTO Y TOMA LA
SIGUIENTE ELECCIN (N-sima) PARA CONTINUAR EL RECORRIDO. EXISTE UNA PILA
QUE GUARDA LOS CUADROS (COORDENADAS) QUE HA RECORRIDO EL CABALLO, DE ESTA
MANERA SIMULA LA RECURSIVIDAD.
NOTA ADICIONAL: POR EL TIPO DE MTODO, PARA MUCHAS POSICIONES INICIALES
EL PROGRAMA PUEDE TARDARSE BASTANTE EN DAR UNA SOLUCIN
tablero[i, j]

imov[i]
jmov[j]
coordx[i]
coord[j]
tabk[k]
iinit, jinit
istack
i,j
inext, jnext
n

SE USA TABLERO DE 6x6 PARA AGILIZAR EL PROCESO.


N SIGNIFICA QUE EL CUADRO EN FILA I, COLUMNA J FUE EL
N-simo CUADRO VISITADO EN EL VIAJE DEL CABALLO.
0 (CERO) SIGNIFICA QUE EL CUADRO NO HA SIDO VISITADO.
99 SIGNIFICA QUE EL CUADRO EST FUERA DE LOS LIMITES
DEL TABLERO Y ES USADO PARA PREVENIR QUE EL CABALLO
SE MUEVA FUERA DEL TABLERO.
MOVIMIENTO DE FILA PARA LA JUGADA.
MOVIMIENTO DE COL PARA LA JUGADA.
FILA DONDE SE REALIZ JUGADA XITOSA.
COL DONDE SE REALIZ JUGADA XITOSA.
INTENTO EN EL QUE SE LOGR LA JUGADA XITOSA.
POSICIN DE ARRANQUE.
APUNTADOR A LA PILA TABK DONDE ESTA LA JUGADA ACTUAL.
LA POSICIN ACTUAL DEL CABALLO.
EL POSIBLE CUADRO A SER VISITADO A CONTINUACIN.
VALOR QUE SE LE DA A CADA CUADRO PARA CONOCER EL NUMERO
DE JUGADA.

*/
#include <stdio.h>
#include <conio.h>
/* Inicializacin de posibles movimientos del caballo para i,j */
int imove[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
int jmove[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};

Programacin en Lenguaje C

152

Luis Hernndez Lara

Centro de Investigacin en Computacin

void main()
{
int tablero[11][11];
int coordx[70],coordy[70],tabk[70];
int n, i, j, k, inext, jnext, iinit, jinit, istack;
double movs;
clrscr();
/* Selecciona la posicin inicial del caballo */
printf("\nTablero de 6x6 para que sea ms rpido */
printf("\nDame la posicion 1<=i<=6_ ");
scanf("%d",&iinit);
printf("\nDame la posicion 1<=j<=6_ ");
scanf("%d",&jinit);
iinit += 2;
jinit += 2;
/* Inicializa el tablero */
for (i=1;i<= 10;i++)
for (j=1;j<= 10;j++)
{
tablero[i][j] = 0;
if ((i < 3) || (i > 8) || (j < 3) || (j > 8))
}

tablero[i][j] = 99;

/* Inicializa variables */
k = 1;
tablero[iinit][jinit] = 1;
i = iinit;
j = jinit;
n = 2;
istack = 1;
coordx[istack] = j;
coordy[istack] = i;
tabk[istack] = k;
movs = 0;

Programacin en Lenguaje C

153

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Loop principal, y checa fin del viaje */


do{
while (k <= 8)
{/* inicio de while */
inext = i + imove[k];
jnext = j + jmove[k];
movs = movs + 1;
if (tablero[inext][jnext] != 0) k = k+1; /*se ensaya otra posicin*/
else
{ /* se marca posicin de avance vlida */
istack = istack + 1;
coordy[istack] = inext;
coordx[istack] = jnext;
tabk[istack] = k;
tablero[inext][jnext] = n;
n = n + 1;
j = jnext;
i = inext;
k = 1;
}
}/* fin while */
/* Se simula la recursividad si el caballo no se puede mover
a alguna casilla (de sus 8 posibles) por estar ocupada */
if(n <= 36)
{ /* se marca a cero (sin usar) la casilla de donde ya no se pudo
mover el caballo, y se rescata de la pila la posicin desde
donde se movio la ltima vez */
tablero[i][j] = 0;
n = n - 1;
k = tabk[istack];
istack = istack - 1;
if(istack != 0)
{
i = coordy[istack];
j = coordx[istack];
k = k + 1;
}
}
}while(n<=36 && istack > 0);
/* until (n > 36) || (istack == 0); */

Programacin en Lenguaje C

154

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Se imprime la solucin */
n = n-1;
printf("\n\n");
if(istack == 0) printf("NO HAY SOLUCIN");
else
{
for (i=3;i<=8;i++)
{
printf("\n\n");
for (j=3;j<=8;j++)
printf("
%2d",tablero[i][j]);
}
}
printf("\n\n");
printf("El nmero de movimientos fue de %.2f",movs);
getch();
}

Programacin en Lenguaje C

155

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.3.
/*
Archivo: ejer153.c
Objetivo: Ejemplo complementario
Funcin: Programa que genera bromas.
*/
#include
#include
#include
#include
#include

<stdio.h>
<conio.h>
<ctype.h>
<string.h>
<stdlib.h>

#define PER 18
#define ACC 22

/* nmero de individuos */
/* nmero de acciones */

char *persona[] = { "un sacerdote", "un vendedor de autos",


"un diputado", "un senador", "un policia",
"un bombero", "Bill Clinton", "un literato",
"un programador de computadoras", "el granjero",
"un conductor de noticiero", "un profesor de matemticas",
"un secretario de estado", "un abogado","un enterrador",
"un vendedor de autos", "un estudiante de high school",
"una modelo de televisin" }; /*18*/
char *accion[] = { "habla mucho y dice poco",
"usa lo que no le cuesta",
"piensa con los pies",
"conduce una bicicleta",
"se siente dueo del mundo",
"muestra un rostro que no tiene",
"dice verdades a medias",
"nunca resuelve un problema",
"solo lee el Esto",
"no conoce a Dios",
"opina de lo que no conoce",
"se viste de lentejuelas",
"debe usar un parche en un ojo",
"haciendo abdominales",
"comiendo sopa de letras",
"sentado en un bote de basura",
"interesado en el dinero",
"no sabe usar su arma",
"mejor que no hable",
"aprendiendo poltica",
"comiendo gorditas de chicharrn",
"estudiando Historia de Mxico"}; /*22*/

Programacin en Lenguaje C

156

Luis Hernndez Lara

Centro de Investigacin en Computacin

void main()
{
char broma[80];
int i,j;
clrscr();
randomize();
gotoxy(5,5);
puts("Escritor de bromas");
gotoxy(5,10);
puts("Quieres que escriba una broma s/n ? _ ");
gotoxy(43,10);
while(toupper(getche()) == 'S')
{
i = random (PER); /* genera nmero aleatorio entre 0 y m-1 */
strcpy(broma,persona[i]);
strcat(broma," ");
j = random (ACC);
strcat(broma,accion[j]);
gotoxy(5,15);
puts("
gotoxy(5,15);
puts(broma);
gotoxy(5,10);
puts("Quieres que escriba una broma s/n ? _
");
gotoxy(43,10);
}

");

Programacin en Lenguaje C

157

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.4.
/*
Archivo:
Objetivo:
Funcin:
0x7e
0xff
0xc3
0xc3
0xff
0xff
0xc3
0xc3
0xc3

ejer154.c
Ejemplo complementario
Convierte letras y digitos a gran tamao (matriz 9x8)
AAAAAA
AAAAAAAA
AA
AA
AA
AA
AAAAAAAA
AAAAAAAA
AA
AA
AA
AA
AA
AA

555555
55
55
55
55555555
55
55
5
55
555555

0x7e
0xc0
0xc0
0xc0
0xff
0x03
0x03
0x83
0x7e

*/
#include <conio.h>
#include <stdio.h>
#define ELEMEN 37
void imprime(char );

/* prototipo de funcin */

/* definicion del patrn de */


int patron[ELEMEN][9]={
/* letras y numeros
{0x7e, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
{0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
{0x7e, 0xc3, 0x03, 0x1e, 0x30, 0x60, 0xc0, 0xc0,
{0x7e, 0xc3, 0x03, 0x1e, 0x03, 0x03, 0x03, 0xc3,
{0x06, 0x0e, 0x1e, 0x36, 0x66, 0xff, 0x06, 0x06,
{0x7e, 0xc0, 0xc0, 0xc0, 0xff, 0x03, 0x03, 0x83,
{0x7e, 0xc3, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3,
{0xff, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
{0x7e, 0xc3, 0xc3, 0x7e, 0xc3, 0xc3, 0xc3, 0xc3,
{0x7e, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0xc3,
{0x7e, 0xff, 0xc3, 0xc3, 0xff, 0xff, 0xc3, 0xc3,
{0xfe, 0xc3, 0xc3, 0xc3, 0xfe, 0xc3, 0xc3, 0xc3,
{0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc3,
{0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
{0xff, 0xff, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xff,
{0xff, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0,
{0x7e, 0xc3, 0xc0, 0xc0, 0xce, 0xc3, 0xc3, 0xc3,
{0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3,
{0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
{0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8,
{0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6,
{0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
{0xc3, 0xe7, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3,
{0x83, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3,
{0x7d, 0xc2, 0xc7, 0xcb, 0xdb, 0xdb, 0xe3, 0x43,
{0xfe, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0,
{0x7e, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xcb, 0xc6,
{0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xcc, 0xc6,

Programacin en Lenguaje C

158

*/
0x7e},
0xff},
0xff},
0x7e},
0x06},
0x7e},
0x7e},
0x80},
0x7e},
0x7e},
0xc3},
0xfe},
0x7e},
0xfe},
0xff},
0xc0},
0x7e},
0xc3},
0xff},
0x70},
0xc3},
0xff},
0xc3},
0xc3},
0xbc},
0xc0},
0x7d},
0xc3},

/* 0 */
/* 1 */

/* 5 */

/* 9 */
/* A */
/* B */

/* R */

Luis Hernndez Lara

Centro de Investigacin en Computacin

{0x7f,
{0xff,
{0xc3,
{0xc3,
{0xc3,
{0xc3,
{0xc3,
{0xff,
{0x00,

0xff,
0x18,
0xc3,
0xc3,
0xc3,
0x42,
0x42,
0x03,
0x00,

0xc0,
0x18,
0xc3,
0x66,
0xc3,
0x66,
0x66,
0x06,
0x00,

0xc0,
0x18,
0xc3,
0x66,
0xdb,
0x3c,
0x3c,
0x0c,
0x00,

0x7e,
0x18,
0xc3,
0x66,
0xdb,
0x18,
0x18,
0x18,
0x00,

0x3f,
0x18,
0xc3,
0x66,
0xe7,
0x3c,
0x18,
0x30,
0x00,

0x03,
0x18,
0xc3,
0x24,
0xe7,
0x66,
0x18,
0x60,
0x00,

0xff,
0x18,
0x7e,
0x18,
0xc3,
0x42,
0x18,
0xc0,
0x00,

0xfe},
0x18},
0x3c},
0x18},
0x81},
0xc3},
0x18},
0xff},
0x00},

/* Y */
/* Z */
/* blanco */

};
void main()
{
char caracter;
clrscr();
printf("\nTeclee la letra a desplegar: ");
caracter = getchar();
/* detecta invlidos diferentes a numeros y letras*/
if(caracter >=97 && caracter <=122) caracter -= 32;
/* minsculas */
else
/* a maysculas */
if(caracter <48 || caracter >122) caracter = ' '; /* invlidos */
else
/* a blancos */
if(caracter > 57 && caracter < 65 ||
caracter > 90 && caracter < 97) caracter = ' ';
imprime(caracter);
printf("\nPara terminar oprima cualquier tecla _");
getch();
}
/* Funcin que crece e imprime el carcter */
void imprime(char caract)
{
register int i, j;
int scan;
char caract2;
caract2 = caract; /* para rescatar el carcter original */
if(caract == 27) caract += 9;
/* detecta blancos */
if(caract >= 48 && caract <= 57) caract -=48; /* detecta digito */
if(caract >= 65 && caract <= 90) caract -=55; /* detecta letras */
/* compara bit por bit el carcter leido vs el patrn requerido */
for(i=0;i<9;i++)
{
scan = 0x80 ;
for( j = 0 ; j < 8 ; j++)
{ patron[caract][i] & scan ? printf("%c",caract2) : printf(" ");
scan >>= 1;
}
printf("\n");
}
}

Programacin en Lenguaje C

159

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.5.
/*
Archivo:
Objetivo:
Funcin:

ejer155.c
Ejemplo complementario
Programa para calcular cuadros magicos de hasta 15x15.
Sumatoria de valores de filas, columnas y
diagonales principal y secundaria es el mismo

*/
#include <stdlib.h>
#include <stdio.h>
#define MAX 16
void lectura(int *numero);
void pro_cuadro(int numero);
void imprime(int numero);
int cuadro[MAX][MAX];
void main()
{
char cond;
int numero;
cond = 's';
while(cond == 's')
{
lectura(&numero);
pro_cuadro(numero);
imprime(numero);
gotoxy(35,23);
printf("Si desea calcular otro cuadro teclee
cond = getch();
}
}

Programacin en Lenguaje C

160

's': ");

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que lee el grado del cuadro */


void lectura(int *numero)
{
int num = -1;
long int i;
while(num < 1 || num > MAX-1 || num%2 == 0)
{
clrscr();
gotoxy(27,2);
printf("*** CUADROS MAGICOS ***");
gotoxy(19,10);
printf("TECLEE EL GRADO DEL CUADRO A CALCULAR = ");
scanf("%i",&num);
gotoxy(20,23);
if(num%2 == 0)
printf("*ERROR* EL GRADO DEBE SER IMPAR");
else
{
gotoxy(10,23);
if(num < 1 || num > MAX-1)
printf("*ERROR* EL GRADO ESTA FUERA DE RANGO, DEBE SER DE 1 A 15");
}
for(i=0;i<=30000000;i++);
*numero = num;
}
}
/* Funcin que calcula el cuadro mgico */
void pro_cuadro(int numero)
{
int i,j,valor;
valor = 1;
for(i=0;i<MAX;i++)
for(j=0;j<MAX;j++) cuadro[i][j] = 0;
i = 1;
j = numero / 2 + 1;

/* PRIMER VALOR EN LA TABLA */


/* CALCULA POSICIN DE
/* INICIO

*/
*/

while(valor <= numero*numero)


{
if(cuadro[i][j] == 0)
{
cuadro[i][j] = valor;
valor += 1;
i -= 1;
j -= 1;
if(i <= 0) i = numero;
if(j <= 0) j = numero;
}
else
{
i += 2;
j += 1;
if(i > numero) i -= numero;
if(j > numero) j -= numero;
}
}/* fin de while */
}

Programacin en Lenguaje C

161

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que imprime el cuadro calculado */


void imprime(int numero)
{
int i,j,fil,col,m=223,n=219;
clrscr();
gotoxy(22,2);
printf("*** CUADRO MGICO DE GRADO %2i ***",numero);
col = (80 - (numero * 4)) / 2;
fil = (28 - numero) / 2;
gotoxy(col-1,fil-1);
for(i=col-1;i<=col+(numero*4-1);i++) printf("%c",m-3);
for(i=1;i<=numero;i++)
{
gotoxy(col-1,fil);
printf("%c",n);
gotoxy(col,fil++);
for(j=1;j<=numero;j++)
printf("%3i ",cuadro[i][j]);
gotoxy(col+(numero*4-1),fil-1);
printf("%c",n);
}
gotoxy(col-1,fil);
for(i=col-1;i<=col+(numero*4-1);i++) printf("%c",m);
}

Programacin en Lenguaje C

162

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.6.
/*
Archivo: ejer156.c
Objetivo: Ejemplo complementario
Funcin: Convierte una cantidad en pesos y centavos a su equivalente
en letras
*/
#include <dos.h>
#include <stdlib.h>
char unidades[][13] =
{"cero","un","dos","tres","cuatro","cinco","seis","siete",
"ocho","nueve","diez","once","doce","trece","catorce",
"quince","dieciseis","diecisiete","dieciocho",
"diecinueve","veinte","veintiuno","veintidos",
"veintitres","veinticuatro","veinticinco","veintiseis",
"veintisiete","veintiocho","veintinueve"};
char decenas[][10] = {"","","","treinta","cuarenta","cincuenta",
"sesenta","setenta","ochenta","noventa"};
char centenas[][14] = {"","ciento","doscientos","trescientos","cuatrocientos",
"quinientos","seiscientos","setecientos","ochocientos",
"novecientos"};
/* Prototipos de funcin */
void lee(long *, long *);
void cambia_a_letras(long);
void millones(int, int, int);
void miles(int, int, int);
void cientos(int, int, int);
void pesos(long );
void centavos(long);
void main()
{
long entero,decimal;
lee(&entero,&decimal);
while(entero >= 0 && decimal >= 0)
{
cambia_a_letras(entero);
pesos(entero);
cambia_a_letras(decimal);
centavos(decimal);
lee(&entero,&decimal);
}
} /* fin de main */

Programacin en Lenguaje C

163

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que lee la cantidad */


void lee(long *entero, long *decimal)
{
printf("\nPara salir teclee una cantidad negativa");
printf("\nDe una cantidad (mximo 999999999.99) : $");
scanf("%ld%*c%ld",entero,decimal);
}
/* Funcin determina los digitos activos de la cantidad */
void cambia_a_letras(long x)
{
int cml, dml, uml, cm, dm, um, c, d, u;
cml=x/100000000;
dml=(x%100000000)/10000000;
uml=((x%100000000)%10000000)/1000000;
cm =(((x%100000000)%10000000)%1000000)/100000;
dm =((((x%100000000)%10000000)%1000000)%100000)/10000;
um =(((((x%100000000)%10000000)%1000000)%100000)%10000)/1000;
c =((((((x%100000000)%10000000)%1000000)%100000)%10000)%1000)/100;
d =(((((((x%100000000)%10000000)%1000000)%100000)%10000)%1000)%100)/10;
u =(((((((x%100000000)%10000000)%1000000)%100000)%10000)%1000)%100)%10;
millones(cml,dml,uml);
miles(cm,dm,um);
cientos(c,d,u);
}
/* Funcin que evala si el nmero est en el rango de miles */
void miles(int c,int d, int u)
{
if(c || d || u)
{
if(c) printf("%s ",centenas[c]);
if((d*10+u)<30) printf("%s ",unidades[d*10+u]);
else
if(d)
{ printf("%s ",decenas[d]);
if(u) printf("y %s ",unidades[u]);
}
else
if(u) printf("%s ",unidades[u]);
printf("mil ");
}
}

Programacin en Lenguaje C

164

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que evala si el nmero es > 1 y menor a 100 o


si est entre 100 y 999 */
void cientos(int c,int d, int u)
{
if(c || d || u)
{
/* El caso cien sin decenas ni unidades */
if (c==1 && d==0 &&u==0) printf 8"cien");
else
if(c) printf("%s ",centenas[c]);
/* calcula si esta entre 1 y 29 */
if((d*10+u)> 0 && (d*10+u)<30 ) printf("%s ",unidades[d*10+u]);
else
if(d)
{ printf("%s ",decenas[d]);
if(u) printf("y %s ",unidades[u]);
}
else
if(u) printf("%s ",unidades[u]);
}
}
/* Funcin que evala si hay millones */
void millones(int c,int d, int u)
{
if(c || d || u)
{
if(c) printf("%s ",centenas[c]);
if((d*10+u)<30) printf("%s ",unidades[d*10+u]);
else
if(d)
{ printf("%s ",decenas[d]);
if(u) printf("y %s ",unidades[u]);
}
else
if(u) printf("%s ",unidades[u]);
if(!c && !d && u == 1) printf("milln");
else printf("millones ");
}
}
/* Funcin que imprime la leyenda de pesos (para la parte entera) */
void pesos(long x)
{
if(x > 1) printf("pesos ");
else
if(x==1) printf("peso ");
else
if(x==0) printf("%s pesos ",unidades[0]);
}

Programacin en Lenguaje C

165

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* Funcin que imprime la leyenda de centavos (para la parte fraccionaria),


termina la cantidad */
void centavos(long y)
{
if (y > 1) printf("centavos 00/100 m.n.");
else
if(y == 1) printf("centavo 00/100 m.n.");
else
if(y == 0) printf("%s centavos 00/100 m.n.",unidades[0]);
}

Programacin en Lenguaje C

166

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercico 15.7.
Si usted tiene inquietud sobre grficos, le presentamos un programa que hace uso de la
biblioteca de Turbo C++, para graficar en modo pantalla de texto.
/*
Archivo: ejer157.c
Objetivo: Ejemplo complementario
Funcin: Programita que mueve una pelotita en la pantalla
En turbo c++ 3.0 activar men, para disponer de la biblioteca
Options->Linker->Libraries->Graphics Libraries
*/
#include
#include
#include
#include
#include

<stdio.h>
<alloc.h>
<graphics.h>
<conio.h>
<stdlib.h>

void main(void)
{
int graphdriver = DETECT, graphmode, errcode;
char far *image;
short x, y, ruta;
unsigned numbytes;
randomize();
/*initgraph(&graphdriver, &graphmode, "c:\\tc\\bgi");*/
initgraph(&graphdriver, &graphmode, "");
ellipse(5,5,0,360,5,5);
setcolor(YELLOW);
setfillstyle(SOLID_FILL,YELLOW);
floodfill(5,5,WHITE);
numbytes = (unsigned int) imagesize(0,0,10,30);
if((image = (char far *) malloc(numbytes)) == (char far *)NULL)
{
closegraph();
printf("No hay memoria para la grfica\n");
getch();
exit(0);
}
getimage(0,0,10,30,image);
cleardevice();
setcolor(WHITE);
x = getmaxx()/2;
y = getmaxy()/2;
ruta = 1; /* 1 arrder, 2 abder, 3 abizq, 4 ariz */
putimage(x,y,image,XOR_PUT);

Programacin en Lenguaje C

167

Luis Hernndez Lara

Centro de Investigacin en Computacin

/* ciclo infinito de movimiento */


for(;;)
{
putimage(x,y,image,XOR_PUT);
switch(ruta){
case 1: if(x >= getmaxx()) ruta = 4, x+=rand() % 3, y-=rand() % 3;
else
if(y <= 0) ruta = 2, x+=rand() % 3, y-=rand() % 3;
else x+=1, y-=1;
break;
case 2: if(x >= getmaxx()) ruta = 3, x+=rand() % 3,y+=rand() % 3;
else
if(y >= getmaxy()) ruta = 1, x+=rand() % 3,y+=rand() % 3;
else x+=1, y+=1;
break;
case 3: if(x <= 0) ruta = 2, x-=rand() % 3,y+=rand() % 3;
else
if(y >= getmaxy()) ruta = 4, x-=rand() % 3,y+=rand() % 3;
else x-=1, y+=1;
break;
case 4: if(x <= 0) ruta = 1, x-=rand() % 3,y-=rand() % 3;
else
if(y <= 0) ruta = 3, x-=rand() % 3,y-=rand() % 3;
else x-=1, y-=1;
break;
}
putimage(x,y,image,XOR_PUT);
if(kbhit()) break;
}
closegraph();
}

Programacin en Lenguaje C

168

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.8.
/*
Archivo:
Objetivo:
Funcin:
*/
#include
#include
#include
#include

ejer158.c
Ejemplo complementario
Graficar funciones predefinidas

<stdio.h>
<conio.h>
<math.h>
<alloc.h>

float x[100],y[100];
float xmax,xmin,ymax,ymin;
float tetapaso,increm;
int n;
float teta;
void
void
void
void
void
void
void
void
void
void

lectura(float *);
encabeza(char *);
maxmin();
grafica(int , int );
rosa();
hipo();
card();
espi();
cara();
seno();

void main()
{
float tetaini,tetafin;
int i,num,npx,npy;
char op;

/* programa para graficar */


/* funciones predefinidas */

npx = 24;
/* puntos en x */
n = npy = 80;
/* puntos en y */
op = '0';
while (op != '9')
{
encabeza(&op);
num = op - '0';
if(num > 0 && num < 7)
{
clrscr();
printf("\nDAME EL NMERO DE GRADOS INICIAL = ");
lectura(&teta);
tetaini = teta / 57.3;

Programacin en Lenguaje C

169

Luis Hernndez Lara

Centro de Investigacin en Computacin

printf("\nDAME EL NMERO DE GRADOS FINAL


lectura(&teta);
tetafin = teta / 57.3;
tetapaso = tetaini;
increm = (tetafin - tetaini) / (n-1);
if(tetaini == 0 && tetafin == 0) exit(0);
switch(op)
{
case '1':
rosa();
break;
case '2':
hipo();
break;
case '3':
card();
break;
case '4':
espi();
break;
case '5':
cara();
break;
case '6':
seno();
break;
default :
break;
}
maxmin();
grafica(npx,npy);
}

= ");

}
getch();
} /* fin de main */
void lectura(float *teta)
{
char s[5];
int h;
for(h=0;h<=5;h++) s[h] = ' ';
gets(s);
*teta = atof(s);
} /* fin de lectura */

Programacin en Lenguaje C

170

Luis Hernndez Lara

Centro de Investigacin en Computacin

void encabeza(char *op)


{
clrscr();
printf("\n-----------------------------------------------------");
printf("\nPROGRAMA PARA GRAFICAR FUNCIONES PREDEFINIDAS
-");
printf("\n-----------------------------------------------------");
printf("\n-");
printf("\nELIJA LA OPCIN DESEADA
-");
printf("\n-----------------------------------------------------");
printf("\n");
printf("\n
ROSA DE TRES PTALOS
=====> 1");
printf("\n
HIPOCICLOIDE
=====> 2");
printf("\n
CARDIOIDE
=====> 3");
printf("\n
ESPIRAL DE ARQUMIDES
=====> 4");
printf("\n
CARACOL DE PASCAL
=====> 5");
printf("\n
SENO
=====> 6");
printf("\n
FIN DE PROGRAMA
=====> 9");
printf("\n\n\n
Teclee la opcion: ");
*op = getch();
} /* fin de encabeza */
void maxmin()
{
int ind;
ymax = ymin = y[1];
xmax = xmin = x[1];
for(ind=1;ind<=n;ind++)
{
if (ymax < y[ind])
if (y[ind] < ymin)
}
for(ind=1;ind<=n;ind++)
{
if (xmax < x[ind])
if (x[ind] < xmin)
}
} /* fin de maxmin */

Programacin en Lenguaje C

ymax = y[ind];
ymin = y[ind];

xmax = x[ind];
xmin = x[ind];

171

Luis Hernndez Lara

Centro de Investigacin en Computacin

void grafica(int nx, int ny)


{
char matriz[100][100];
int ii,jj,col,fil,jx,jy;
for (ii=0;ii<=nx;ii++)
for (jj=0;jj<=ny;jj++) matriz[ii][jj] = ' ';
if (xmax*xmin <= 0)
{
jy = (-xmin) / (xmax - xmin) * (nx-2) + 1;
for(ii=1;ii<ny;ii++)
matriz[jy][ii] = 'Y';
}
if (ymax*ymin <= 0)
{
jx = (-ymin) / (ymax - ymin) * (ny-2) + 1;
for(ii=1;ii<nx;ii++)
matriz[ii][jx] = 'X';
}
for (ii=1;ii<ny;ii++)
{
col = (y[ii] - ymin) / (ymax - ymin) * (ny-2) + 1;
fil = (x[ii] - xmin) / (xmax - xmin) * (nx-2) + 1;
matriz[fil][col] = '*';
}
clrscr();
for (ii=1;ii<nx;ii++)
{
for (jj=1;jj<ny;jj++) printf("%c",matriz[ii][jj]);
printf("\n");
}
getch();
} /* fin de grfica */
void rosa()
{
int k;
float rad;
for(k=1;k<=n;k++)
{
rad = sin(3 * tetapaso);
x[k] = rad * cos(tetapaso);
y[k] = rad * sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de rosa */

Programacin en Lenguaje C

172

Luis Hernndez Lara

Centro de Investigacin en Computacin

void hipo()
{
char ss[5];
int k;
float a;
gotoxy(10,16);
printf("DAME EL RADIO DE
.a. = ");
gets(ss);
a = atof(ss);
for(k=1;k<=n;k++)
{
x[k] = a * cos(tetapaso) * cos(tetapaso) * cos(tetapaso);
y[k] = a * sin(tetapaso) * sin(tetapaso) * sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de hipo */
void card()
{
int k;
float rad;
for(k=1;k<=n;k++)
{
rad = 1 * (1 + cos(tetapaso));
x[k] = rad * cos(tetapaso);
y[k] = rad * sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de card */
void espi()
{
int k;
float rad;
for(k=1;k<=n;k++)
{
rad = 1 * tetapaso;
x[k] = rad * cos(tetapaso);
y[k] = rad * sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de espi */

Programacin en Lenguaje C

173

Luis Hernndez Lara

Centro de Investigacin en Computacin

void cara()
{
char ss[5];
int k;
float a,b;
float rad;
gotoxy(10,16);
printf("DAME EL DIMETRO DE
.a. =
gets(ss);
a = atof(ss);
gotoxy(10,18);
printf("DAME LA LONGITUD DE
.b. =
gets(ss);
b = atof(ss);
for(k=1;k<=n;k++)
{
rad = b + (a * cos(tetapaso));
x[k] = rad * cos(tetapaso);
y[k] = rad * sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de cara */

");

");

void seno()
{
int k;
for(k=1;k<=n;k++)
{
x[k] = tetapaso;
y[k] = sin(tetapaso);
tetapaso = tetapaso + increm;
}
} /* fin de seno */

Programacin en Lenguaje C

174

Luis Hernndez Lara

Centro de Investigacin en Computacin

Ejercicio 15.9.
/*
Archivo:
Objetivo:
Funcin:
*/

ejer159.c
Ejemplo complementario
Calcular la integral de una funcin por la regla trapezoidal

#include<stdio.h>
#include<conio.h>
#define f(x) x*x

/* define la funcin

/* PROTOTIPOS DE FUNCIN

*/

x2 */

float funcion(float x);


/* FUNCION MAIN

*/

void main(void)
{
float integral;
float a,b;
int n;
float h;

/*
/*
/*
/*

rea bajo la curva */


Limites inferior y superior */
Nmero de trapecios */
Ancho de cada trapecio */

float x;
int i;
printf("\nTeclea el lmite inferior
-a- : ");
scanf("%f",&a);
printf("\nTeclea el lmite superior
-b- : ");
scanf("%f",&b);
printf("\nTeclea el nmero de trapecios -n- : ");
scanf("\n%d",&n);
h = (b-a)/n;
x= a;
for(i=2;i<=n;i++)
{
x+=h;
integral+=funcion(x);
}
integral += (funcion(a)+funcion(b))/2.0;
integral*=h;
printf("\nLa solucin con %d trapecios, desde %f hasta %f es : %f",
n,a,b,integral);
getch();
} /* fin de main */

Programacin en Lenguaje C

175

Luis Hernndez Lara

Centro de Investigacin en Computacin

float funcion(float x)
{
float retorno;
retorno = f(x);
return retorno;
}

Programacin en Lenguaje C

176

Luis Hernndez Lara

Centro de Investigacin en Computacin

BIBLIOGRAFA.

1. [Aho, 1983] A. V., et al. Data Structures and Algorithms. Massachusetts, E.U.A.,
Addison-Wesley.
2. [Barkakati, 1990] Naba. Turbo C++ Bible. Indiana, E.U.A., SAMS-The Waite Group,
Inc.
3. [Galve, 1993] Frances J., et al. Algortmica, diseo y anlisis de algoritmos
imperativos. Wilmington, Delaware, E.U.A., Addison-Wesley Iberoamericana, S.A.
4. [Kernighan, 1988] Brain W., Ritchie, Dennis M. The C Programming Language.
Englewoods Cliffs, New Jersey, E.U.A., Prentice-Hall.
5. [Sethi, 1996] Ravi. Programming Languages: Concepts and Constructs. New
Jersey, E.U.A., Addison-Wesley Publishing Co.
6. [Schildt, 1995] Herbert. C Manual de Referencia. Madrid, Espaa, McGrawHill/Interamericana de Espaa, S.A., Madrid, Espaa, 3. Ed.
7. Secretariat: Standard - The C Language. X3J11/90-013. Computer and Business
Equipment Manufactures Association, 311 First Street, NW, Suite 500, Washington,
DC 2001, U.S.A.

Programacin en Lenguaje C

177

Luis Hernndez Lara

Anda mungkin juga menyukai