Manual C
Manual C
POLITÉCNICA
DE CARTAGENA
FUNDAMENTOS DE INFORMÁTICA.
PROGRAMACIÓN EN C.
Pedro María Alcover Garau
Ingeniero Industrial
Ingeniero Técnico Industrial
FUNDAMENTOS DE INFORMÁTICA.
PROGRAMACIÓN EN C.
Pedro María Alcover Garau
Septiembre, 2005
© Pedro María Alcover Garau
ISBN: 84–95781–61–1
Seguro que quien haga uso de este manual detectará errores y erratas.
También apreciará modos de decir que podrían mejorarse, y que
ofrecerían una mayor claridad de exposición.
Agradeceré recibir todas las sugerencias, porque así se podrá ofrecer, a
quienes vengan detrás, una versión del manual mejorada. Se puede
contactar conmigo a través del correo electrónico. Mi dirección es
[email protected].
Muchas gracias.
CAPÍTULO 1
LENGUAJE C. 5
Introducción 5
Entorno de programación. 7
Estructura básica de un programa en C. 9
Elementos léxicos 12
Sentencias simples y sentencias compuestas 13
Errores y depuración 14
Recapitulación 15
El entorno de Borland C++ 15
CAPÍTULO 2
TIPOS DE DATOS Y VARIABLES EN C 19
Declaración de variables. 20
Tipos de datos primitivos en C: sus dominios. 22
Tipos de datos primitivos en C: sus operadores. 25
Operador asignación. 26
Operadores aritméticos. 27
Operadores relacionales y lógicos. 30
Operadores a nivel de bit. 34
i
Operadores compuestos. 39
Operador sizeof 40
Expresiones en las que intervienen variables de diferente
tipo. 41
Operador para forzar cambio de tipo. 43
Propiedades de los operadores. 45
Valores fuera de rango en una variable. 48
Constantes. Directiva #define. 50
Intercambio de valores de dos variables. 51
Ayudas On line. 52
Recapitulación 52
Ejemplos y Ejercicios propuestos (del 1 al 15) 53
CAPÍTULO 3
FUNCIONES DE ENTRADA Y SALIDA POR
CONSOLA 65
Salida de datos. La función printf() 66
Entrada de datos. La función scanf() 74
Recapitulación 76
Ejercicios (del 16 al 19) 77
ANEXO: Ficha resumen de la función printf() 83
CAPÍTULO 4
ESTRUCTURAS DE CONTROL 87
Introducción 87
Conceptos previos 89
Estructuras de control condicionales 90
Estructura de selección múltiple: Sentencia switch 97
Un ejercicio planteado. 101
Estructuras de repetición. Iteración. 104
Sentencias de salto: break y continue 116
Palabra reservada goto 120
Variables de control de las iteraciones 120
Recapitulación. 122
Ejercicios. (del 20 al 39) 122
ii
CAPÍTULO 5
ÁMBITO Y VIDA DE LAS VARIABLES 147
Ámbito y Vida. 147
El almacenamiento de las variables en la memoria. 148
Variables Locales y Variables Globales 150
Variables estáticas y dinámicas. 154
Variables en registro. 156
Variables extern 157
En resumen… 158
Ejercicios (40) 160
CAPÍTULO 6
ARRAYS NUMÉRICOS: VECTORES Y MATRICES 163
Noción y declaración de array. 164
Noción y declaración de array de dimensión múltiple, o
matrices. 166
Ejercicios (del 41 al 47) 169
CAPÍTULO 7
CARACTERES Y CADENAS DE CARACTERES 181
Operaciones con caracteres. 182
Entrada de caracteres. 185
Cadena de caracteres. 186
Dar valor a una cadena de caracteres. 188
Operaciones con cadenas de caracteres. 191
Otras funciones de cadena. 196
Ejercicios. (del 48 al 51) 199
CAPÍTULO 8
PUNTEROS 203
Definición y declaración 204
Dominio y operadores para los punteros 205
Punteros y vectores 209
Índices y operatoria de punteros 212
iii
Puntero a puntero 215
Advertencia final 219
Ejercicios. (del 52 al 53) 221
CAPÍTULO 9
FUNCIONES 223
Definiciones 224
Funciones en C 227
Declaración de la función. 228
Definición de la función. 230
Llamada a la función 232
La sentencia return 233
Ámbito y vida de las variables 236
Recurrencia 239
Llamadas por valor y llamadas por referencia 243
Vectores y matrices como argumentos 246
Funciones de escape 249
Ejercicios. (del 54 al 63) 250
CAPÍTULO 10
ASIGNACIÓN DINÁMICA DE MEMORIA 277
Función malloc 279
Función free 283
Ejemplo: la Criba de Erastóthenes. (Ejercicio 64) 283
Matrices en memoria dinámica 288
Ejercicios. (65) 292
CAPÍTULO 11
ALGUNOS USOS CON FUNCIONES 299
Punteros a funciones 300
Vectores de punteros a funciones 303
iv
Funciones como argumentos 305
Ejemplo: la función qsort 308
Estudio de tiempos 312
Creación de MACROS 315
Ejemplo de MACRO: la Criba de Erastóthenes 316
Funciones con un número variable de argumentos 320
Argumentos de la línea de órdenes 325
Ejercicios. (del 66 al 67) 328
CAPÍTULO 12
ESTRUCTURAS ESTÁTICAS DE DATOS Y
DEFINICIÓN DE TIPOS 329
Tipos de dato enumerados 330
Dar nombre a los tipos de dato 331
Estructuras de datos y tipos de dato estructurados 333
Estructuras de datos en C 334
Vectores y punteros a estructuras 339
Anidamiento de estructuras 341
Tipo de dato union 344
Ejercicios. (68) 348
CAPÍTULO 13
GESTIÓN DE ARCHIVOS 353
Tipos de dato con persistencia 354
Archivos y sus operaciones 356
Archivos de texto y binarios 359
Tratamiento de archivos en el lenguaje C 359
Archivos secuenciales con buffer. 361
Entrada y salida sobre archivos de acceso aleatorio 373
Ejercicios. (del 69 al 70) 375
v
vi
PARTE I:
Primeros pasos
en lenguaje C.
Fundamentos de informática. Programación en Lenguaje C
2
PARTE I: Primeros pasos en lenguaje C.
3
Fundamentos de informática. Programación en Lenguaje C
4
CAPÍTULO 1
LENGUAJE C.
Introducción.
Los lenguajes de programación están especialmente diseñados para
programar computadoras. Sus características fundamentales son:
6
Capítulo 1. Lenguaje C.
Entorno de programación.
Para realizar la tarea de escribir el código de una aplicación en un
determinado lenguaje, y poder luego compilar y obtener un programa
que realiza la tarea planteada, se dispone de lo que se denomina un
entorno de programación.
7
Fundamentos de informática. Programación en Lenguaje C.
8
Capítulo 1. Lenguaje C.
Obtención del
programa Enlace
ejecutable (.exe)
Sí Errores de No
ejecución
Programas Archivos de
objeto del biblioteca (.lib)
Figura 1.1.: Fases de F
usuario
desarrollo de un programa
9
Fundamentos de informática. Programación en Lenguaje C.
#include <stdio.h>
/* Este es un programa en C. */
// Imprime un mensaje en la pantalla del ordenador
void main(void)
{
printf(“mi primer programa en C”);
}
10
Capítulo 1. Lenguaje C.
11
Fundamentos de informática. Programación en Lenguaje C.
Elementos léxicos.
Entendemos por elemento léxico cualquier palabra válida en el
lenguaje C. Serán elementos léxicos, o palabras válidas, todas aquellas
palabras que formen parte de las palabras reservadas del lenguaje, y
todas aquellas palabras que necesitemos generar para la redacción del
programa, de acuerdo con una normativa sencilla.
12
Capítulo 1. Lenguaje C.
13
Fundamentos de informática. Programación en Lenguaje C.
Errores y depuración.
No es extraño que, al terminar de redactar el código de un programa, al
iniciar la compilación, el compilador deba abortar su proceso y avisar de
que existen errores. El compilador ofrece algunos mensajes que
clarifican frecuentemente el motivo del error, y la corrección de esos
errores no comporta habitualmente demasiada dificultad. A esos errores
sintácticos los llamamos errores de compilación. Ejemplo de estos
errores pueden ser que se haya olvidado terminar una sentencia con el
punto y coma, o que falte una llave de cierre de bloque de sentencias
compuestas, o sobre un paréntesis, o se emplee un identificador mal
construido…
14
Capítulo 1. Lenguaje C.
Recapitulación.
En este capítulo hemos introducido los conceptos básicos iniciales para
poder comenzar a trabajar en la programación con el lenguaje C. Hemos
presentado el entorno habitual de programación y hemos visto un
primer programa en C (sencillo, desde luego) que nos ha permitido
mostrar las partes básicas del código de un programa: las directivas de
preprocesador, los comentarios, la función principal, las sentencias
(simples o compuestas) y las llaves que agrupan sentencias. Y hemos
aprendido las reglas básicas de creación de identificadores.
15
Fundamentos de informática. Programación en Lenguaje C.
16
Capítulo 1. Lenguaje C.
Para compilar y ejecutar basta con elegir la opción Menú Debug Æ Run
o, como indica esa misma opción, pulsar simultáneamente las teclas
Control y F9. Una tercera opción es pulsar el botón en forma de rayo
amarillo situado en la sexta posición de la barra de botones.
17
Fundamentos de informática. Programación en Lenguaje C.
18
CAPÍTULO 2
TIPOS DE DATOS Y VARIABLES EN C
Un tipo de dato puede ser tan complejo como se quiera. Puede necesitar
un byte para almacenar cualquier valor de su dominio, o requerir de
muchos bytes.
Declaración de variables.
Antes de ver los tipos de dato primitivos, conviene saber cómo se crea
una variable en C.
20
Capítulo 2. Tipos de datos y variables en C.
21
Fundamentos de informática. Programación en Lenguaje C
RANGO DE VALORES
TIPOS SIGNO MENOR MAYOR
22
Capítulo 2. Tipos de datos y variables en C.
23
Fundamentos de informática. Programación en Lenguaje C
Una variable declarada como de tipo long se entiende que es long int.
Y una variable declarada como de tipo short, se entiende que es short
int. Muchas veces se toma como tipo de dato únicamente el modificador
de tamaño, omitiendo la palabra clave int.
Los restantes tipos de dato se definen para codificar valores reales. Hay
que tener en cuenta que el conjunto de los reales es no numerable
(entre dos reales siempre hay un real y, por tanto, hay infinitos reales).
Los tipos de dato que los codifican ofrecen una codificación finita sí
numerable. Esos tipos de dato codifican subconjuntos del conjunto de
los reales; subconjuntos que, en ningún caso, pueden tomarse como un
intervalo del conjunto de los reales.
24
Capítulo 2. Tipos de datos y variables en C.
25
Fundamentos de informática. Programación en Lenguaje C
Operador asignación.
El operador asignación permite al programador modificar los valores de
las variables y alterar, por tanto, el estado de la memoria del ordenador.
nombre_variable = expresión;
a = a + 1;
26
Capítulo 2. Tipos de datos y variables en C.
LValue = RValue;
Donde Lvalue sólo puede ser el nombre de una variable, y nunca una
expresión, ni un literal. Expresiones como a + b = c; ó 3 = variable; son
erróneas, pues ni se puede cambiar el valor del literal 3 que, además,
no está en memoria porque es un valor literal; ni se puede almacenar
un valor en la expresión a + b, porque los valores se almacenan en
variables, y a + b no es variable alguna.
Operadores aritméticos.
Los operadores aritméticos son:
27
Fundamentos de informática. Programación en Lenguaje C
Supongamos la expresión
28
Capítulo 2. Tipos de datos y variables en C.
29
Fundamentos de informática. Programación en Lenguaje C
a = b + ++c;
30
Capítulo 2. Tipos de datos y variables en C.
a > b + 2;
x + y == z + t;
31
Fundamentos de informática. Programación en Lenguaje C
Los operadores lógicos son: AND, cuyo identificador está formado por el
carácter repetido “&&”; OR, con el identificador “||”; y el operador
negación, cuyo identificador es el carácter de admiración final (‘!’).
a b a && b a || b !a
F F F F V
F V F V V
V F F V F
V V V V F
32
Capítulo 2. Tipos de datos y variables en C.
float pi = 3.141596;
long x = 0, y = 100, z =1234;
33
Fundamentos de informática. Programación en Lenguaje C
34
Capítulo 2. Tipos de datos y variables en C.
Por ejemplo, y antes de seguir con los otros tres operadores a nivel
de bit, supongamos que tenemos el siguiente código:
unsigned short int a = 0xABCD, b = 0x6789;
unsigned short int a_and_b = a & b;
unsigned short int a_or_b = a | b;
unsigned short int a_xor_b = a ^ b;
35
Fundamentos de informática. Programación en Lenguaje C
and or xor
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0
36
Capítulo 2. Tipos de datos y variables en C.
En el siguiente código
unsigned short int var1 = 12;
unsigned short int d = 1;
unsigned short int var2 = var1 << d;
var2 será el doble que var1, es decir, 24. Y si d hubiera sido igual a
2, entonces var2 sería cuatro veces var1, es decir, 48. Y si d hubiera
sido igual a 3, entonces var2 sería ocho veces var1, es decir, 96.
37
Fundamentos de informática. Programación en Lenguaje C
var2 = var1 << 1;: estado de memoria para la variable var2 será
FFF2, que es la codificación del entero -14.
38
Capítulo 2. Tipos de datos y variables en C.
Operadores compuestos.
Ya se ha visto que una expresión de asignación en C trae, a su izquierda
(Lvalue), el nombre de una variable y, a su derecha (Rvalue) una
expresión a evaluar, o un literal, o el nombre de otra variable. Y ocurre
frecuentemente que la variable situada a la izquierda forma parte de la
expresión de la derecha. En estos casos, y si la expresión es sencilla,
todos los operadores aritméticos y los operadores a nivel de bit binarios
(exceptuando, por tanto, los operadores de signo, incremento,
decremento y complemento) pueden presentar otra forma, en la que se
asocia el operador con el operador asignación. Son los llamados
operadores de asignación compuestos:
+= x += y; es lo mismo que decir x = x + y;
–= x -= y; es lo mismo que decir x = x – y;
*= x *= y; es lo mismo que decir x = x * y;
/= x /= y; es lo mismo que decir x = x / y;
%= x %= y; es lo mismo que decir x = x % y;
>>= x >>= y; es lo mismo que decir x = x >> y;
<<= x <<= y; es lo mismo que decir x = x << y;
&= x &= y; es lo mismo que decir x = x & y;
|= x |= y; es lo mismo que decir x = x | y;
^= x ^= y; es lo mismo que decir x = x ^ y;
39
Fundamentos de informática. Programación en Lenguaje C
Operador sizeof.
Ya sabemos el número de bytes que ocupan en memoria todas las
variables de tipo de dato primitivo en C: 1 byte las variables tipo char;
2 las de tipo short; 4 las de tipo long y float; 8 las de tipo double, y
10 las variables long double.
sizeof(nombre_variable); ó sizeof(nombre_tipo_de_dato);
40
Capítulo 2. Tipos de datos y variables en C.
de bytes que ocupa una variable, la verdad es que con frecuencia ese
dato es muy necesario.
41
Fundamentos de informática. Programación en Lenguaje C
El resultado final será pues un valor del tipo de dato double. Y así será
almacenado en la posición de memoria de la variable y de tipo double.
42
Capítulo 2. Tipos de datos y variables en C.
(tipo) nombre_variable;
43
Fundamentos de informática. Programación en Lenguaje C
44
Capítulo 2. Tipos de datos y variables en C.
45
Fundamentos de informática. Programación en Lenguaje C
Las reglas de precedencia son las que se recogen el la tabla 2.6. Cuanto
más alto en la tabla esté el operador, más alta es su precedencia, y
antes se evalúa ese operador que cualquier otro que esté más abajo en
la tabla. Y para aquellos operadores que estén en la misma fila, es decir,
que tengan el mismo grado de precedencia, el orden de evaluación, en
el caso en que ambos operadores intervengan en una expresión, viene
definido por la asociatividad: de derecha a izquierda o de izquierda a
derecha.
46
Capítulo 2. Tipos de datos y variables en C.
() [] -> . I–D
! ~ ++ -- + - * & D–I
.* ->* I–D
* / % I–D
+ - I–D
<< >> I–D
> >= < <= I–D
== != I–D
& I–D
^ I–D
| I–D
&& I–D
|| D–I
?: I–D
= += -= *= /= %= &= |= <<= >>= D–I
, I–D
a * x + b * y – c / z:
47
Fundamentos de informática. Programación en Lenguaje C
48
Capítulo 2. Tipos de datos y variables en C.
49
Fundamentos de informática. Programación en Lenguaje C
50
Capítulo 2. Tipos de datos y variables en C.
51
Fundamentos de informática. Programación en Lenguaje C
Ayudas On line.
Muchos editores y compiladores de C cuentan con ayudas en línea
abundante. Todo lo referido en este capítulo puede encontrarse en ellas.
Es buena práctica de programación saber manejarse por esas ayudas,
que llegan a ser muy voluminosas y que gozan de buenos índices para
lograr encontrar el auxilio necesario en cada momento.
Recapitulación.
Después de estudiar este capítulo, ya sabemos crear y operar con
nuestras variables. También conocemos muchos de los operadores
definidos en C. Con todo esto podemos realizar ya muchos programas
sencillos.
52
Capítulo 2. Tipos de datos y variables en C.
#include <stdio.h>
void main(void)
{
signed long a, b;
signed long sum, res, pro, coc, mod;
// Cálculos
sum = a + b;
res = a - b;
pro = a * b;
coc = a / b;
mod = a % b;
53
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
float a, b;
float sum, res, pro, coc;
// Cálculos
sum = a + b;
res = a - b;
pro = a * b;
coc = a / b;
// mod = a % b; : esta operación no está permitida
// Mostrar resultados por pantalla.
printf("La suma es igual a %f\n", sum);
printf("La resta es igual a %f\n", res);
printf("El producto es igual a %f\n", pro);
printf("El cociente es igual a %f\n", coc);
}
54
Capítulo 2. Tipos de datos y variables en C.
#include <stdio.h>
void main(void)
{
float a, b;
printf("Introduzca el valor del parámetro a ... ");
scanf("%f",&a);
printf("Introduzca el valor del parámetro b ... ");
scanf("%f",&b);
printf("x = %f",-b / a);
}
#include <stdio.h>
void main(void)
{
short x;
long cuadrado, cubo;
printf("Introduzca un valor ... ");
scanf("%hi",&x);
cuadrado = (long)x * x;
cubo = cuadrado * x;
printf("El cuadrado de %hd es %li\n",x, cuadrado);
printf("El cubo de %hd es %li\n",x, cubo);
}
55
Fundamentos de informática. Programación en Lenguaje C
tema se presenta con detalle las dos funciones de entrada y salida por
consola.
#include <stdio.h>
void main(void)
{
double b, h, S;
printf("Introduzca la base ... ");
scanf("%lf",&b);
printf("Introduzca la altura ... ");
scanf("%lf",&h);
S = b * h / 2;
printf("La superficie del triangulo de ");
printf("base %.2lf y altura %.2lf ",b,h);
printf("es %.2lf",S);
}
56
Capítulo 2. Tipos de datos y variables en C.
#include <stdio.h>
#define PI 3.14159
void main(void)
{
signed short int r;
double l, S;
const double pi = 3.14159;
printf("Indique el valor del radio ... ");
scanf("%hd",&r);
printf("La longitud de la circunferencia");
printf(" cuyo radio es %hd",r);
l = 2 * pi * r;
printf(" es %lf. \n",l);
printf("La superficie de la circunferencia");
printf(" cuyo radio es %hd",r);
S = PI * r * r;
printf(" es %lf. \n",S);
}
57
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
double fahr, cels;
printf("Temperatura en grados Fahrenheit ... ");
scanf("%lf",&fahr);
cels = (5 / 9) * (fahr - 32);
printf("La temperatura en grados Celsius ");
printf("resulta ... %lf.",cels);
}
58
Capítulo 2. Tipos de datos y variables en C.
59
Fundamentos de informática. Programación en Lenguaje C
int a = 10, b = 5, c, d;
float x = 10.0 ,y = 5.0, z, t, v;
c = a/b;
d = x/y;
z = a/b;
t = (1 / 2) * x;
v = (1.0 / 2) * x;
60
Capítulo 2. Tipos de datos y variables en C.
#include <stdio.h>
void main(void)
{
char a = 127;
a++;
printf("%hd", a);
}
La salida que se obtiene con este código es… -128. Intente justificar por
qué ocurre. No se preocupe si aún no conoce el funcionamiento de la
función printf(). Verdaderamente la variable a ahora vale -128. ¿Por
qué?
#include <stdio.h>
void main(void)
{
61
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
char a = 'X', b = 'Y';
printf("\nvalor (caracter) de a: %c", a);
printf("\nvalor (caracter) de b: %c", b);
S = 4 ⋅ π ⋅ r2 V = 4 3 ⋅ π ⋅ r3
62
Capítulo 2. Tipos de datos y variables en C.
#include <stdio.h>
#include <math.h>
void main(void)
{
double aureo;
printf("Número AUREO: tal que x + 1 = x * x.\n");
// Cálculo del número Aureo
// x^2 = x + 1 ==> x^2 - x - 1 = 0 ==> x = (1 + sqrt(5)) / 2.
aureo = (1 + sqrt(5)) / 2;
printf("El número AUREO es .. %lf\n",aureo);
printf("aureo + 1 ........... %lf\n",aureo + 1);
printf("aureo * aureo ....... %lf\n", aureo * aureo);
}
63
Fundamentos de informática. Programación en Lenguaje C
1
x = V0 ⋅ t ⋅ cos(α ) y = V0 ⋅ t ⋅ sen(α ) − ⋅ g ⋅ t2
2
64
CAPÍTULO 3
FUNCIONES DE ENTRADA Y SALIDA
POR CONSOLA
66
Capítulo 3. Funciones de entrada y salida por consola.
printf(“Otro texto”);
Para poder escribir este carácter de salto de línea, y otros que llamamos
caracteres de control, se escribe, en el lugar de la cadena donde
queremos que se imprima ese carácter especial, una barra invertida (‘\’)
seguida de una letra. Cuál letra es la que se debe poner dependerá de
qué carácter especial se desea introducir. Esos caracteres de control son
67
Fundamentos de informática. Programación en Lenguaje C
68
Capítulo 3. Funciones de entrada y salida por consola.
69
Fundamentos de informática. Programación en Lenguaje C
70
Capítulo 3. Funciones de entrada y salida por consola.
71
Fundamentos de informática. Programación en Lenguaje C
donde vemos que los tres valores impresos en líneas diferentes quedan
alineados en sus unidades, decenas, centenas, etc. gracias a que todos
esos valores se han impreso con un ancho de campo igual a 6: su
impresión ha ocasionado tantos desplazamientos de cursos como indica
el ancho de campo.
La instrucción
72
Capítulo 3. Funciones de entrada y salida por consola.
73
Fundamentos de informática. Programación en Lenguaje C
74
Capítulo 3. Funciones de entrada y salida por consola.
Las letras que indican el tipo de dato a recibir se recogen en la tabla 3.3.
Los modificadores de tipo de dato son los mismos que para la función
printf.
75
Fundamentos de informática. Programación en Lenguaje C
Recapitulación.
Hemos presentado el uso de las funciones printf() y scanf(), ambas
declaradas en el archivo de cabecera stdio.h. Cuando queramos hacer
uno de una de las dos funciones, o de ambas, deberemos indicarle al
programa con la directiva de preprocesador #include <stdio.h>.
76
Capítulo 3. Funciones de entrada y salida por consola.
Ejercicios.
#include <stdio.h>
void main(void)
{
unsigned char ch;
#include <stdio.h>
void main(void)
{
signed long int sli;
signed short int ssi;
77
Fundamentos de informática. Programación en Lenguaje C
78
Capítulo 3. Funciones de entrada y salida por consola.
79
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#include <math.h>
void main(void)
{
double a = M_PI;
80
Capítulo 3. Funciones de entrada y salida por consola.
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
randomize();
81
Fundamentos de informática. Programación en Lenguaje C
82
Capítulo 3. Funciones de entrada y salida por consola.
83
Fundamentos de informática. Programación en Lenguaje C
modificador significado
h argumento se interpreta como un short int.
l argumento se interpreta como un long int cuando
precede a un entero (d, i, o, u, x, X) o double si
precede a un tipo de dato de coma flotante (f, g, G, e,
E).
L argumento se interpreta como un long double si
precede a un tipo de dato de coma flotante (f, g, G, e,
E).
ancho significado
num Especifica el número mínimo de caracteres que se
imprimen. Si el valor que se imprime es menor que este
num entonces el resultado es completado con ceros. El
valor nunca es truncado incluso si es mayor.
* El ancho no se especifica en el formato de la cadena
sino que se indica en el valor entero que precede al
argumento que tiene que formatearse.
.precisión significado
.num Para los tipos f, e, E, g, G: indica el número de dígitos
que se imprimen después del punto decimal (por defecto
es 6).
Para el tipo s: indica el número máximo de caracteres
que se imprimen. (por defecto imprime hasta encontrar
el primer carácter null).
flags significado
- Alineación a la izquierda con el ancho de campo dado
(por defecto alinea a la derecha). Este flag sólo tiene
sentido cuando se especifica el ancho de campo.
+ Obliga a anteponer un signo al resultado (+ o -) si el
tipo es con signo. (por defecto sólo el signo menos - se
imprime).
blanco Si el argumento es un valor positivo con signo, se
inserta un blanco antes del número.
0 Coloca tantos ceros a la izquierda del número como
sean necesarios para completar el ancho de campo
especificado.
# Usado con los tipos o, x o X el valor es precedido con 0,
0x o 0X respectivamente si no son cero.
Usado con e, E o f obliga a que el valor de salida
contenga el punto decimal incluso aunque sólo sigan
ceros.
Usado con g o G el resultado es el mismo que con e o E
pero los ceros sobrantes no se eliminan.
84
Capítulo 3. Funciones de entrada y salida por consola.
argumento(s)
Parámetro(s) opcional(es) que contiene(n) los datos que se insertarán
en el lugar de los % etiquetas especificados en los parámetros del
formato. Debe haber el mismo número de parámetros que de etiquetas
de formato.
Valor de retorno de printf.
Si tiene éxito representa el número total de caracteres impresos. Si hay
un error, se devuelve un número negativo.
Ejemplo.
/* printf: algunos ejemplos de formato*/
#include <stdio.h>
void main(void)
{
printf("Caracteres: %c %c \n", 'a', 65);
printf("Decimales: %d %ld\n", 1977, 650000);
printf("Precedidos de blancos: %10d \n", 1977);
printf("Precedidos de ceros: %010d \n", 1977);
printf("Formato: %d %x %o %#x %#o\n",100,100,100,100,100);
printf("float: %4.2f %+.0e %E\n", 3.1416, 3.1416, 3.1416);
printf("Ancho: %*d \n", 5, 10);
printf("%s \n", "Mi mamá me mima");
}
Y la salida:
Caracteres: a A
Decimales: 1977 650000
Precedidos con blancos: 1977
Precedidos con ceros: 0000001977
Formato: 100 64 144 0x64 0144
float: 3.14 +3e+000 3.141600E+000
Ancho: 10
Mi mamá me mima
85
Fundamentos de informática. Programación en Lenguaje C
86
CAPÍTULO 4
ESTRUCTURAS DE CONTROL
Introducción.
Las reglas de la programación estructurada son:
88
Capítulo 4. Estructuras de control.
Conceptos previos.
La regla 3 de la programación estructurada habla de tres estructuras de
control: la secuencia, la selección y la repetición. Nada nuevo hay ahora
que decir sobre la secuencia, que vendría esquematizada en la figura
4.1. En la figura 4.2. se esquematizan diferentes posibles estructuras de
selección; y en la figura 4.3. las dos estructuras básicas de repetición.
89
Fundamentos de informática. Programación en Lenguaje C
No Sí No Sí
Condición Condición
Instrucción Instrucción
Instrucción
No Sí
Condición
No Condición
Sí
Instrucción Instrucción
Instrucción
90
Capítulo 4. Estructuras de control.
if(condición) sentencia;
Ejemplo:
91
Fundamentos de informática. Programación en Lenguaje C
Ejemplo:
92
Capítulo 4. Estructuras de control.
if(expresión_1) /* primer if */
{
if(expresión_2) /* segundo if */
{
if(expresión_3) /* tercer if */
sentencia_1;
else /* alternativa al tercer if */
sentencia_2;
}
else /* alternativa al 2º if */
sentencia_3;
}
else /* alternativa al primer if */
sentencia_4;
Sí No
C1
Sí No
C2
Sí No
C3
S1 S2 S3 S4
93
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
short D, d;
char opcion;
printf("Programa para dividir dos enteros...\n");
printf("Introduzca el dividendo ... ");
scanf("%hd",&D);
printf("Introduzca el divisor ... ");
scanf("%hd",&d);
if(d != 0)
printf("%hu / %hu = %hu", D, d, D / d);
else
{
printf("No se puede dividir por cero.\n");
printf("¿Introducir otro denominador (s/n)?");
opcion = getchar();
if(opcion == 's')
{
printf("\nNuevo denominador ... ");
scanf("%hd",&d);
if(d != 0)
printf("%hu / %hu = %hu", D, d, D/d);
else
printf("De nuevo ha introducido 0.");
}
}
}
• Escala if - else – if
94
Capítulo 4. Estructuras de control.
else sentencia4;
}
}
Como se ve, una estructura así anidada se escribe con mayor facilidad y
expresa también más claramente las distintas alternativas. No es
necesario que, en un anidamiento de sentencias condicionales,
encontremos un else final: el último if puede ser una bifurcación
abierta:
if(condición1) sentencia1;
else if (condición2) sentencia2;
else if(condición3) sentencia3;
95
Fundamentos de informática. Programación en Lenguaje C
96
Capítulo 4. Estructuras de control.
97
Fundamentos de informática. Programación en Lenguaje C
switch(a)
{
case 1: printf(“UNO\t”);
case 2: printf(“DOS\t”);
case 3: printf(“TRES\t”);
default: printf(“NINGUNO\n”);
}
No Sí
a=1 “UNO”
No Sí
a=2 “DOS”
No Sí
a=3 “TRES”
“NINGUNO”
Figura 4.5.: Flujograma del
programa ejemplo con switch, sin
F
sentencias break.
98
Capítulo 4. Estructuras de control.
DOS
No Sí
a=1 “UNO” break;
No Sí
a=2 “DOS” break;
No Sí
a=3 “TRES” break;
“NINGUNO”
Figura 4.6.: Flujograma del
programa ejemplo con switch,
F
con sentencias break.
Una sola sentencia puede tener más de una etiqueta case. Queda claro
en el siguiente ejemplo:
short int nota;
printf("Introduzca la nota del examen ... ");
scanf("%hd",¬a);
99
Fundamentos de informática. Programación en Lenguaje C
switch(nota)
{
case 1:
case 2:
case 3:
case 4: printf(“SUSPENSO”);
break;
case 5:
case 6: printf(“APROBADO”);
break;
case 7:
case 8: printf(“NOTABLE”);
break;
case 9: printf(“SOBRESALIENTE”);
break;
case 10: printf(“MATRÍCULA DE HONOR”);
break;
default: printf(“Nota introducida errónea.”);
}
100
Capítulo 4. Estructuras de control.
Un ejercicio planteado.
Planteamos ahora un ejercicio a resolver: solicite del usuario que
introduzca por teclado un día, mes y año, y muestre entonces por
pantalla el día de la semana que le corresponde.
d = ⎡⎣(26 × M − 2 ) 10 + D + A + A 4 + C 4 − 2 × C ⎤⎦ mod7
101
Fundamentos de informática. Programación en Lenguaje C
• D = 15
• C = 19
es decir… ¡martes!
void main(void)
{
unsigned short D, mm, aaaa;
unsigned short M, A, C;
102
Capítulo 4. Estructuras de control.
if(mm< 3)
{
M = mm + 10;
A = (aaaa - 1) % 100;
C = (aaaa - 1) / 100;
}
else
{
M = mm - 2;
A = aaaa % 100;
C = aaaa / 100;
}
103
Fundamentos de informática. Programación en Lenguaje C
• Estructura while.
while(condición) sentencia;
104
Capítulo 4. Estructuras de control.
105
Fundamentos de informática. Programación en Lenguaje C
Este último ejemplo ha sido sencillo. Veamos otro ejemplo que requiere
un poco más de imaginación. Supongamos que queremos hacer un
programa que solicite al usuario la entrada de un entero y que entonces
muestre por pantalla el factorial de ese número. Ya se sabe la definición
de factorial: n ! = n ⋅ (n − 1) ⋅ (n − 2) ⋅ ... ⋅ 2 ⋅ 1 .
106
Capítulo 4. Estructuras de control.
n 5 4 3 2 1 0
Fact 5 20 60 120 120 120
donde todo es igual excepto que ahora se ha hecho uso del operador
compuesto en la primera sentencia del bloque. Pero aún se puede
compactar más:
107
Fundamentos de informática. Programación en Lenguaje C
Esta línea de programa espera una entrada por teclado. Cuando ésta se
produzca comprobará que hemos tecleado el carácter ‘a’ minúscula; de
no ser así, volverá a esperar otro carácter.
Una forma más sencilla ó fácil de ver el significado de esta última línea
de código vista sería expresarlo de la siguiente manera:
while(ch != ‘a’)
ch = getchar();
108
Capítulo 4. Estructuras de control.
Hemos tenido que emplear una variable auxiliar, que hemos llamado
aux, para poder hacer el intercambio de variables: que a pase a valer el
valor de b y b el del resto de dividir a por b.
109
Fundamentos de informática. Programación en Lenguaje C
• Estructura do–while.
do sentencia while(condición);
110
Capítulo 4. Estructuras de control.
PROCESO
Sí No
repetir
111
Fundamentos de informática. Programación en Lenguaje C
printf("%lu.", Fact);
printf("\n\nCalcular otro factorial (s/n) ");
do
opcion = getchar();
while (opcion != ‘s’ && opcion != ‘n’);
}while(opcion = getchar() == 's');
}
C
C1 ≡ opcion ≠ ' s ' | opcion ≠ ' n '
C 2 ≡ opcion = ' s '
PROCESO
opcion
Sí No
C1
Sí No
C2
112
Capítulo 4. Estructuras de control.
• Estructura for.
s1
Sí No
e1
s3
F
s2
113
Fundamentos de informática. Programación en Lenguaje C
5. Vuelta al paso 2.
6. Fin de la iteración.
Por ejemplo, veamos un programa que muestra por pantalla los enteros
pares del 1 al 100:
#include <stdio.h>
void main(void)
{
short i;
for(i = 2 ; i <= 100 ; i += 2)
printf("%5hd",i);
}
114
Capítulo 4. Estructuras de control.
{
short i;
for(i = 2 ; i <= 100 ; i += 2)
{
printf("%5hd",i);
if(i % 10 == 0) printf("\n");
}
}
Esta estructura for no itera más que la sentencia punto y coma. Toda la
trasformación que deseamos realizar queda en la expresión del cálculo
del factorial mediante la expresión Fact *= n--.
115
Fundamentos de informática. Programación en Lenguaje C
116
Capítulo 4. Estructuras de control.
}
printf("Ha introducido el entero par %hd",num);
printf(" después de %hd impares. ",i - 1);
}
num i ←1 i ← i +1 i ←1
C1 ≡ num mod2 = 0
i ← i +1 C num C
C1 F C1 F
117
Fundamentos de informática. Programación en Lenguaje C
C1 ≡ nummod2 ≠ 0 C
suma ← 0 F
C1
118
Capítulo 4. Estructuras de control.
que repetirá la ejecución del código hasta que se pulse la tecla ‘a’, y que
ocasionará la ejecución del break.
i ←1
C1
i ← i +1
C2 F
C1 ≡ i ≤ 100 i
C 2 ≡ i mod2 ≠ 0
119
Fundamentos de informática. Programación en Lenguaje C
120
Capítulo 4. Estructuras de control.
121
Fundamentos de informática. Programación en Lenguaje C
Recapitulación.
Hemos presentado las estructuras de control posibles en el lenguaje C.
Las estructuras condicionales de bifurcación abierta o cerrada,
condicionales anidadas, operador interrogante, dos puntos, y sentencia
switch. También hemos visto las posibles iteraciones creadas con las
estructuras for, while y do – while, y las modificaciones a las
estructuras que podemos introducir gracias a las palabras reservadas
break y continue.
Ejercicios.
En todos los ejercicios que planteamos a continuación quizá será
conveniente que antes de abordar la implementación se intente diseñar
un algoritmo en pseudocódigo o mediante un diagrama de flujo. Si en
algún caso el problema planteado supone especial dificultad quedará
recogido ese flujograma en estas páginas. En bastantes casos, puede
consultarse éste en las páginas del manual “Fundamentos de
informática. Codificación y algoritmia”.
122
Capítulo 4. Estructuras de control.
#include <stdio.h>
void main(void)
{
long suma = 0;
short i;
for(i = 2 ; i <= 200 ; i += 2)
suma += i;
printf("esta suma es ... %ld.\n",suma);
}
#include <stdio.h>
void main(void)
{
long suma;
short i, num;
for(i = 0, suma = 0 ; ; i++)
{
printf("Introduzca número ... ");
scanf("%hd",&num);
suma += num;
if(num == 0) break;
}
if(i == 0) printf("No se han introducido enteros.");
else printf("La media es ... %.2f.",(float)suma / i);
}
123
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
short suma;
short i, num;
for(num = 2 ; num < 10000 ; num++)
{
for(i = 1, suma = 0 ; i <= num / 2 ; i++)
if(num % i == 0) suma += i;
if(num == suma)
printf("En entero %hd es perfecto.\n",num);
}
}
124
Capítulo 4. Estructuras de control.
#include <stdio.h>
void main(void)
{
unsigned short int a0,a1,a2,a3;
printf("Introduzca cuatro enteros ... \n\n");
printf("Primer entero ... ");
scanf("%hu",&a0);
printf("Segundo entero ... ");
scanf("%hu",&a1);
printf("Tercer entero ... ");
scanf("%hu",&a2);
printf("Cuarto entero ... ");
scanf("%hu",&a3);
if(a0 > a1)
{
a0 ^= a1;
a1 ^= a0;
a0 ^= a1;
}
if(a0 > a2)
{
a0 ^= a2;
a2 ^= a0;
a0 ^= a2;
}
if(a0 > a3)
{
a0 ^= a3;
a3 ^= a0;
a0 ^= a3;
}
if(a1 > a2)
{
a1 ^= a2;
a2 ^= a1;
a1 ^= a2;
}
if(a1 > a3)
{
a1 ^= a3;
a3 ^= a1;
a1 ^= a3;
125
Fundamentos de informática. Programación en Lenguaje C
}
if(a2 > a3)
{
a2 ^= a3;
a3 ^= a2;
a2 ^= a3;
}
printf("\nOrdenados... \n");
printf("%hu <= %hu <= %hu <= %hu.", a0, a1, a2, a3);
}
126
Capítulo 4. Estructuras de control.
#include <stdio.h>
void main(void)
{
127
Fundamentos de informática. Programación en Lenguaje C
signed long a;
unsigned long Test;
char opcion;
do
{
Test = 0x80000000;
printf("\n\nIndique el entero ... ");
scanf("%ld", &a);
while(Test)
{
Test & a ? printf("1") : printf("0");
Test >>= 1;
}
printf("\n¿Desea introducir otro entero? ... ");
do
opcion = getchar();
while (opcion != 's' && opcion != 'n');
}while(opcion == 's');
}
128
Capítulo 4. Estructuras de control.
#include <stdio.h>
#include <math.h>
void main(void)
{
unsigned long int numero, raiz;
unsigned long int div;
char chivato;
printf("Dame el numero que vamos a testear ... ");
scanf("%lu", &numero);
chivato = 0;
raiz = sqrt(numero);
for(div = 2 ; div <= raiz ; div++)
{
if(numero % div == 0)
{
chivato = 1;
break;
}
}
if(chivato == 1)
printf("El numero %lu es compuesto",numero);
else printf("El numero %lu es primo",numero);
}
129
Fundamentos de informática. Programación en Lenguaje C
n = a× b < n× n =n⇒n<n
En este programa vamos probando con todo los posibles enteros que
dividen al número estudiado, que serán todos los comprendidos entre el
2 y la raíz cuadrada de ese número. En cuanto se encuentra un valor
que divide al entero introducido, entonces ya está claro que ese número
es compuesto y no es menester seguir buscando otros posibles
divisores. Por eso se ejecuta la sentencia break.
Otro modo de saber si hemos salido del bucle por haber encontrado un
divisor o por haber terminado el recorrido de la variable de control de la
130
Capítulo 4. Estructuras de control.
void main(void)
{
unsigned long fib1 = 1, fib2 = 1, Fib = 1;
unsigned short n, i = 3;
131
Fundamentos de informática. Programación en Lenguaje C
while(i <= n)
{
Fib = fib1 + fib2;
fib1 = fib2;
fib2 = Fib;
i++;
}
printf("El término %hu de la serie es %lu.\n",n,Fib);
}
#include <stdio.h>
#include <math.h>
void main(void)
{
float a, b, c;
double r;
// introducción de parámetros...
printf("Introduzca los coeficientes...\n\n");
printf("a --> "); scanf("%f",&a);
printf("b --> "); scanf("%f",&b);
printf("c --> "); scanf("%f",&c);
// Ecuación de primer grado...
if(a == 0)
{ // No hay ecuación ...
if(b == 0) printf("No hay ecuación.\n");
else // Sí hay ecuación de primer grado
{
printf("Ecuación de primer grado.\n");
printf("Tiene una única solución.\n");
printf("x1 --> %lf\n", -c / b);
}
}
// Ecuación de segundo grado. Soluciones imaginarias.
else if ((r = b * b - 4 * a * c) < 0)
{
printf("Ecuación sin soluciones reales.\n");
r = sqrt(-r);
132
Capítulo 4. Estructuras de control.
#include <stdio.h>
void main(void)
{
long int numero;
long int div;
printf("%ld.",numero);
}
133
Fundamentos de informática. Programación en Lenguaje C
π2 ∞
1
6
= ∑ 2.
k =1 k
#include <stdio.h>
#include <math.h>
void main(void)
{
double PI = 0;
( −1)
k
π ∞
4
= ∑ 2⋅k +1
k =0
134
Capítulo 4. Estructuras de control.
#include <stdio.h>
#define LIMITE 100000
void main(void)
{
double PI = 0;
π 2 2 4 4 6 6 8 8
= ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ... .
2 1 3 3 5 5 7 7 9
De nuevo el cálculo del valor del número pi. Estos ejercicios son muy
sencillos de buscar (Internet está llena de definiciones de propiedades
del número pi) y siempre es fácil comprobar si hemos realizado un buen
código: basta ejecutarlo y comprobar si sale el famoso 3.14.
135
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#define LIMITE 100000
void main(void)
{
double PI = 2;
for(int num = 2 , den = 1, i = 1 ;
i < LIMITE ; i++ , i % 2 ? num+=2 : den+=2)
PI *= num / (double)den;
printf("El valor de PI es ... %lf.",PI);
}
136
Capítulo 4. Estructuras de control.
tres marineros.
void main(void)
{
unsigned long N = 6, n;
unsigned long soluciones = 0;
137
Fundamentos de informática. Programación en Lenguaje C
138
Capítulo 4. Estructuras de control.
1 1 1 1
e= + + + + ...
0! 1! 2! 3!
#include <stdio.h>
void main(void)
{
double p = 1, e = 1;
for(short n = 1 ; n < 100 ; n++)
{
p *= 1.0 / n;
e += p;
}
printf("El numero e es ... %20.17lf.",e);
}
139
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
// Con cuántas cerillas se va a jugar.
unsigned short cerillas;
// Cuántas cerillas se pueden quitar cada vez.
unsigned short quitar;
// Cerillas que quita el ganador y el perdedor.
unsigned short qp, qg;
char ganador;
do
{
printf("\n\n\nCon cuántas cerillas
se va a jugar ... ");
scanf("%hu",&cerillas);
if(cerillas == 0) break;
do
{
printf("\Cuántas cerillas pueden
quitarse de una vez... ");
scanf("%hu",&quitar);
if(quitar >= cerillas)
printf("No pueden quitarse tantas
cerillas.\n");
}while(quitar >= cerillas);
140
Capítulo 4. Estructuras de control.
cerillas -= qg;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30))printf("\n\n");
}
printf("\n");
}
// FIN DE MOSTRAR CERILLAS
else printf("\nComienza el jugador...");
while(cerillas != 1)
{
do
{
printf("\nCerillas que retira el
jugador ... ");
scanf("%hu",&qp);
if(qp > quitar)
printf("\nNo puede quitar mas
de %hu.\n",quitar);
}while(qp > quitar);
cerillas -= qp;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30)) printf("\n\n");
}
printf("\n");
// Fin de MOSTRAR CERILLAS
if(cerillas == 1)
{
ganador = 'j';
break;
}
qg = quitar - qp + 1;
printf("\nLa máquina retira %hu
cerillas.\n",qg);
cerillas -= qg;
// MOSTRAR CERILLAS ...
printf("\n");
for(short i = 1 ; i <= cerillas ; i++)
{
printf(" |");
if(!(i % 30))printf("\n\n");
}
printf("\n");
141
Fundamentos de informática. Programación en Lenguaje C
if(ganador == 'j')
printf("\nHa ganado el jugador...");
else if(ganador == 'm')
printf("\nHe ganado yo, la máquina...");
}while(cerillas);
}
Φ2 = Φ + 1 Φ −1 = 1 Φ Φ3 = (Φ + 1) (Φ − 1)
Φ =1+1 Φ Φ = 1+ Φ y otras…
1 1 1
Si Φ = 1 + ⇒ Φ =1+ ⇒ Φ =1+ ...
Φ 1 1
1+ 1+
Φ 1
1+
Φ
142
Capítulo 4. Estructuras de control.
1
Φ 1+
1
1+
1
1+
1
1 + ...
1
1+
1
#include <stdio.h>
#define LIMITE 1000
void main(void)
{
double au = 1;
143
Fundamentos de informática. Programación en Lenguaje C
tenemos:
Φ = 1 + Φ = 1 + 1 + Φ = 1 + 1 + 1 + Φ = ... = 1 + 1 + 1 + 1 + 1 + ... 1 + Φ
#include <stdio.h>
#include <math.h>
#define LIMITE 100000
void main(void)
{
double au = 1;
#include <stdio.h>
#include <math.h>
void main(void)
{
long a, b, div;
printf("Límite inferior ... ");
scanf("%ld",&a);
printf("Límite superior ... ");
scanf("%ld",&b);
144
Capítulo 4. Estructuras de control.
El primer for recorre todos los enteros comprendidos entre los dos
límites introducidos por teclado. El segundo for averigua si la variable
num codifica en cada iteración del primer for un entero primo o
compuesto: si al salir del segundo for se tiene que num % div es igual a
cero, entonces num es compuesto y se ejecuta las sentencia continue
que vuelve a la siguiente iteración del primer for. En caso contrario, el
valor de num es primo, y entonces sigue adelante con las sentencias del
primer for, que están destinadas únicamente a mostrar por pantalla, de
forma ordenada, ese entero primo, al igual que habrá mostrado
previamente todos los otros valores primos y mostrará los que siga
encontrando posteriormente.
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263,
145
Fundamentos de informática. Programación en Lenguaje C
146
CAPÍTULO 5
ÁMBITO Y VIDA DE LAS VARIABLES
Ámbito y Vida.
Entendemos por ámbito de una variable el lugar, dentro de un
programa, en el que esta variable tiene significado. Hasta el momento
todas nuestras variables han tenido como ámbito todo el programa, y
quizá ahora no es sencillo hacerse una idea intuitiva de este concepto;
pero realmente, no todas las variables están “en activo” a lo largo de
todo el programa.
Fundamentos de informática. Programación en Lenguaje C
148
Capítulo 5. Ámbito y vida de las variables.
149
Fundamentos de informática. Programación en Lenguaje C
150
Capítulo 5. Ámbito y vida de las variables.
Una variable será local cuando se crea en un bloque del programa, que
puede ser una función, o un bloque interno de una función.
Por ejemplo:
long x = 12;
// Sólo x está disponible.
{
long y = 25;
// Tanto x como y están disponibles.
}
// La variable y está fuera de ámbito. Ha terminado su vida.
151
Fundamentos de informática. Programación en Lenguaje C
En este código, que como vimos permite buscar los números perfectos
entre los primeros 10000 enteros, declara dos variables (j y suma) en el
bloque de la estructura del primer for; la variable j está declarada aún
más local, en el interior del segundo for. Al terminar la ejecución del for
gobernado por la variable i, esas dos variables dejan de existir; la
variable j muere nada más se abandona el espacio de ejecución de la
sentencia iterada por el segundo for. Si a su vez, la estructura for más
externa estuviera integrada dentro de otra estructura de iteración, cada
vez que se volviera a ejecutar ese for se volverían a crear esas dos
variables, que tendrían el mismo nombre, pero no necesariamente las
mismas direcciones de memoria que antes.
152
Capítulo 5. Ámbito y vida de las variables.
#include <stdio.h>
long b = 0, c = 0;
void main(void)
{
for(long b = 0 ; b < 10 ; b++) c++;
printf("El valor de b es %ld y el de c es %ld", b, c);
}
¿Cuál es la salida que ofrecerá por pantalla este código? Por lo que
respecta a la variable c no hay ninguna duda: se ha incrementado diez
veces, y su valor, después de ejecutar la estructura for, será 10. Pero,
¿y b? Esta variable ha sufrido también una variación y ha llegado al
valor 10. Pero… ¿cuál de los dos variables b ha cambiado?: la de ámbito
más local. Y como la sentencia que ejecuta la función printf ya está
fuera de la estructura for, y para entonces la variable local b ya ha
muerto, la variable b que muestra la función printf no es otra que la
global: la única viva en este momento. La salida que mostrará el
programa es la siguiente: El valor de b es 0 y el de c es 10.
153
Fundamentos de informática. Programación en Lenguaje C
154
Capítulo 5. Ámbito y vida de las variables.
Cuando se crea una variable local dentro de una bloque, o dentro de una
función, el compilador reserva espacio para esa variable cada vez que se
llama a la función: mueve en cada ocasión hacia abajo el puntero de pila
tanto como sea preciso para volver a crear esa variable. Si existe un
valor inicial para la variable, la inicialización se realiza cada vez que se
pasa por ese punto de la secuencia.
void main(void)
{
for(long i = 0 ; i < 3 ; i++)
for(long j = 0 ; j < 4 ; j++)
{
static long a = 0;
long b = 0;
155
Fundamentos de informática. Programación en Lenguaje C
Variables en registro.
Cuando se declara una variable, se reserva un espacio de memoria para
almacenar sus sucesivos valores. Cuál sea ese espacio de memoria es
cuestión que no podemos gobernar del todo. Especialmente, como ya se
ha dicho, no podemos decidir cuáles son las variables que deben
ubicarse en los espacios de registro.
156
Capítulo 5. Ámbito y vida de las variables.
Una variable candidata a ser declarada register es, por ejemplo, las
que actúan de contadoras en estructuras for.
Variables extern
Aunque estamos todavía lejos de necesitar este tipo de declaración,
presentamos ahora esta palabra clave de C, que hace referencia al
ámbito de las variables.
157
Fundamentos de informática. Programación en Lenguaje C
Para evitar ese problema, las variable globales que deben permanecer
en todos o varios de los módulos de un programa se declaran como
extern en todos esos módulos excepto en uno, donde se declara como
variable global sin la palabra extern. Al compilar entonces esos
módulos, no se creará la variable donde esté puesta la palabra extern,
y permitirá la compilación al considerar que, en alguno de los módulos
de linkado, esa variable sí se crea. Evidentemente, si la palabra extern
se coloca en todos los módulos, entonces en ninguno se crea la variable
y se producirá error en el linkado.
En resumen…
Ámbito:
El ámbito es el lugar del código donde las sentencias pueden hacer uso
de una variable.
Extensión:
158
Capítulo 5. Ámbito y vida de las variables.
Se puede forzar a que una variable local exista durante toda la ejecución
del programa. Eso puede hacerse mediante la palabra reservada de C
static. En ese caso, al terminar la ejecución de la última instrucción del
bloque donde está creada, la variable no desaparece. De todas formas,
mientras no se vuelva a las sentencias de ese bloque, esa variable no
podrá ser reutilizada, porque fuera de ese bloque, aún estando viva,
está fuera de su ámbito.
159
Fundamentos de informática. Programación en Lenguaje C
Ejercicios
#include <stdio.h>
void main(void)
{
unsigned short a, b, mcd;
do
{
printf("Valor de a ... ");
scanf("%hu",&a);
printf("Valor de b ... ");
scanf("%hu",&b);
if(a == 0 && b == 0) break;
while(b)
{
static unsigned short cont = 0;
mcd = b;
b = a % b;
a = mcd;
cont++;
printf("\ncont = %hu", cont); }
printf("\n\nEl mcd es %hu.", mcd);
}while(1);
160
Capítulo 5. Ámbito y vida de las variables.
161
Fundamentos de informática. Programación en Lenguaje C
162
CAPÍTULO 6
ARRAYS NUMÉRICOS: VECTORES Y
MATRICES
tipo nombre_vector[dimensión];
164
Capítulo 6. Arrays numéricos: vectores y matrices.
Este código recorre todo el vector e inicializa a cero todas y cada una de
sus variables.
Téngase cuidado, por ejemplo, con el recorrido del vector, que va desde
el elemento 0 hasta el elemento dimensión – 1. Un error habitual es
escribir el siguiente código:
short mi_vector[1000], i;
for(i = 0 ; i <= 1000 ; i++) mi_vector[i] = 0;
165
Fundamentos de informática. Programación en Lenguaje C
Por lo demás, estas variables son exactamente iguales que todas las
vistas hasta el momento. También ellas pueden ser declaradas globales
o locales, o static, o extern.
tipo nombre_matriz[dim_1][dim_2]…[dim_N];
float matriz[3][3];
que reserva 9 bloques de cuatro bytes cada uno para poder almacenar
valores tipo float. Esas variables se llaman también con índices, en este
caso dos índices (uno para cada dimensión) que van desde el 0 hasta el
valor de cada dimensión menos uno.
Por ejemplo:
long matriz[5][2], i, j;
166
Capítulo 6. Arrays numéricos: vectores y matrices.
donde tenemos una matriz de cinco filas y dos columnas, toda ella con
los valores iniciales a cero. También se puede inicializar la matriz
mediante el operador asignación y llaves. En este caso se haría lo
siguiente:
167
Fundamentos de informática. Programación en Lenguaje C
&m[1][2] = 0012FF87
&m[1][3] = 0012FF88
&m[1][4] = 0012FF89
Donde vemos que los elementos van ordenados desde el m[0][0] hasta
el m[0][4], y a continuación el m[1][0]: cuando termina la primera fila
comienza la segunda fila.
168
Capítulo 6. Arrays numéricos: vectores y matrices.
m[0][5] = 0;
Ejercicios
169
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
void main(void)
{
short matriz[3][3];
short i, j;
for(i = 0 ; i < 3 ; i++)
for(j = 0 ; j < 3 ; j++)
{
printf("matriz[%hd][%hd] = ", i, j);
scanf("%hd",&matriz[i][j]);
}
for(i = 0 ; i < 3 ; i++)
{
printf("\n\n");
for(j = 0 ; j < 3 ; j++)
printf("%5hd",matriz[i][j]);
}
printf("\n\n\n");
for(i = 0 ; i < 3 ; i++)
{
printf("\n\n");
for(j = 0 ; j < 3 ; j++)
printf("%5hd",matriz[j][i]);
}
}
170
Capítulo 6. Arrays numéricos: vectores y matrices.
#define TAM 3
#include <stdio.h>
void main(void)
{
short a[TAM][TAM];
short b[TAM][TAM];
short s[TAM][TAM];
short p[TAM][TAM];
short i, j, k;
// Entrada matriz a.
for(i = 0 ; i < TAM ; i++)
for(j = 0 ; j < TAM ; j++)
{
printf("a[%hd][%hd] = ", i, j);
scanf("%hd",&a[i][j]);
}
// Entrada matriz b.
for(i = 0 ; i < TAM ; i++)
for(j = 0 ; j < TAM ; j++)
{
printf("b[%hd][%hd] = ", i, j);
scanf("%hd",&b[i][j]);
}
// Cálculo Suma.
for(i = 0 ; i < TAM ; i++)
for(j = 0 ; j < TAM ; j++)
s[i][j] = a[i][j] + b[i][j];
// Cálculo Producto.
// p[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j]
for(i = 0 ; i < TAM ; i++)
for(j = 0 ; j < TAM ; j++)
{
p[i][j] = 0;
for(k = 0 ; k < TAM ; k++)
p[i][j] += a[i][k] * b[k][j];
}
// Mostrar resultados.
// SUMA
for(i = 0 ; i < TAM ; i++)
{
printf("\n\n");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",a[i][j]);
printf("\t");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",b[i][j]);
printf("\t");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",s[i][j]);
printf("\t");
}
171
Fundamentos de informática. Programación en Lenguaje C
// PRODUCTO
printf("\n\n\n");
for(i = 0 ; i < TAM ; i++)
{
printf("\n\n");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",a[i][j]);
printf("\t");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",b[i][j]);
printf("\t");
for(j = 0 ; j < TAM ; j++)
printf("%4hd",p[i][j]);
printf("\t");
}
}
#include <stdio.h>
void main(void)
{
short datos[1000];
short i, j, nn;
// Introducción de datos.
i = 0;
do
{
printf("Entada de nuevo dato ... ");
scanf("%hi",&datos[i]);
i++;
172
Capítulo 6. Arrays numéricos: vectores y matrices.
173
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#define TAM 1000
void main(void)
{
unsigned long int numero, mitad;
unsigned long int i;
unsigned long int div;
unsigned long int D[TAM];
for(i = 0 ; i < TAM ; i++) D[i] = 0;
D[0] = 1;
printf("Numero que vamos a testear ... ");
scanf("%lu", &numero);
mitad = numero / 2;
for(i = 1 , div = 2 ; div <= mitad ; div++)
{
if(numero % div == 0)
{
D[i] = div;
i++;
if(i == TAM)
{
printf("Vector mal dimensionado.");
break;
}
}
}
if(i < TAM) D[i] = numero;
if(i == 1) printf("\n%lu es PRIMO.\n",numero);
else
{
printf("\n%lu es COMPUESTO. ", numero);
printf("Sus divisores son:\n\n");
for(i = 0 ; i < TAM && D[i] != 0; i++)
printf("\n%lu", D[i]);
}
}
174
Capítulo 6. Arrays numéricos: vectores y matrices.
void main(void)
{
signed long N;
unsigned short bits[32], i;
unsigned long Test;
do
{
printf("\n\nIntroduce un entero ... ");
175
Fundamentos de informática. Programación en Lenguaje C
scanf("%li",&N);
if(N == 0) break;
}while(1);
}
6 1 8
7 5 3
2 9 4
176
Capítulo 6. Arrays numéricos: vectores y matrices.
177
Fundamentos de informática. Programación en Lenguaje C
Aparte del código que cada uno pueda escribir de la mano del
flujograma, ofrecemos ahora otro que agiliza de forma notable la
búsqueda de la siguiente posición del cuadro donde se ha de colocar el
siguiente valor de numero. En el código se ha definido una macro
mediante la directiva #define. No es trivial verlo a la primera, pero
ayuda el ejemplo a comprender que a veces un código bien pensado
facilita su comprensión.
El código es el siguiente:
#include <stdio.h>
#define lr(x, N) ((x)< 0 ? N+(x)%N : ((x)>=N ? (x)%N : (x) ))
void main(void)
{
unsigned short magico[17][17];
unsigned short fil, col, dim, num;
do
{
printf( "\nDimensión ( impar entre 3 y 17 ): ");
scanf("%hu", &dim);
}while(dim % 2 == 0);
178
Capítulo 6. Arrays numéricos: vectores y matrices.
179
Fundamentos de informática. Programación en Lenguaje C
C C C
dim fil ← 0
fil ← 0
numero ← numero + 1
F No Si
C3
C 3 ≡ M[fil ][col ] ≠ 0
180
CAPÍTULO 7
CARACTERES Y CADENAS DE
CARACTERES
Ejemplo de uso:
if(isalnum(‘@’)) printf(“Alfanumérico”):
else printf(“No alfanumérico”);
182
Capítulo 7. Caracteres y cadenas de caracteres.
Ejemplo de uso:
if(isalnum(‘2’)) printf(“Alfabético”):
else printf(“No alfabético”);
Ejemplo de uso:
if(iscntrl(‘\n’)) printf(“Carácter de control”):
else printf(“No carácter de control”);
183
Fundamentos de informática. Programación en Lenguaje C
184
Capítulo 7. Caracteres y cadenas de caracteres.
Entrada de caracteres.
Hemos visto dos funciones que sirven bien para la introducción de
caracteres.
185
Fundamentos de informática. Programación en Lenguaje C
Cadena de caracteres.
Una cadena de caracteres es una formación de caracteres. Es un vector
tipo char, cuyo último elemento es el carácter nulo (ó NULL, ó ‘\0’ se
escribe en C). Toda cadena de caracteres termina con el carácter
llamado carácter NULO de C. Este carácter indica donde termia la
cadena.
char mi_cadena[dimensión];
186
Capítulo 7. Caracteres y cadenas de caracteres.
Faltaba el carácter nulo con el que debe terminar toda cadena. De todas
formas, la asignación de valor a una cadena suele hacerse mediante
comillas dobles, de la siguiente manera:
187
Fundamentos de informática. Programación en Lenguaje C
mi_cadena[0] = ‘\0’;
188
Capítulo 7. Caracteres y cadenas de caracteres.
Hay que hacer una advertencia grave sobre el uso de esta función:
puede ocurrir que la cadena introducida por teclado sea de mayor
longitud que el número de bytes que se han reservado. Esa incidencia
no es vigilada por la función gets. Y si ocurre, entonces, además de
grabar información de la cadena en los bytes reservados para ello, se
hará uso de los bytes, inmediatamente consecutivos a los de la cadena,
hasta almacenar toda la información tecleada más su carácter nulo final.
Esa violación de memoria puede tener —y de hecho habitualmente
tiene— consecuencias desastrosas para el programa.
El programa está bien construido. Pero hay que tener en cuenta que el
nombre que se introduce puede, fácilmente, superar los 10 caracteres.
Por ejemplo, si un usuario responde diciendo “José Antonio”, ya ha
introducido 13 caracteres: 4 por José, 7 por Antonio, 1 por el carácter
en blanco, y otro más por el carácter nulo final. En ese caso, el
comportamiento del programa sería imprevisible.
189
Fundamentos de informática. Programación en Lenguaje C
190
Capítulo 7. Caracteres y cadenas de caracteres.
191
Fundamentos de informática. Programación en Lenguaje C
192
Capítulo 7. Caracteres y cadenas de caracteres.
193
Fundamentos de informática. Programación en Lenguaje C
194
Capítulo 7. Caracteres y cadenas de caracteres.
break;
}
i++;
}
if(chivato == 1)
printf("cadena01 > cadena02");
else if(chivato == 2)
printf("cadena02 > cadena01");
else if(cad01[i] == NULL && cad02[i] != NULL)
printf("cadena02 > cadena01");
else if(cad01[i] != NULL && cad02[i] == NULL)
printf("cadena01 > cadena02");
else
printf("cadenas iguales");
}
195
Fundamentos de informática. Programación en Lenguaje C
196
Capítulo 7. Caracteres y cadenas de caracteres.
197
Fundamentos de informática. Programación en Lenguaje C
198
Capítulo 7. Caracteres y cadenas de caracteres.
j = 0;
i++;
}
else if((e[i] == '+' || e[i] == '-') && est == 2)
{
op = e[i];
i++;
est = 3;
}
else if(e[i] == '=' && est == 5)
{
printf("%lu %c %lu = ",a1,op,a2);
printf("%lu", op=='+' ? a1 + a2 : a1 - a2);
break;
}
else
{
err = 1;
break;
}
}
if(err == 1) printf("Error de entrada de datos");
}
Ejercicios.
#include <stdio.h>
void main(void)
{
char cadena[100];
short int a, e, i, o, u, cont;
printf("Introduzca una cadena de texto ... \n");
gets(cadena);
a = e = i = o = u = 0;
for(cont = 0 ; cadena[cont] != NULL ; cont++)
{
if(cadena[cont] == 'a') a++;
else if(cadena[cont] == 'e') e++;
else if(cadena[cont] == 'i') i++;
199
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#include <ctype.h>
void main(void)
{
char cadena[100];
short int cont;
printf("Introduzca una cadena de texto ... \n");
gets(cadena);
for(cont = 0 ; cadena[cont] != NULL ; cont++)
cadena[cont] = toupper(cadena[cont]);
printf("La cadena introducida ha sido ...\n");
printf("%s\n",cadena);
}
200
Capítulo 7. Caracteres y cadenas de caracteres.
#include <stdio.h>
#include <string.h>
void main(void)
{
char cadena[100];
short int i, j;
printf("Introduzca una cadena de texto ... \n");
gets(cadena);
for(i = 0 ; cadena[i] != NULL ; )
if(cadena[i] == 32)
for(j = i ; cadena[j] != NULL ; j++)
cadena[j] = cadena[j + 1];
else i++;
printf("La cadena introducida ha sido ...\n");
printf("%s\n",cadena);
}
201
Fundamentos de informática. Programación en Lenguaje C
#include <ctype.h>
#include <stdio.h>
void main(void)
{
char c[100];
short int i;
short int d;
printf("Introduzca una cadena de texto ... \n");
gets(c);
for(i = 0 ; c[i] != NULL ; i++)
c[i] = toupper(c[i]);
printf("Introduzca el desplazamiento ... \n");
scanf("%hd",&d);
d %= 26; /* Si d = 26 * k + d', donde d' < 26
entonces desplazar d en el
abecedario es lo mismo que desplazar d'. */
for(i = 0 ; c[i] != NULL ; i++)
{
if(isalpha(c[i]))
{
c[i] += d;
if(c[i] > 'Z') c[i] = 'A' + c[i] - 'Z' - 1;
}
}
printf("La cadena transformada queda ... \n");
printf("%s",c);
}
202
CAPÍTULO 8
PUNTEROS
Definición y declaración.
Una variable tipo puntero es una variable que contiene la
dirección de otra variable.
Y como tipos de dato que son, habrá que definir para ellos un dominio y
unos operadores.
tipo *nombre_puntero;
Por ejemplo:
204
Capítulo 8. Punteros.
Esa variable p así declarada será una variable puntero a short, que no
es lo mismo que puntero a float, etc.
long a, b, *c;
205
Fundamentos de informática. Programación en Lenguaje C
Y así se ha creado una variable puntero a long llamada px, que servirá
para almacenar direcciones de variables de tipo long. Mediante la
segunda instrucción asignamos a ese puntero la dirección de la variable
x. Habitualmente se dice que px apunta a x.
206
Capítulo 8. Punteros.
1. ¿Dónde está pt? Porque pt es una variable, y por tanto está ubicada
en la memoria y tendrá una dirección. Para ver esa dirección, basta
aplicar a pt el operador dirección &. pt está en &pt.
*pt = 3.141596;
207
Fundamentos de informática. Programación en Lenguaje C
Pero no sólo hay que inicializar las variables puntero: hay que
inicializarlas bien, con coherencia. No se puede asignar a un puntero a
un tipo de dato concreto la dirección de una variable de un tipo de dato
diferente. Por ejemplo:
float x, px;
long y;
px = &y;
208
Capítulo 8. Punteros.
Punteros y vectores
Los punteros sobre variables simples tienen una utilidad clara en las
funciones. Allí los veremos con detenimiento. Lo que queremos ver
ahora es el uso de punteros sobre arrays.
209
Fundamentos de informática. Programación en Lenguaje C
a b
F6C3:9870 Ã pa pb Ä F6C3:9870
b[0]
F6C3:9871 F6C3:9871
a[0]
F6C3:9872 pb + 1 Ä F6C3:9872
b[1]
F6C3:9873 F6C3:9873
F6C3:9874 Ã pa + 1 pb + 2 Ä F6C3:9874
b[2]
F6C3:9875 F6C3:9875
a[1]
F6C3:9876 pb + 3 Ä F6C3:9876
b[3]
F6C3:9877 F6C3:9877
F6C3:9878 Ã pa + 2 pb + 4 Ä F6C3:9878
b[4]
F6C3:9879 F6C3:9879
a[2]
F6C3:987A pb + 5 Ä F6C3:987A
b[5]
F6C3:987B F6C3:987B
F6C3:987C Ã pa + 3 pb + 6 Ä F6C3:987C
… …
F6C3:987D F6C3:987D
210
Capítulo 8. Punteros.
211
Fundamentos de informática. Programación en Lenguaje C
pf2(0012FF4C) - pf1(0012FF28) = 9
pd2(0012FF20) - pd1(0012FED8) = 9
pld2(0012FECE) - pld1(0012FE74) = 9
(long)pc2 - (long)pc1 = 9
(long)ph2 - (long)ph1 = 18
(long)pf2 - (long)pf1 = 36
(long)pd2 - (long)pd1 = 72
(long)pld2 - (long)pld1 = 90
212
Capítulo 8. Punteros.
tipo nombre_array[dimensión];
213
Fundamentos de informática. Programación en Lenguaje C
Con índices:
#include <stdio.h>
#include <string.h>
void main(void)
{
char orig[100], copia[100];
short i, l;
printf("Introduzca la cadena ... \n");
gets(orig);
l = strlen(orig);
for(i = 0 ; i < l ; i++)
copia[l - i - 1] = orig[i];
copia[i] = NULL;
printf("Cadena original: %s\n",orig);
printf("Cadena copia: %s\n",copia);
}
214
Capítulo 8. Punteros.
Puntero a puntero
Un puntero es una variable que contiene la dirección de otra variable.
Según sea el tipo de variable que va a ser apuntada, así, de ese tipo,
debe ser declarado el puntero. Ya lo hemos dicho.
Pero un puntero es también una variable. Y como variable que es, ocupa
una porción de memoria: tiene una dirección.
Por ejemplo:
Y así como antes hemos visto que hay una relación directa entre
punteros a un tipo de dato y vectores de este tipo de dato, también
veremos ahora que hay una relación directa entre punteros a punteros y
matrices de dimensión 2. Y entre punteros a punteros a punteros y
215
Fundamentos de informática. Programación en Lenguaje C
double m[4][6];
216
Capítulo 8. Punteros.
m = 0012FECC
*(m + 0) = 0012FECC &m[0][0] = 0012FECC
*(m + 1) = 0012FEFC &m[1][0] = 0012FEFC
*(m + 2) = 0012FF2C &m[2][0] = 0012FF2C
*(m + 3) = 0012FF5C &m[3][0] = 0012FF5C
Tenemos que m vale lo mismo que *(m + 0); su valor es la dirección del
primer elemento de la matriz: m[0][0]. Después de él, vienen todos los
demás, uno detrás de otro: después de m[0][5] vendrá el m[1][0], y
esa dirección la podemos obtener con *(m + 1); después de m[1][5]
vendrá el m[2][0], y esa dirección la podemos obtener con *(m + 2);
después de m[2][5] vendrá el m[3][0], y esa dirección la podemos
obtener con *(m + 3); y después de m[3][5] se termina la cadena de
elementos reservados.
217
Fundamentos de informática. Programación en Lenguaje C
Con índices:
#include <stdio.h>
void main(void)
{
double m[3][3];
double det;
short i,j;
for(i = 0 ; i < 3 ; i++)
for(j = 0 ; j < 3 ; j++)
{
printf("m[%hd][%hd] = ", i, j);
scanf("%lf",&m[i][j]);
}
det = 0;
det += (m[0][0] * m[1][1] * m[2][2]);
det += (m[0][1] * m[1][2] * m[2][0]);
det += (m[0][2] * m[1][0] * m[2][1]);
det -= (m[0][2] * m[1][1] * m[2][0]);
det -= (m[0][1] * m[1][0] * m[2][2]);
det -= (m[0][0] * m[1][2] * m[2][1]);
printf("El determinante ... \n");
for(i = 0 ; i < 3 ; i++)
{
printf("\n | ");
for(j = 0 ; j < 3 ; j++)
printf("%8.2lf",m[i][j]);
printf(" | ");
}
printf("\n\n es ... %lf",det);
}
218
Capítulo 8. Punteros.
Advertencia final
El uso de puntero condiciona el modo de programar. El puntero es una
herramienta muy poderosa y muy arriesgada también. Es necesario
saber bien qué se hace, porque jugando con punteros se pueden
“burlar” muchas seguridades de C.
219
Fundamentos de informática. Programación en Lenguaje C
do
{
a = 0;
do
{
static short local = 0;
local++;
printf("local = %2hd\n",local);
a++;
}while (a < 5);
printf("\n");
b++;
}while(b < 5);
}
220
Capítulo 8. Punteros.
Ejercicios
#include <stdio.h>
void main(void)
{
char c[3];
short i[3], cont;
float f[3];
printf("Las direcciones de memoria son:\n");
for(cont = 0 ; cont < 3 ; cont++)
{
printf("&c[%2d] = %10p\t",cont,c + cont);
printf("&i[%2d] = %10p\t",cont,i + cont);
printf("&f[%2d] = %10p\n\n",cont,f + cont);
}
}
221
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
main()
{
char c[20],*pc1,*pc2;
short int i[20],*pi1,*pi2;
float f[20],*pf1,*pf2;
pc1 = &c[0];
pc2 = &c[19];
pi1 = &i[0];
pi2 = &i[19];
pf1 = &f[0];
pf2 = &f[19];
printf("(int)pc2-(int)pc1 es %d\n",(int)pc2-(int)pc1);
printf("pc2 - pc1 es %d\n\n",pc2 - pc1);
printf("(int)pi2-(int)pi1 es %d\n",(int)pi2-(int)pi1);
printf("pi2 - pi1 es %d\n\n",pi2 - pi1);
printf("(int)pf2-(int)pf1 es %d\n",(int)pf2-(int)pf1);
printf("pf2 - pf1 es %d\n\n",pf2 - pf1);
}
(int)pc2 - (int)pc1 es 19
pc2 - pc1 es 19
(int)pi2 - (int)pi1 es 38
pi2 - pi1 es 19
(int)pf2 - (int)pf1 es 76
pf2 - pf1 es 19
222
CAPÍTULO 9
FUNCIONES
Y ya hemos visto que, sin saber cómo, hemos echado mano de una
función estándar programada por ANSI C que nos ha resuelto nuestro
problema. ¿Cómo se ha logrado que se vea en pantalla un texto, o el
valor de una variable? ¿Qué desarrollo de Taylor se ha aplicado para
llegar a calcular el seno de un ángulo dado? No lo sabemos. ¿Dónde está
el código que resuelve nuestro problema? Tampoco lo sabemos. Pero
cada vez que hemos invocado a una de esas funciones, lo que ha
ocurrido es que el contador de programa ha abandonado nuestra
secuencia de sentencias y se ha puesto con otras sentencias, que son
las que codifican las funciones que hemos invocado.
Definiciones
Abstracción – Modularidad – Programación estructurada.
224
Capítulo 9. Funciones.
225
Fundamentos de informática. Programación en Lenguaje C
226
Capítulo 9. Funciones.
Tanto los procedimientos como las funciones pueden ser vistos como
cajas negras: un código del que desconocemos sus sentencias, al que se
le puede suministrar unos datos de entrada y obtener modificaciones
para esos valores de entrada y/o el cálculo de un nuevo valor, deducido
a partir de los valores que ha recibido como entrada.
Con eso se consigue programas más cortos; que el código pueda ser
usado más de una vez; mayor facilidad para gestionar un correcto orden
de ejecución de sentencias; que las variables tengan mayor carácter
local, y no puedan ser manipuladas fuera del ámbito para el que han
sido creadas.
Funciones en C
Una función, en C, es un segmento independiente de código fuente,
diseñado para realizar una tarea específica.
227
Fundamentos de informática. Programación en Lenguaje C
Declaración de la función.
La declaración de una función se realiza a través de su prototipo. Un
prototipo tiene la forma:
228
Capítulo 9. Funciones.
Donde tipo1,…, tipoN declara de qué tipo es cada uno de los valores
que la función recibirá como parámetros al ser invocada. En la
declaración del prototipo es opcional indicar el nombre que tomarán las
variables que recibirán esos valores y que se comportarán como
variables locales de la función. Sea como sea, ese nombre sí deberá
quedar recogido en la definición de la función. Pero eso es adelantar
acontecimientos.
Toda función que quiera ser definida e invocada debe haber sido
previamente declarada. El prototipo de la función presenta el modo en
que esa función debe ser empleada. Es como la definición de su
interface, de su forma de comunicación: qué valores, de qué tipo y en
qué orden debe recibir la función como argumentos al ser invocada. El
prototipo permite localizar cualquier conversión ilegal de tipos entre los
argumentos utilizados en la llamada de la función y los tipos definidos
en los parámetros, entre los paréntesis del prototipo. Además, controla
que el número de argumentos usados en una llamada a una función
coincida con el número de parámetros de la definición.
Existe una excepción a esa regla: cuando una función es de tipo int,
puede omitirse su declaración. Pero es recomendable no hacer uso de
esa excepción. Si en una expresión, en una sentencia dentro del cuerpo
229
Fundamentos de informática. Programación en Lenguaje C
Definición de la función.
Ya tenemos la función declarada. Con el prototipo ha quedado definido
el modo en que podemos utilizarla: cómo nos comunicamos nosotros
con ella y qué resultado nos ofrece.
Hay que escribir el código, las sentencias, que van a realizar la tarea
para la que ha sido creada la función.
230
Capítulo 9. Funciones.
231
Fundamentos de informática. Programación en Lenguaje C
Llamada a la función
La llamada a una función es una sentencia habitual en C. Ya la hemos
usado con frecuencia, invocando hasta el momento únicamente
funciones de biblioteca. Pero la forma de invocar es la misma para
cualquier función.
nombre_función([argumento1][, …, argumentoN]);
232
Capítulo 9. Funciones.
La sentencia return
Hay dos formas ordinarias de terminar la ejecución de una función.
233
Fundamentos de informática. Programación en Lenguaje C
return [expresión];
234
Capítulo 9. Funciones.
Definición:
void mostrar(short x)
{
printf(“El valor recibido es %hd.”, x);
}
Llamada: mostrar(10);
Definición:
unsigned long int cuadrado(short x)
{
return x * x;
}
Un tercer ejemplo, ahora con dos sentencias return: una función que
reciba como parámetros formales dos valores enteros y devuelve el
valor del mayor de los dos:
Definición:
short mayor(short x, short y)
{
if(x > y) return x;
else return y;
}
235
Fundamentos de informática. Programación en Lenguaje C
Llamada:
A = mayor(a,b);
long Factorial(short a)
{
long F = 1;
while(a) F *= a--;
return F;
}
236
Capítulo 9. Funciones.
237
Fundamentos de informática. Programación en Lenguaje C
238
Capítulo 9. Funciones.
Recurrencia
Ya lo hemos comentado antes. Una función decimos que es recurrente si
existe una llamada a sí misma en el cuerpo de su definición.
n ! = n ⋅ (n − 1)!
239
Fundamentos de informática. Programación en Lenguaje C
240
Capítulo 9. Funciones.
241
Fundamentos de informática. Programación en Lenguaje C
El factorial de 3 es 6.
242
Capítulo 9. Funciones.
243
Fundamentos de informática. Programación en Lenguaje C
void intercambio(long*,long*);
O también
void intercambio(long*a,long*b)
{
short aux;
aux = *b;
*b = *a;
*a = aux;
}
intercambio(&x,&y);
Donde lo que le pasa son las direcciones (no los valores) de las dos
variables de las que se desea intercambiar sus valores.
244
Capítulo 9. Funciones.
Muchos son los ejemplos de funciones que, al ser invocadas, reciben los
parámetros por referencia. La función scanf recibe el parámetro de la
variable sobre la que el usuario deberá indicar su valor con una llamada
por referencia. También lo hemos visto en la función gets, que recibe
como parámetro la dirección de la cadena de caracteres donde se
almacenará la cadena que introduzca el usuario.
Por otro lado, siempre que deseemos que una función nos devuelva más
de un valor también será necesario utilizar llamadas por referencia: uno
de los valores deseamos podremos recibirlo gracias a la sentencia
return de la función llamada; los demás podrán quedar en los
argumentos pasados como referencia: entregamos a la función sus
direcciones, y ella, al terminar, deja en esas posiciones de memoria los
resultados deseados.
245
Fundamentos de informática. Programación en Lenguaje C
246
Capítulo 9. Funciones.
247
Fundamentos de informática. Programación en Lenguaje C
248
Capítulo 9. Funciones.
cuáles son los límites del vector y no permitir que se acceda a posiciones
de memoria que están fuera de la dimensión del vector.
Funciones de escape
Existen ocasiones en que lo mejor que se puede hacer es abortar a
ejecución de una aplicación antes de llegar a consecuencias más
desastrosas si se continuara la ejecución del programa. A veces más
vale abortar misión intentando salvar la mayor parte de los muebles,
que dejar que una situación irresoluble arruine la línea de ejecución y
entonces se produzca la interrupción de la ejecución de una forma no
controlada por nosotros.
El prototipo de la función es
249
Fundamentos de informática. Programación en Lenguaje C
void abort(void)
Ejercicios
#include <stdio.h>
// Función principal...
void main(void)
{
short a, b;
flushall();
getchar();
}
250
Capítulo 9. Funciones.
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
short fibonacci(short);
#include <stdio.h>
#include <conio.h>
void main(void)
{
short N;
printf("Indique el término de la serie: ");
251
Fundamentos de informática. Programación en Lenguaje C
scanf("%hd", &N);
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
while(x > 2)
{
Fib = fib1 + fib2;
fib1 = fib2;
fib2 = Fib;
x--;
}
return Fib;
}
#include <stdio.h>
/* ------------------------------------------------------- */
252
Capítulo 9. Funciones.
randomize();
for(int i = 0 ; i < TAM ; i++)
vector[i] = random(1000);
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
253
Fundamentos de informática. Programación en Lenguaje C
254
Capítulo 9. Funciones.
58. Escriba una aplicación que reciba un entero y busque todos sus
divisores, dejándolos en un vector.
#include <stdio.h>
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
255
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#define TAM 100
256
Capítulo 9. Funciones.
printf("Introduzca valores.");
printf("Al terminar introduzca en valor cero.");
for(i = 0 ; i < TAM ; i++)
{
printf("\n\nnumeros[%3hu] -> ",i);
scanf("%lu",numeros + i);
if(*(numeros + i) == 0) break;
}
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
i = 2;
m = mcd(*(n + 0),*(n + 1));
while(i < d) m = mcd(m,*(n + i++));
return m;
}
257
Fundamentos de informática. Programación en Lenguaje C
#include <stdio.h>
#include <conio.h>
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
return suma == x ? 1 : 0;
}
258
Capítulo 9. Funciones.
#include <stdio.h>
/* ------------------------------------------------------- */
/* Función Hanoi. */
/* ------------------------------------------------------- */
259
Fundamentos de informática. Programación en Lenguaje C
∑f
i =1
i = fn+2 − 1
∑f
i =1
2⋅i = f2⋅n+1 − 1
∑f
i =1
2⋅i −1 = f2⋅n
∑f
2
i = fn ⋅ fn+1
i =1
260
Capítulo 9. Funciones.
/* ======================================================= */
/* PROGRAMA DE LA SERIE DE FIBONACCI. */
/* ======================================================= */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define RANGO 40
// Función principal...
void main(void)
{
unsigned long fib[RANGO + 1];
// No utilizaremos el elemento 0.
unsigned short i;
char opcion;
fib[1] = 1;
261
Fundamentos de informática. Programación en Lenguaje C
fib[2] = 1;
// Serie de fibonacci...
for(i = 3 ; i <= RANGO ; i++)
fib[i] = fib[i - 1] + fib[i - 2];
do
{
// Menú de opciones ...
opcion = menu();
switch(opcion)
{
case '1': fib01(fib); break;
case '2': fib02(fib); break;
case '3': fib03(fib); break;
case '4': fib04(fib); break;
case '5': fib05(fib); break;
case '6': fib06(fib); break;
case '7': fib07(fib); break;
case '8': fib08(fib); break;
case '0': printf("\nFin del programa");
printf("\nPulse tecla para terminar");
flushall();
getchar();
break;
default: printf("opción no definida ... ");
}
}while(opcion != '0');
}
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
clrscr();
262
Capítulo 9. Funciones.
do
opcion = getchar();
while(opcion < '0' || opcion > '8');
return opcion;
}
// Función fib01
void fib01(unsigned long*f)
{
unsigned short n, i;
unsigned long S = 0;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 1.");
printf("\n\n\tLa suma de los n primeros terminos");
printf("\n\tes igual a f[n + 2] - 1.");
263
Fundamentos de informática. Programación en Lenguaje C
// Función fib02
void fib02(unsigned long*f)
{
unsigned short n, i;
unsigned long S = 0;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 2.");
printf("\n\tLa suma de los n primeros
terminos pares (2, 4, ..., 2 * n)");
printf("\n\tpares es igual a f[2 * n + 1] - 1.");
// Función fib03
void fib03(unsigned long*f)
{
unsigned short n, i;
unsigned long S = 0;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 2.");
264
Capítulo 9. Funciones.
// Función fib04
void fib04(unsigned long*f)
{
unsigned short n, i;
unsigned long S = 0;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 3.");
printf("\n\tLa suma de los cuadrados de los
n primeros terminos");
printf("\n\tes igual a f[n] * f[n + 1].");
265
Fundamentos de informática. Programación en Lenguaje C
// Función fib05
void fib05(unsigned long*f)
{
unsigned short n, m;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 5.");
printf("\n\tSi n es divisible por m, entonces f[n]");
printf("\n\tes divisible por f[m].\n\n");
// Función fib06
void fib06(unsigned long*f)
{
unsigned short n;
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 6.");
266
Capítulo 9. Funciones.
// Función fib07
void fib07(unsigned long*f)
{
unsigned short n;
const double oro = (1 + sqrt(5)) / 2;
char blancos[] = " ";
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 7.");
printf("\n\tEl cociente de dos elementos
consecutivos de la serie");
printf("\n\tse aproxima al numero aureo.\n\n");
// Función fib08
void fib08(unsigned long*f)
{
unsigned short n;
267
Fundamentos de informática. Programación en Lenguaje C
clrscr();
printf("\n\n\n\tOPCION SELECCIONADA 8.");
printf("\n\tMostrar los 40 primeros elementos
de la serie de Fibonacci.\n\n");
268
Capítulo 9. Funciones.
/Función principal
void main(void)
{
char leido[200], leidoM[200];
unsigned long int n, naux;
unsigned short C, D, U, c, d, u;
do
{
// Inicializamos las cadenas de caracteres.
leido[0] = '\0';
leidoM[0] = '\0';
if(U || D || C)
{
// Sin el número es mayor que 999:
strcat(leidoM,centenas(C,D,U));
strcat(leidoM,decenas(U,D));
strcat(leidoM,unidades(U,D));
strcat(leidoM, "mil ");
}
strcat(leido,centenas(c,d,u));
strcat(leido,decenas(u,d));
269
Fundamentos de informática. Programación en Lenguaje C
strcat(leido,unidades(u,d));
strcat(leidoM,leido);
/* ------------------------------------------------------- */
/* Definición de las funciones */
/* ------------------------------------------------------- */
switch(u)
{
case 0: return "";
case 1: return "uno ";
case 2: return "dos ";
case 3: return "tres ";
case 4: return "cuatro ";
case 5: return "cinco ";
case 6: return "seis ";
case 7: return "siete ";
case 8: return "ocho ";
case 9: return "nueve ";
}
}
270
Capítulo 9. Funciones.
271
Fundamentos de informática. Programación en Lenguaje C
272
PARTE II:
Profundizando
en C.
Fundamentos de informática. Programación en Lenguaje C
274
PARTE II: Profundizando en C.
275
Fundamentos de informática. Programación en Lenguaje C
276
CAPÍTULO 10
ASIGNACIÓN DINÁMICA DE
MEMORIA
long numeros[100];
long A[f][c];
278
Capítulo 10. Asignación dinámica de memoria.
Función malloc
Esta función malloc queda definida en la biblioteca stdlib.h. También la
encontramos en la biblioteca alloc.h. Recomendamos hacer uso siempre
de la definición recogida en stdlib.
Su prototipo es el siguiente:
Veamos un ejemplo:
long dim;
float *vector;
printf(“Dimensión de su vector ...”);
279
Fundamentos de informática. Programación en Lenguaje C
scanf(“%ld”,&dim);
vector = (float*)malloc(4 * dim);
280
Capítulo 10. Asignación dinámica de memoria.
281
Fundamentos de informática. Programación en Lenguaje C
282
Capítulo 10. Asignación dinámica de memoria.
Función free
Esta función viene también definida en la biblioteca stdlib.h. Su
cometido es liberar la memoria que ha sido reservada mediante la
función malloc, o calloc, o realloc. Su sintaxis es la siguiente:
283
Fundamentos de informática. Programación en Lenguaje C
Se comienza generando una tabla con todos los números desde 1 hasta
el límite superior (en nuestro caso hemos quedado que un millón).
Tomamos el número 1 como primo por definición. A continuación se
pasa al siguiente número, que es el 2, que ya desde ese momento se
considerará primo, y se procede a marcar en la tabla como enteros
compuestos (es decir, no primos) a todos los números posteriores a 2 y
múltiplos de 2.
284
Capítulo 10. Asignación dinámica de memoria.
Una vez tenemos claro el algoritmo que nos permitirá llegar a crear la
tabla de los primos, el siguiente paso será implementar el programa que
nos haga este proceso.
64. Escriba un programa que cree un vector con todos los primos
menores que un millón Utilice, para la búsqueda de los primos,
la criba de Erasthótenes.
void main(void)
{
char *num;
long *primos;
long pr, i;
285
Fundamentos de informática. Programación en Lenguaje C
}
TablaPrimos(num, primos, MAX + 1);
free(num);
286
Capítulo 10. Asignación dinámica de memoria.
287
Fundamentos de informática. Programación en Lenguaje C
Luego, para ver cómo se puede hacer uso de esa matriz creada
mediante memoria dinámica, solicitamos al usuario que dé valor a cada
elemento de la matriz y, finalmente, mostramos por pantalla todos los
elementos de la matriz.
El código es el siguiente:
#include <stdlib.h>
#include <stdio.h>
void main(void)
{
float **p;
short f, c;
short i, j;
// Introducir las dimensiones ...
printf("Indique filas del vector ... ");
scanf("%hd",&f);
printf("Indique columnas del vector ... ");
scanf("%hd",&c);
// Creación de las filas ...
p = (float**)malloc(f * sizeof(float*));
if(p == NULL)
{
printf("Memoria insuficiente.\n");
printf("La ejección se interrumpirá.\n");
printf("Pulse una tecla para terminar ... ");
288
Capítulo 10. Asignación dinámica de memoria.
getchar();
exit(0);
}
// Creación de las columnas ...
for( i = 0 ; i < f ; i++)
{
*(p + i) = (float*)malloc(c * sizeof(float));
if(*(p + i) == NULL)
{
printf("Memoria insuficiente.\n");
printf("La ejección se interrumpirá.\n");
printf("Pulse una tecla para terminar...");
getchar();
exit(0);
}
}
// Asignación de valores ...
for(i = 0 ; i < f ; i++)
for(j = 0 ; j < c ; j++)
{
printf("matriz[%2hd][%2hd] = ", i, j);
scanf("%f",*(p + i) + j);
}
// Mostrar la matriz por pantalla ...
for(i = 0 ; i < f ; i++)
{
printf("\n");
for(j = 0 ; j < c ; j++)
printf("%6.2f\t",*(*(p + i) + j));
}
// Liberar la memoria ...
for(i = 0 ; i < f ; i++)
free(*(p + i));
free(p);
}
289
Fundamentos de informática. Programación en Lenguaje C
Decíamos que había dos formas de crear una matriz por asignación
dinámica de memoria. La segunda es crear un solo array, de longitud
igual al producto de filas por columnas. Y si la matriz tiene α filas y β
columnas, considerar los β primeros elementos del vector como la
primera fila de la matriz; y los segundos β elementos, como la segunda
fila, y así, hasta llegar a la última fila.
290
Capítulo 10. Asignación dinámica de memoria.
291
Fundamentos de informática. Programación en Lenguaje C
Ejercicios.
6 1 8
7 5 3
2 9 4
292
Capítulo 10. Asignación dinámica de memoria.
el punto anterior.
#include <stdio.h>
#include <stdlib.h>
usi Dimension(void);
void CuadroACero(uli**,usi);
uli** AsignarMemoria(uli**,usi);
void CrearCuadro(uli**,usi);
void MostrarCuadro(uli**, usi);
void main(void)
{
usi dim;
uli **cuadro;
usi i;
do
{
// Valor de la dimensión ...
dim = Dimension();
if(!dim) break;
293
Fundamentos de informática. Programación en Lenguaje C
/* ------------------------------------------------------- */
/* Función Dimension() */
/* ------------------------------------------------------- */
usi Dimension(void)
{
usi d;
do
{
clrscr();
printf("Dimension del cuadro. Debe ser un
valor IMPAR ... ");
printf("\nIndique dimension CERO si
desea terminar la aplicacion -> ");
scanf("%hu",&d);
}while(!(d % 2) && d);
return d;
}
/* ------------------------------------------------------- */
/* Función CuadroACero() */
/* ------------------------------------------------------- */
void CuadroACero(uli**C,usi d)
{
usi i, j;
for(i = 0 ; i < d ; i++)
for(j = 0 ; j < d ; j++)
*(*(C + i) + j) = 0;
}
/* ------------------------------------------------------- */
/* Función AsignarMemoria() */
/* ------------------------------------------------------- */
294
Capítulo 10. Asignación dinámica de memoria.
uli** AsignarMemoria(uli**C,usi d)
{
usi i;
if((C = (uli**)malloc(d * sizeof(uli*))) == NULL)
{
printf("\nError (1) de asignacion de
memoria.");
printf("\nLa ejecucion del programa no
puede continuar.");
printf("\nPulse cualquier tecla para terminar
la aplicacion");
getchar();
return C;
}
return(C);
}
/* ------------------------------------------------------- */
/* Función CrearCuadro() */
/* ------------------------------------------------------- */
void CrearCuadro(uli**C,usi d)
{
usi posX, posY, antX, antY, elem;
while(elem <= d * d)
{
*(*(C + posX) + posY) = elem;
// Nueva posición X ...
antX = posX;
posX = posX ? posX - 1 : d - 1;
// Nueva posicion Y ...
295
Fundamentos de informática. Programación en Lenguaje C
antY = posY;
posY = posY ? posY - 1 : d - 1;
// Si la casilla ya ha sido ocupada ...
if(*(*(C + posX) + posY))
{
posX = antX;
posY = antY == d - 1 ? 0 : antY + 1;
}
elem++;
}
}
/* ------------------------------------------------------- */
/* Función MostrarCuadro() */
/* ------------------------------------------------------- */
if(sumaf != NULL)
{
for(i = 0 ; i < d ; i++)
{
*(sumaf + i) = 0;
for(j = 0 ; j < d ; j++)
*(sumaf + i) += *(*(C + i) + j);
}
}
if(sumac != NULL)
{
for(i = 0 ; i < d ; i++)
{
*(sumac + i) = 0;
for(j = 0 ; j < d ; j++)
*(sumac + i) += *(*(C + j) + i);
}
}
sumad[0] = sumad[1] = 0;
for(i = 0 ; i < d ; i++)
sumad[0] += *(*(C + i) + i);
for(i = 1 ; i <= d ; i++)
sumad[1] += *(*(C + d - i) + i - 1);
296
Capítulo 10. Asignación dinámica de memoria.
{
printf("\n");
for(j = 0 ; j < d ; j++)
printf("%5hu",*(*(C + j) + i));
printf(" -> %lu\n",*(sumaf + i));
}
printf("\n");
for(i = 0 ; i < d ; i++)
printf(" |");
printf("\n");
for(i = 0 ; i < d ; i++)
printf(" V");
printf("\n\n");
for(i = 0 ; i < d ; i++)
printf("%5lu",*(sumac + i));
297
Fundamentos de informática. Programación en Lenguaje C
298
CAPÍTULO 11
ALGUNOS USOS CON FUNCIONES
Punteros a funciones
En los primeros temas de este manual hablábamos de que toda la
información de un ordenador se guarda en memoria. No sólo los datos.
También las instrucciones tienen su espacio de memoria donde se
almacenan y pueden ser leídas. Todo programa debe ser cargado sobre
la memoria principal del ordenador antes de comenzar su ejecución.
300
Capítulo 11. Algunos usos con funciones.
tipo_función (*puntero_a_funcion)(tipo1,…,tipoN);
puntero_a_función = nombre_función_1;
301
Fundamentos de informática. Programación en Lenguaje C
void main(void)
{
float a, b;
unsigned char op;
float (*operacion)(float, float);
switch(op)
302
Capítulo 11. Algunos usos con funciones.
{
case '+': operacion = sum; break;
case '-': operacion = res; break;
case '*': operacion = pro; break;
case '/': operacion = div;
}
303
Fundamentos de informática. Programación en Lenguaje C
Donde deberá haber tantos nombres de función, todas ellas del mismo
tipo, como indique la dimensión del vector. Como siempre, cada una de
las funciones deberá quedar declarada y definida en el programa.
float(*operacion[4])(float,float)= {sum,res,pro,div};
Con esto hemos declarado cuatro punteros, cada uno de ellos apuntando
a cada una de las cuatro funciones definidas. A partir de ahora será lo
mismo invocar a la función sumaf que invocar a la función apuntada por
el primer puntero del vector.
304
Capítulo 11. Algunos usos con funciones.
tipo_función (*puntero_a_funcion)(parámetros)
305
Fundamentos de informática. Programación en Lenguaje C
*puntero_a_función(parámetros)
void main(void)
{
float a, b;
unsigned char op;
float (*operacion[4])(float, float) ={sum,res,pro,div};
do
{
printf("\n\nPrimer operador ... ");
scanf("%f",&a);
printf("Segundo operador ... ");
scanf("%f",&b);
printf("Operación ... \n)");
printf("\n\n1. Suma\n2. Resta”);
printf(“\n3. Producto\n4. Cociente");
printf("\n\n\tSu opción (1 , 2 , 3 , 4) ... ");
306
Capítulo 11. Algunos usos con funciones.
do
op = getche();
while(op - '0' < 1 || op - '0' > 4 );
mostrar(a,op,b,operacion[(short)(op - '1')]);
printf("\n\nOtra operación (s / n) ... ");
do
op = getche();
while(op != 's' && op != 'n');
}while(op == 's');
}
307
Fundamentos de informática. Programación en Lenguaje C
308
Capítulo 11. Algunos usos con funciones.
Hay que explicar porqué los tipos que recoge el prototipo son siempre
void. El motivo es porque la función qsort está definida para ser capaz
de ordenar un array de cualquier tipo. Puede ordenar enteros, reales,
letras, u otros tipos de dato mucho más complejos, que se pueden crear
y que veremos en un capítulo posterior. La función no tiene en cuenta el
tipo de dato: simplemente quiere saber dos cosas:
309
Fundamentos de informática. Programación en Lenguaje C
void randomize(void);
#define TAM 10
#define RANGO 1000
int ordenar(void*,void*);
void main(void)
{
long numeros[TAM];
long i;
randomize();
for(i = 0 ; i < TAM ; i++)
numeros[i] = random(RANGO);
// Mostramos resultados
310
Capítulo 11. Algunos usos con funciones.
311
Fundamentos de informática. Programación en Lenguaje C
Estudio de tiempos
A veces es muy ilustrativo poder estudiar la velocidad de algunas
aplicaciones que hayamos implementado en C.
clock_t clock(void);
312
Capítulo 11. Algunos usos con funciones.
void main(void)
{
long numeros[TAM];
long i, j;
time_t t1, t2;
randomize();
for(i = 0 ; i < TAM ; i++)
numeros[i] = random(RANGO);
// Vamos a ordenar esos numeros ...
// Método de la burbuja ...
t1 = clock();
for( i = 0 ; i < TAM ; i++)
for(j = i ; j < TAM ; j++)
if(numeros[i] > numeros[j])
cambiar(numeros + i, numeros + j);
t2 = clock();
printf("t2 - t1 = %ld.\n", t2 - t1);
}
313
Fundamentos de informática. Programación en Lenguaje C
void main(void)
{
long numeros[TAM];
long i, j;
time_t t1, t2;
randomize();
for(i = 0 ; i < TAM ; i++)
numeros[i] = random(RANGO);
314
Capítulo 11. Algunos usos con funciones.
Creación de MACROS
La directiva #define, que ya hemos visto, permite la definición de
macros.
315
Fundamentos de informática. Programación en Lenguaje C
316
Capítulo 11. Algunos usos con funciones.
Las barras invertidas al final de cada línea indican que aunque hay un
salto de línea en el editor, el texto continúa en la línea siguiente. Deben
ponerse tal cual, sin espacio en blanco alguno posteriormente a ellas.
317
Fundamentos de informática. Programación en Lenguaje C
318
Capítulo 11. Algunos usos con funciones.
319
Fundamentos de informática. Programación en Lenguaje C
Sin embargo no todas las funciones que hemos utilizado son realmente
así de rígidas. Por ejemplo, la función printf, tantas veces invocada en
nuestros programas, no tiene un número prefijado de parámetros:
Vamos a ver en este epígrafe cómo lograr definir una función en la que
el número de parámetros sea variable, en función de las necesidades
que tenga el usuario en cada momento.
Existen una serie de macros que permiten definir una función como si
tuviera una lista variable de parámetros. Esas macros, que ahora
veremos, están definidas en la biblioteca stdarg.h.
320
Capítulo 11. Algunos usos con funciones.
321
Fundamentos de informática. Programación en Lenguaje C
Lo primero que habrá que hacer con esta variable de tipo va_list será
inicializarla con la lista de argumentos variables recibida en la llamada a
la función.
Para inicializar esa variable se emplea una de las tres macros definidas
en la biblioteca stdarg.h: la macro va_start, que tiene la siguiente
sintaxis:
Su sintaxis es:
322
Capítulo 11. Algunos usos con funciones.
323
Fundamentos de informática. Programación en Lenguaje C
Su sintaxis es:
void main(void)
{
double S;
S = sum(7, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
printf("%f",S);
}
324
Capítulo 11. Algunos usos con funciones.
También se puede hacer eso con la función main. En ese caso, quien
debe pasar los parámetros de arranque a la función principal será el
usuario del programa compilado en el momento en que indique al
sistema operativo el inicio de esa ejecución de programa.
325
Fundamentos de informática. Programación en Lenguaje C
Desde luego, los nombres de las variables argc y argv son mera
convención: cualquier identificador que se elija servirá de la misma
manera.
326
Capítulo 11. Algunos usos con funciones.
327
Fundamentos de informática. Programación en Lenguaje C
Ejercicios
66. Una vez ha creado un vector que contiene todos los primos
menores que un límite superior dado, declare y defina una
función que busque los primos enlazados. Se llaman primos
enlazados a aquellos primos cuya diferencia es igual a dos, es
decir, que son dos impares consecutivos: por ejemplo 11 t 13;
17 y 19, etc. (Sin resolver)
#include <stdio.h>
#include <math.h>
#define CUADRADO(x) x*x
#define SUMA(x,y) CUADRADO(x) + CUADRADO(y)
#define RECTO(x,y) sqrt(SUMA(x,y))
void main(void)
{
printf("%2.1f",RECTO(3,4));
}
328
CAPÍTULO 12
ESTRUCTURAS ESTÁTICAS DE
DATOS Y DEFINICIÓN DE TIPOS
Hemos visto, de hecho, ya diferentes tipos de dato a los que por ahora
no hemos prestado atención alguna, pues aún no habíamos llegado a
este capítulo: tipo de dato size_t, ó time_t: cada vez que nos los
hemos encontrado hemos despejado con la sugerencia de que se
considerasen, sin más, tipos de dato iguales a long.
En este tema vamos a ver cómo se pueden definir nuevos tipos de dato.
Fundamentos de informática. Programación en Lenguaje C
Mediante la palabra clave enum se logran crear tipos de dato que son
subconjunto de los tipos de dato int. Los tipos de dato enumerados
tienen como dominio un subconjunto del dominio de int. De hecho las
variables creadas de tipo enum son tratadas, en todo momento, como
si fuesen de tipo int. Lo que hace enum es mejorar la legibilidad del
programa. Pero a la hora de operar con sus valores, se emplean todos
los operadores definidos para int.
Veamos un ejemplo:
330
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
void main(void)
{
enum judo c;
printf(“Los colores definidos son ... \n”);
for(c = blanco ; c <= negro ; c++)
printf("%d\t",c);
}
331
Fundamentos de informática. Programación en Lenguaje C
Así, se pueden definir los tipos de dato estándar con otros nombres, que
quizá convengan por la ubicación en la que se va a hacer uso de esos
valores definidos por el tipo de dato. Y así tenemos:
typedef unsinged size_t;
typedef long time_t;
O también:
332
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
Sino simplemente
semaforo cruce;
333
Fundamentos de informática. Programación en Lenguaje C
Estructuras de datos en C
Una estructura de datos en C es una colección de variables, no
necesariamente del mismo tipo, que se referencian con un nombre
común. Lo normal será crear estructuras formadas por variables que
tengan alguna relación entre sí, de forma que se logra compactar la
información, agrupándola de forma cabal. Cada variable de la estructura
se llama, en el lenguaje C, elementos de la estructura. Este concepto es
equivalente al presentado antes al hablar de campos.
334
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
};
variable_estructura.identificador_1
variable_estructura.identificador_1 = valor_1;
335
Fundamentos de informática. Programación en Lenguaje C
nombre_estructura nombre_variable;
336
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
// RESTA ...
printf("\n\n");
mostrar(A);
printf(" - ");
mostrar(B);
337
Fundamentos de informática. Programación en Lenguaje C
C = restc(A,B);
mostrar(C);
// PRODUCTO ...
printf("\n\n");
mostrar(A);
printf(" * ");
mostrar(B);
C = prodc(A,B);
mostrar(C);
}
void mostrar(complejo X)
{
printf("(% .2lf%s%.2lf * i) ", X.real, X.imag > 0 ? "
+" : " " , X.imag);
}
338
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
asignatura curricula[100];
339
Fundamentos de informática. Programación en Lenguaje C
void main(void)
{
asig *curr;
short n, i;
printf("Indique nº de asignaturas de su CV ... ");
scanf("%hd",&n);
/* La variable n recoge el número de elementos de tipo
asignatura que debe tener nuestro array. */
curr = (asig*)malloc(n * sizeof(asig));
if(curr == NULL)
{
printf("Memoria insuficiente.\n");
printf("La ejecucion se interrumpira.\n");
340
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
Anidamiento de estructuras
Podemos definir una estructura que tenga entre sus miembros una
variable que sea también de tipo estructura. Por ejemplo:
341
Fundamentos de informática. Programación en Lenguaje C
typedef struct
{
unsigned short dia;
unsigned short mes;
unsigned short anyo;
}fecha;
typedef struct
{
unsigned long clave;
char descripcion[50];
double creditos;
fecha convocatorias[3];
}asignatura;
typedef struct
{
unsigned short dia;
unsigned short mes;
unsigned short anyo;
}fecha;
typedef struct
{
unsigned long clave;
char descripcion[50];
double creditos;
fecha c[3];
}asignatura;
void main(void)
{
342
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
asignatura asig;
time_t bloquehoy;
struct tm *hoy;
bloquehoy = time(NULL);
hoy = localtime(&bloquehoy);
asig.clave = 10102301;
*asig.descripcion = '\0';
strcat(asig.descripcion,"fundamentos de informática");
asig.creditos = 7.5;
asig.c[0].dia = 15;
asig.c[0].mes = 1;
asig.c[0].anyo = hoy->tm_year - 100;
asig.c[1].dia = 21;
asig.c[1].mes = 6;
asig.c[1].anyo = hoy->tm_year - 100;
asig.c[2].dia = 1;
asig.c[2].mes = 9;
asig.c[2].anyo = hoy->tm_year - 100;
printf("Asignatura %10ld\n",asig.clave);
printf("%s\t",asig.descripcion);
printf("%4.1lf\n", asig.creditos);
printf("\npriemra convocatoria ... ");
printf("%2hu-%2hu-%02hu", asig.c[0].dia,
asig.c[0].mes,asig.c[0].anyo);
printf("\nsegunda convocatoria ... ");
printf("%2hu-%2hu-%02hu", asig.c[1].dia,
asig.c[1].mes,asig.c[1].anyo);
printf("\ntercera convocatoria ... ");
printf("%2hu-%2hu-%02hu", asig.c[2].dia,
asig.c[2].mes,asig.c[2].anyo);
}
Hemos asignado a cada uno de los tres elementos del vector c los
valores de día, mes y año correspondientes a cada una de las tres
convocatorias. Hemos utilizado índices de vectores para referenciar cada
una de las tres fechas. Podríamos haber trabajado también con
operatoria de punteros. Por ejemplo, la referencia al día de la segunda
convocatoria es, con operatoria de índices
asig.c[1].dia = 21;
343
Fundamentos de informática. Programación en Lenguaje C
344
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
typedef union
{
tipo_1 identificador_1;
tipo_2 identificador_2;
...
tipo_N identificador_N;
} nombre_union;
typedef struct
{
long dni; // número de dni.
char ss[30]; // número de la seg. social.
}ident2;
void main(void)
{
ident1 id1;
ident2 id2;
345
Fundamentos de informática. Programación en Lenguaje C
id2.dni = 44561098;
*(id2.ss + 0) = NULL;
strcat(id2.ss,"12/0324/5431890");
printf("\nid2.dni = %ld\n",id2.dni);
printf("id2.ss = %s\n",id2.ss);
id2.dni = 44561098
id2.ss = 12/0324/5431890
id1.dni = 44561098
id1.ss = ╩‗º☻324/5431890 (mal)
346
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
En este aspecto, una buena utilidad del mal uso de las uniones (en ese
caso no sería mal uso: sería una treta del programador) será el poder
obtener el código interno de la información de los valores de tipo float.
Veamos como podríamos hacerlo:
#include <stdio.h>
typedef union
{
float fvalor;
unsigned long lvalor;
}codigo;
void main(void)
{
unsigned long Test = 0x80000000;
codigo a;
while(Test)
{
printf("%c",a.lvalor & Test ? '1' : '0');
Test >>= 1;
}
}
347
Fundamentos de informática. Programación en Lenguaje C
esa clase de valores, pero quien quiera conocerla y cotejarla bien puede
hacerlo: la norma está fácilmente accesible; y el programa que
acabamos de presentar permite la visualización de esa codificación.
Ejercicios
La estructura que define el nuevo tipo de dato podría ser como la que
sigue:
#define Byte4 32
typedef unsigned long int UINT4;
typedef struct
{
/* número de elementos UINT4 reservados. */
UINT4 D;
/* número de elementos UINT4 utilizados actualmente. */
UINT4 T;
/* número de bits significativos. */
UINT4 B;
/* El número, que tendrá tantos elementos como indique D. */
UINT4 *N;
}NUMERO;
Que tiene cuatro elementos, que servirán para conocer bien las
propiedades del número (nuevo tipo de dato entero) y que nos
permitirán agilizar luego numerosas operaciones con ellos. El puntero N
recogerá un array (en asignación dinámica) donde se codificarán los
numeros; a este puntero se le asignan tantos elementos enteros largos
consecutivos como indique el campo D. Y una vez creado el número
(reservada la memoria), siempre convendrá mantener actualizado el
348
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
#define msg01_001 \
"01_001: Error de asignación de memoria en CrearNumero()\n"
void CrearNumero(NUMERO*n)
{
/* Con esta función asignamos una cantidad de memoria a n->N
(tantos elementos UINT4 como indique n->D) */
349
Fundamentos de informática. Programación en Lenguaje C
UINT4 c;
if(original->T > copia->D)
{
printf(msg01_002);
exit(1);
}
/* Si el original y la copia no son la misma variable ... */
if(original->N != copia->N)
{
PonerACero(copia);
for(c = 0 ; c < original->T ; c++)
*(copia->N + c) = *(original->N + c);
copia->T = original->T;
copia->B = original->B;
}
}
350
Capítulo 12. Estructuras estáticas de datos y definición de tipos.
Test >>= 1;
n->B--;
}
}
}
351
Fundamentos de informática. Programación en Lenguaje C
352
CAPÍTULO 13
GESTIÓN DE ARCHIVOS
354
Capítulo 13. Gestión de archivos.
355
Fundamentos de informática. Programación en Lenguaje C
356
Capítulo 13. Gestión de archivos.
357
Fundamentos de informática. Programación en Lenguaje C
358
Capítulo 13. Gestión de archivos.
Para trabajar con archivos con buffer, las funciones, tipos de dato
predefinidos y constantes están recogidos en la biblioteca stdio.h. Para
trabajar en entrada y salida de archivos sin buffer están las funciones
definidas en io.h.
359
Fundamentos de informática. Programación en Lenguaje C
360
Capítulo 13. Gestión de archivos.
FILE *puntero_a_archivo;
361
Fundamentos de informática. Programación en Lenguaje C
• Apertura de archivo.
Su prototipo es:
362
Capítulo 13. Gestión de archivos.
363
Fundamentos de informática. Programación en Lenguaje C
gets(nombre_archivo);
fopen(nombre_archivo, “w”);
364
Capítulo 13. Gestión de archivos.
365
Fundamentos de informática. Programación en Lenguaje C
366
Capítulo 13. Gestión de archivos.
fputs(nombre,archivo);
367
Fundamentos de informática. Programación en Lenguaje C
randomize();
for(i = 0 ; i < TAM ; i++)
or[i] = (float)random(1000) / random(100);
368
Capítulo 13. Gestión de archivos.
{
printf("No se ha podido abrir el archivo.\n");
printf("Pulse una tecla para finalizar... ");
getchar();
exit(1);
}
for(i = 0 ; i < TAM ; i++)
fprintf(ARCH,"Valor %04hi-->%12.4f\n",i,or[i]);
fclose(ARCH);
369
Fundamentos de informática. Programación en Lenguaje C
370
Capítulo 13. Gestión de archivos.
Estas dos funciones son útiles para leer y escribir cualquier tipo de
información. Es habitual emplearla junto con el operador sizeof, para
determinar así la longitud (n_bytes) de cada elemento a leer o escribir.
randomize();
for(i = 0 ; i < TAM ; i++)
or[i] = (float)random(1000) / random(100);
371
Fundamentos de informática. Programación en Lenguaje C
fclose(ARCH);
Función feof: Esta función (en realidad es una macro) determina el final
de archivo. Es conveniente usarla cuando se trabaja con archivos
binarios, donde se puede inducir a error y tomar como carácter EOF un
valor entero codificado.
Su prototipo es:
Su prototipo es:
372
Capítulo 13. Gestión de archivos.
remove("numeros.dat");
373
Fundamentos de informática. Programación en Lenguaje C
374
Capítulo 13. Gestión de archivos.
while(!feof(ARCH))
{
fseek(ARCH,16,SEEK_CUR);
fscanf(ARCH,"%f",cp + i++);
}
Ejercicios
375
Fundamentos de informática. Programación en Lenguaje C
fclose(archivo);
for(i = 0 ; i < 26 ; i++) suma += letra[i];
for(i = 0 ; i < 26 ; i++)
{
printf("[ %c ]= %10ld\t",(char)(i+’A’),letra[i]);
printf("%7.2lf\n",((float)letra[i]/suma)*100);
}
376
Capítulo 13. Gestión de archivos.
La pega es que con este código no sumamos las veces que aparecen las
vocales con acento, o la letra ‘u’ con diéresis. Y, desde luego, no
calculamos cuántas veces aparece la letra ‘Ñ’ ó la letra ‘ñ’. Para poder
hacer esos cálculos, deberemos modificar el programa añadiendo
algunas instrucciones:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void main(void)
{
long letra[27];
short caracter;
long suma = 0;
short int i;
FILE *archivo;
377
Fundamentos de informática. Programación en Lenguaje C
fclose(archivo);
for(i = 0 ; i < 27 ; i++) suma += letra[i];
for(i = 0 ; i < 26 ; i++)
{
printf("[ %c ]= %10ld\t",(char)(i+’A’),letra[i]);
printf("%7.2lf\n",((float)letra[i]/suma)*100);
}
printf("[ %c ] = %10ld\t", 165,letra[26]);
printf("%7.2lf\n",((float)letra[26] / suma) * 100);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
unsigned long clave;
378
Capítulo 13. Gestión de archivos.
char descr[50];
double cred;
}asignatura;
short mostrar_opciones(void);
void error(void);
short anyadir(char*);
short pantalla(char*);
short impresora(char*);
void main(void)
{
char nombre_archivo[80];
short opcion;
short oK;
printf("Nombre del archivo de asignaturas ... ");
gets(nombre_archivo);
do
{
opcion = mostrar_opciones();
switch(opcion)
{
case '1': oK = anyadir(nombre_archivo);
if(oK) error();
break;
case '2': oK = pantalla(nombre_archivo);
if(oK) error();
break;
case '3': oK = impresora(nombre_archivo);
if(oK) error();
break;
case '4': exit(1);
}
}while(1);
}
short mostrar_opciones(void)
{
char opcion;
clrscr();
printf("\n\n\t\tOpciones y Tareas");
printf("\n\n\t1. Añadir nueva asignatura.");
printf("\n\t2. Mostrar listado por pantalla.");
printf("\n\t3. Mostrar listado en archivo.");
printf("\n\t4. Salir del programa.");
printf("\n\n\t\t\tElegir opcion ... ");
do opcion = getchar(); while(opcion <'0'&&opcion >'4');
return opcion;
}
void error(void)
379
Fundamentos de informática. Programación en Lenguaje C
{
printf("Error en la operacion de acceso disco.\n");
printf("Pulse una tecla para terminar ... \n");
getchar();
exit(1);
}
ARCH = fopen(archivo,"a+b");
rewind(ARCH);
while(fread(&asig,sizeof(asig),1,ARCH) == 1)
{
printf("\n\nClave ......... %lu",asig.clave);
printf("\nDescripcion ... %s",asig.descr);
printf("\nCreditos ...... %6.1lf",asig.cred);
}
printf("\n\n\tPulsar una tecla para continuar ... ");
getchar();
if(ferror(ARCH)) return 1;
fclose(ARCH);
return 0;
}
380
Capítulo 13. Gestión de archivos.
asignatura asig;
ARCH1 = fopen(archivo,"rb");
ARCH2 = fopen("impresora","w");
while(fread(&asig,sizeof(asig),1,ARCH1) == 1)
{
fprintf(ARCH2,"\n\nClave\t%lu", asig.clave);
fprintf(ARCH2,"\nDescripcion \t%s", asig.descr);
fprintf(ARCH2,"\nCreditos\t%6.1lf", asig.cred);
}
printf("\n\n\tPulsar una tecla para continuar ... ");
getchar();
if(ferror(ARCH1)) return 1;
fclose(ARCH1);
fclose(ARCH2);
return 0;
}
381
Fundamentos de informática. Programación en Lenguaje C
como “rb” para evitar el error en caso de que el usuario quiera leer un
archivo inexistente.
382