Professional Documents
Culture Documents
tratamiento de la información.
tratables como un todo, al mismo tiempo que cada uno de sus elementos es
capítulo.
5.1 ARRAYS
Un array es una colección de datos del mismo tipo -exceptuando el tipo void- que
dos dimensiones podríamos imaginarlo como una tabla en la que los elementos
dimensiones. Son los corchetes los que le indican al compilador que se trata
extern int vector [ ]; /* declaración del array vector; sus elementos son de tipo int y
la definición actual del vector tiene que estar hecha en otro fichero
fuente */
#define TAM 6
int a[2][3][4][5][TAM]; /* declaración de un array de cinco dimensiones */
Como vemos en este último ejemplo, el tamaño de una de las dimensiones puede
venir determinado tanto por un literal como par un identificador creado con una
directiva define, siempre que sea entero. Nunca se podrá utilizar para este fin
una variable.
ordinal dentro del conjunto. Este número de orden indicará al compilador cuantos
inicial del array, es decir, servirá para que el compilador construya las
por tanto, desde el 0 para el primer elemento hasta n-1 para el último, siendo n
del tipo base, como ya sabemos, los desplazamientos provocados por los índices
dos bytes, pero por ejemplo, el tipo base es una estructura compleja, avanzar
los índices introducidos por el programador. Estos índices podrán ser tanto una
ocupación de diez números enteros, desde la dirección inicial del vector. En esa
posición existirá algún valor sin significado para nuestro programa, pero que se
presentará en la pantalla.
separadas por comas cuyo tipo sea compatible con el tipo base del array.
dimensiones, por lo que sería recomendable editarlo del modo más claro posible.
int valores[2][3]={
5, 9, 32,
27, 6, 81};
o bien
int valores[2][3]= {{5, 9, 32}, {27, 6, 81}};
Cuando se inicializa un array de enteros con menos números que los que podría
encargado de calcular el espacio necesario para almacenar los valores. Con este
array.
que el compilador pueda saber que en este caso existen dos filas, cada una de
Debemos tener presente que los valores de un array, sea de una o más
anterior array de dos dimensiones, una tabla, podríamos visualizarla como sigue:
10 12 14 16 18 20
El compilador es capaz de distinguir las filas de ese array siempre que se declare
su final. Así las funciones que trabajen con ellas podrán recorrerlas hasta
posiciones para una cadena de caracteres deberán incluir una más para el
De esta forma, una inicialización semejante a la que veíamos para los números
char cadena[14]={ 'P', 'r', 'o', 'g', 'r', 'a', 'm', 'a', ' ', 'e', 'n', ' ', 'C', '\0'};
Pero también las cadenas de caracteres podrán ser inicializadas sin delimitar,
Ejemplos:
255.
/*****************************************************************
inverso.c
Programa que introduce números reales en un array y los muestra en orden
inverso al de lectura.
**********************************************************************/
#include <stdio.h>
#define N 10
void main(void)
{
double num[N];
int i;
printf(―\n \nLECTURA DE %d NUMEROS REALES Y PRESENTACION EN
ORDEN INVERSO\n\n", N);
printf(―%.2lf/‖,num[i]);
256.
/**********************************************************************
enmedio.c
Programa que lee números enteros del teclado en un array. La entrada de
datos finalizara cuando se introduzca el número 0 y el resultado será el
número que se encuentra en la mitad de los leídos ( si son dos los que se están
en la mitad. entonces se escribirán ambos números).
************************************************************************/
#include <stdio.h>
#define TAM 15
void main(void)
scanf("%d",&n);
num[i++]=n;
if(i==TAM)
else{
scanf("%d",&n);
}
if(i!=0)
if(i%2==0)
else
puede realizar por valor o por dirección. El lenguaje C no permite pasar como
pasarlo por valor. Sera necesario entonces pasar como argumento un puntero al
array con el que queremos que la función trabaje. El lenguaje C nos facilita
esta operación haciendo que la simple invocación del nombre de un array
p=&enteros[0];
p=enteros;
función(&enteros[0]);
función(enteros);
Vemos a continuación un sencillo ejemplo en el que se trabaja con un array de
números enteros que es enviado come argumento a dos funciones, una que le
257.
/**********************************************************************
pasoarra.c
Programa que prueba el paso de arrays entre funciones.
**********************************************************************/
#include <stdio.h>
#define MAX 10
void main(void)
{
int valores [MAX];
printf("\n\nPRUEBA DEL PASO DE ARRAYS ENTRE FUNCIONES\n\n");
printf("Introduzca un máximo de %d números naturales (<0 para acabar)\n",
MAX);
introducir_valores(valores);
printf("Los valores introducidos fueron:\n");
ver_valores(valores);
}
/**********************************************************************
void introducir_valores(int *valores)
Función que recibe un puntero al array de enteros y modifica sus valores.
**********************************************************************/
void introducir_valores(int *valores)
{
int i=-1;
do {
i++;
printf("Valor natural %d: ", i);
scanf("%d", &valores[i]);
} while (i<MAX-1 && valores[i]>=0);
}
/**********************************************************************
void ver_valores(int valores[ ])
Función que recibe un puntero al array de enteros y presenta en pantalla sus
valores.
**********************************************************************/
void ver_valores(int valores[ ])
{
int i=0;
while(i<MAX && valores[i]>=0) {
printf("Valor natural %d: %d\n", i, valores[i]);
i++;
}
}
Cuando se hace la definición formal de las funciones que recibirán ese puntero,
entero; el saber que se trata de un vector y el controlar sus límites serán tareas
del programador.
Ahora podemos ver claramente cual es la relación directa que existe entre la
sumar el valor del índice del elemento al puntero de inicio del vector, para
principal.
Por lo que ya sabemos, podemos deducir que una cadena no será más que un array
cadena habrá que prever el espacio que ocupara este símbolo de fin.
De entre las funciones definidas en el fichero de cabecera <stdio.h> veremos las
strlen, strcat, strncat, strchr, strrchr, strstr, strcmp, strncmp, strcpy, strncpy,
strpbrk, strspn y strtok, definidas en el fichero <string.h> y strtod, strtol,
strtoul, atoi, atof y atol definidas en el fichero de cabecera <stdlib.h>.
/**********************************************************************
gets.c
Acepta caracteres de la entrada estándar para dejarlos en una cadena y después
presentarlos uno a uno en la pantalla.
**********************************************************************/
#include <stdio.h>
#define MAX 50
void main(void)
{
unsigned char cadena[MAX];
int i;
Esta otra función es una alternativa a printf para la presentación de caracteres en la salida
estándar –generalmente la pantalla-.presenta la cadena de caractres s seguida del carácter de
nueva línea. Si ocurre algún error devolverá el valor EOF, en otro caso, un valor no negativo.
263.
/**********************************************************************
puts.c
presenta caracteres en la salida estándar.
**********************************************************************/
#include <stdio.h>
int main(void)
{
unsigned char cadena[ ]="Bienvenidos a nuestro programa de gestión";
Sirve al igual que scanf, para permitir una entrada con formato , pero en este
caso esa entrada es tomada del array cadena.
264.
/****************************************************************************
sprintf.c
Da formato a un texto que se almacena en una cadena de caracteres.
****************************************************************************/
#include <stdio.h>
#define MAX 50
int main(void)
int dia=14;
gets(nombre);
puts(destino);
265.
/****************************************************************************
strlen.c
Presenta en pantalla la longitud de una cadena de caracteres tecleada.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 50
void main(void)
unsigned longitud;
gets(texto);
longitud = strlen(texto);
266.
/****************************************************************************
strchr.c
Presenta la parte final de una cadena de caracteres a partir del car cter '@'.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 50
void main(void)
{
char texto[MAX],*puntero;
267.
/****************************************************************************
strcat.c
Presenta en pantalla la unión de dos cadenas de caracteres tecleadas, separadas
por el carácter '+'.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 50
void main(void)
gets(texto1);
gets(texto2);
strcat(texto1, "+");
strcat(texto1, texto2);
lenguaje no comprobará los límites de los arrays, y, de ser necesario, ese trabajo
268.
/****************************************************************************
strstr.c
Encuentra la palabra “autor” dentro de una cadena de caracteres.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 50
int main(void)
printf(":\n",MAX);
gets(texto);
if (puntero)
printf("%s\n", puntero);
else
269.
/****************************************************************************
strcmp.c
Compara una cadena de caracteres tecleada con otra introducida en el programa.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 9
int main(void)
scanf("%s", texto);
if (strcmp(texto, "invitado"))
else
En este pequeño programa se utiliza la función strcmp para comparar una cadena
de caracteres introducida por el teclado con otra que sirve como clave. En caso
char*strcpy(char*s,char*t)
Esta es, por tanto, la función con la que realizaremos las operaciones de
asignación de valores a las cadenas de caracteres. El operador de
asignación, '=', sólo se podrá utilizar en el momento de la inicialización de
la cadena, nunca posteriormente.
int main(void)
{
char destino[MAX], origen[MAX];
printf("\n\nCOPIA DE CADENAS\n\n");
printf("Introduzca una cadena de caracteres (de menos de %d caracteres): ",MAX);
gets(origen);
strcpy(destino, origen);
printf("El destino (%s) y el origen (%s) deberían ser iguales", destino, origen);
}
Función que sirve para encontrar las partes de s delimitadas por caracteres de t.
#include <string.h>
#define MAX 50
int main(void)
printf("\n\nUSO DE STRTOK\n\n");
gets(entrada);
nombre=strtok(entrada, delimitadores);
ap1=strtok(NULL, delimitadores);
ap2=strtok(NULL, delimitadores);
printf("\nNombre: %s, apellido 1º: %s, apellido 2º: %s. \n", nombre, ap1, ap2);
}
double strtod(const char*s, char**resto)
[espacios][signo][digitos][.][digitos][e/E[signo]digitos].
conversión de tipos. Las funciones strtod y strtol tienen una gran potencia y
272.
/****************************************************************************
atoi.c
Programa que transforma un argumento compuesto de caracteres en un entero.
Comprueba que le sea proporcionado un único argumento y, si es posible lo convierte
en un entero, presentando los números enteros comprendidos entre el 0 y el
argumento -1.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int i;
if (argc==1)
else
if(argc>2)
else
for (i=0;i<atoi(argv[1]);i++)
printf("%d\n", i);
273.
/****************************************************************************
unirnum.c
Unir cantidades numéricas (que no ocupen más de una línea) tecleadas en la línea de
comandos, para formar una nueva cantidad numérica.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int i;
char numero[81]="";
double resultado;
if (argc <2)
else
{
for (i=1;i<argc;i++)
strcat(numero,argv[i]);
resultado=atof(numero);
una función para la búsqueda binaria, bsearch, que utiliza parámetros muy
282.
/****************************************************************************
buscarb.c
Búsqueda binaria en un array de enteros utilizando la función bsearch. El array en
el que se busca deberá estar ordenado ascendentemente.
****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
int main(void)
int dato;
scanf("%d", &dato);
if (buscar(dato))
else
/****************************************************************************
int buscar(int elemento)
Función que realiza la llamada a bsearch y devuelve el resultado de la búsqueda.
****************************************************************************/
{
int *itemptr;
itemptr = bsearch (&elemento, nums, 6, sizeof(int), (int(*)(const void *,const void *))
orden);
/****************************************************************************
int orden (const int *dato1, const int *dato2)
Función que hace la comparación entre el dato buscado y cada uno de los elementos
del array de enteros. Esta función devolverá un número negativo si dato 1 es menor
que dato 2, un número positivo si es mayor y 0 en caso de igualdad.
****************************************************************************/
return(*dato1 - *dato2);
Resulta evidente que los tipos de datos básicos no cubren todas las posibles
necesidades en el tratamiento de información compleja. Por ello veremos ahora
diferentes agrupaciones de tipos básicos, la forma de emplearlas y su utilidad
dentro de los programas.
5.5.1 Estructuras
Los ejemplos de la vida real que se podrían utilizar para ilustrar el concepto de
estructura son múltiples. Imaginemos que queremos almacenar y tratar la fecha
y hora de algún tipo de suceso. Podemos reservar variables individuales para el
día, el mes, el año, la hora, el minuto y el segundo, o bien podemos facilitar el
tratamiento creando una estructura que agrupe todos esos datos bajo un único
nombre, por ejemplo, momento.
¿Cuál es entonces la ventaja de las estructuras? Que nos permiten manejar con
comodidad colecciones complejas de información heterogénea pero relacionada.
Por ejemplo, podemos hacer asignaciones de toda la estructura, copiarla o
pasarla como argumento de una función, pero también referirnos a cualquiera de
sus elementos individuales.
solo:
struct momento { int dia, mes, ano, hor, min, sec¡ inicio, fin;
tipos de datos base o de otros creados por el programados Los arrays son, por su
extensa utilidad, elementos que casi siempre formarán parte de las estructuras.
struct empleado {
int trienios;
int edad;
};
Decíamos antes que una de las ventajas de las estructuras es que podemos
jefe 1. trienios = 6;
gets(jefel. nombre);
jefe2=jefel;
Asignará los valores de los campos de la variable jefe1 a los campos de jefe2, es
Arrays de estructuras
Probablemente el uso más común de las estructuras es el de formar parte de un
conjunto de empleados. Como cada uno de esos elementos individuales tiene una
y que hacen referencia a un mismo objeto — en este caso información sobre una
array de estructuras.
Por ejemplo, para declarar un array de estructuras en las que sea posible
deberíamos hacer:
struct competidor {
int dorsal;
int edad;
ejemplo que sirva para manejar la información sobre una competición deportiva.
El programa permite simplemente introducir información sobre los participantes,
realiza previamente una llamada a otra función que busca el primer hueco en la
lista. De esta forma se ocuparán las posiciones dejadas por los participantes
283.
/****************************************************************************
compiten.c
Sencillo programa que utiliza una array de estructuras para llevar el control de una
lista de participantes en una competición deportiva.
No se controla que se introduzcan números de dorsal repetidos.
****************************************************************************/
#include <stdio.h>
#include <string.h>
struct competidor {
int dorsal;
int edad;
};
void introducir(void);
void borrar(void);
void listar(void);
int buscar_libre(void);
int menu(void);
void main(void)
int opcion;
do {
opcion=menu();
switch(opcion){
case 1: introducir();
break;
case 2: borrar();
break;
case 3: listar();
break;
} while (opcion);
/****************************************************************************
int menu(void)
Función que presenta el menú de opciones y devuelve la seleccionada por el usuario.
****************************************************************************/
int menu(void)
int opcion;
printf("\n\nCONTROL DE PARTICIPANTES EN UNA COMPETICIÓN
DEPORTIVA\n\n");
printf("0. Salir\n");
do {
scanf("%d", &opcion);
} while(opcion<0 || opcion>3);
return opcion;
/****************************************************************************
void introducir(void)
Función que permite introducir un nuevo participante. Previamente hará una llamada
a la función buscar_libre para comprobar si existe espacio y, en ese caso, cuál es
la primera posición libre.
****************************************************************************/
void introducir(void)
int lugar;
lugar=buscar_libre();
if (lugar==MAX)
else {
scanf("%c",&car); /* elimina el \n almacenado en el teclado */
gets(participantes[lugar].nombre);
gets(participantes[lugar].apellido);
printf("Dorsal: ");
scanf("%d", &(participantes[lugar].dorsal));
printf("Edad: ");
scanf("%d", &(participantes[lugar].edad));
/****************************************************************************
int buscar_libre(void)
Función que encuentra la primera posición libre, si es que existe.
************************************************************************************/
int buscar_libre(void)
{
register int n;
/****************************************************************************
void borrar(void)
Función que permite eliminar un participante colocando el valor nulo en el nombre.
****************************************************************************/
void borrar(void)
register int n;
if (participantes[n].dorsal==dorsal) {
participantes[n].nombre[0]='\0';
encontrado=1;
if (encontrado)
printf("Participante borrado");
else
printf("Dorsal no encontrado");
/****************************************************************************
void listar(void)
Función que presenta en pantalla la lista de participantes.
****************************************************************************/
void listar(void)
register int n;
if (participantes[n].nombre[0]) {
printf("%d\n", participantes[n].edad);
}
Estructuras anidadas
Cuando una estructura forma parte de otra decimos que estamos ante una
estructura anidada.
Para ilustrar esta idea podemos completar el ejemplo anterior. Ahora, queremos
entonces:
struct domicilio {
int num;
};
struct competidor {
int dorsal;
int edad;
};
deberíamos escribir:
puts(participantes[4].direccion.calle);
el primer caso la función crea una copia interna y temporal del argumento para
trabajar con él, copia que desaparece cuando la función acaba. En el segundo caso
Cuando pasamos una estructura de tamaño importante habrá que tener en cuenta
las estructuras por dirección para conseguir una ejecución más rápida y, por
pantalla directamente el array de estructuras sino que haga una llamada a una
esto evitamos la sobrecarga que supondría para la pila del programa el paso de la
estructura completa.
{
printf("%s ", c->nombre);
printf("%s /", c->apellido);
printf("%d /", c->dorsal);
printf("%d\n", c->edad);
}
}
5.5.2 Enumeraciones
Una enumeración en lenguaje C no es más que una agrupación, bajo un nombre
posibles para una variable que se declare de ese nuevo tipo. Las enumeraciones
reserva espacio de memoria hasta que existan variables que se declaren de ese
tipo.
enum dias {lunes, martes, miércoles, jueves, viernes};
declaración que, como siempre, podrá ser resumida en una única instrucción:
y podrá tomar valores de entre los enumerados. Así, serían válidas sentencias
como:
hoy = jueves;
294.
/****************************************************************************
enum.c
Ejemplo de utilización de una enumeración que presenta la duración de las distintas
jornadas laborales.
****************************************************************************/
#include <stdio.h>
void main(void)
scanf("%d", &hoy);
hoy--;
switch(hoy) {
case lunes:
case martes:
case miercoles:
case 3:
case viernes:
printf("8 horas\n");
break;
case sabado:
printf("5 horas\n");
break;
case 6:
printf("0 horas\n");
break;
Se resalta así que no hay que confundir las etiquetas de una enumeración con
textos imprimibles. Esas etiquetas no son más que símbolos que el compilador
momentos.
Hemos declarado una variable ent_y_char para la que el compilador reservará los
bytes que ocuparía un número entero, por ser mayor que un char.
puntero a ella.
haríamos:
ent_y_char.i = 10;
p->i=10;
Las uniones son útiles para interpretar de diferentes modos una representación
de tipos
ser necesaria en muy diferentes ocasiones: para almacenar en un solo byte varias
variables que puedan tomar valor verdadero o falso, para trabajar con
dispositivos que emiten o reciben información en bits o, por ejemplo, para algunas
Con los campos de bits estas operaciones se podrán realizar con eficiencia al
mismo tiempo que se genera un código fuente claro y estructurado. Para realizar
En realidad, los campos de bits no son más que un caso particular de las
elemento particular.
Imaginemos que queremos controlar directamente desde nuestro programa el
Si suponemos que existe una función capaz de preguntar por el estado del
estado = obtener_estado();
estructuras normales:
struct competidor
{
unsigned char nombre[20];
unsigned char apellidos[50];
int dorsal;
int edad;
unsigned federado: 1;
unsigned sexo: 1
unsigned prueba: 6;
};
En este ejemplo se utiliza un único byte para almacenar tres elementos de
5.5.5 Typedef
Esta palabra reservada de C en realidad no sirve para crear un nuevo tipo de
La utilidad del uso de typedef está, por una parte, en que puede colaborar a la
máquinas con diferencias de tamaño en los tipos básicos. SÍ, por ejemplo,
definimos:
variables de tipo int. Si en algún momento necesitamos otro tipo para todas esas
Por otra parte, typedef puede colaborar claramente en hacer más legibles los
de datos.
numero i, valor, x;
Otra aplicación útil de esta sentencia es la de simplificar y hacer más legibles las
5.6 EJERCICIOS
285.
/****************************************************************************
apuest.c
Visualiza varias apuestas de la loter¡a primitiva en la pantalla.
Cada apuesta de loter¡a primitiva son seis n£meros diferentes comprendidos
entre 1 y 49.
El numero de apuestas se leer desde el teclado.
****************************************************************************/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void apuesta(void);
void main(void)
{
int i, na;
srand(time(NULL));
scanf("%d",&na);
for(i=1;i<=na;i++)
apuesta();
/****************************************************************************
void apuesta(void)
Funci¢n que presenta en pantalla cada una de las apuestas aleatorias.
****************************************************************************/
void apuesta(void)
int i=0,n,lot[49]={0};
while(i<6)
n=rand()%49;
if(!lot[n])
lot[n]=1;
i++;
printf("\n");
for(i=0;i<49;i++)
if(lot[i])
286.
/**********************************************************************
apuest2.c
Visualiza varias apuestas de la loter¡a primitiva en la pantalla.
En este caso las funciones reciben un puntero a un array de numeros
enteros como argumento.
**********************************************************************/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void main(void)
int i,na,lot[6];
srand(time(NULL));
scanf("%d",&na);
apuesta(lot);
visapuesta(lot);
/**********************************************************************
void apuesta(int lot[ ])
Funci¢n que llena el array con los n£meros de cada una de
las apuestas aleatorias.
**********************************************************************/
void apuesta(int lot[ ])
int i=0,j,n,enc;
while(i<6){
enc=0;
j=0;
if(lot[j]==n)
enc=!enc;
else
j++;
lot[j]=n;
i++;
}
/**********************************************************************
void visapuesta(int lot[ ])
Funci¢n que presenta en pantalla el array de cada una de las apuestas.
**********************************************************************/
void visapuesta(int lot[ ])
int i;
printf("\n");
for(i=0;i<6;i++)
287.
/****************************************************************************
cuentac.c
Programa que cuenta las apariciones de un carácter dentro de una cadena de
caracteres, leídos ambos desde la entrada estándar.
****************************************************************************/
#include <stdio.h>
#include <string.h>
#define MAX 50
void main(void)
int i, veces=0;
gets(cadena);
scanf("%c", &caracter);
if(cadena[i]==caracter) veces++;
288.
/****************************************************************************
media.c
Programa que calcula el valor medio de un conjunto de valores enteros.
****************************************************************************/
#include <stdio.h>
#define MAX 10
void main(void)
float suma = 0;
scanf("%d", &nvalores);
if (nvalores<1)
nvalores=1;
if (nvalores>MAX)
nvalores=MAX;
scanf("%d", &valores[i]);
suma += valores[i];
289.
/****************************************************************************
sobremed.c
Programa que presenta los valores de un conjunto de enteros que estan
por encima de la media.
****************************************************************************/
#include <stdio.h>
#define MAX 10
void main(void)
{
scanf("%d", &nvalores);
if (nvalores<1)
nvalores=1;
if (nvalores>MAX)
nvalores=MAX;
scanf("%d", &valores[i]);
suma += valores[i];
if (valores[i]>media)