Está en la página 1de 62

EJERCICIOS DE LA ASIGNATURA

"PROGRAMACIÓN"

PROGRAMAS LARGOS RESUELTOS Y COMENTADOS

Escuela Politécnica Superior


Universidad de Alcalá

GRADO EN INGENIERIA EN TECNOLOGIAS DE LA TELECOMUNICACION (GITT)


GRADO EN INGENIERIA EN SISTEMAS DE TELECOMUNICACION (GIST)
GRADO EN INGENIERIA ELECTRONICA DE COMUNICACIONES (GIEC)
GRADO EN INGENIERIA TELEMATICA (GIT)

INDICE

1. EMPRESA DE COMPONENTES ELECTRÓNICOS


2. HÁBITOS DE CONSUMO DE BEBIDAS
3. CONSURSO DE CANCIONES DE RADIO
4. CONSUMO DE SURTIDORES EN GASOLINERA
5. ESTADÍSTICA DE ENERGÍAS EN CENTRAL ELÉCTRICA
6. ESTADÍSTICA DE VENTAS EN UNA TIENDA
7. CONTROL DE PEAJES EN AUTOPISTA
8. APLICACIÓN DE BASE DE DATOS

Más ejercicios similares AQUÍ


Los ejercicios originales proceden de los profesores M. Carmen Ocariz Sanz, Montserrat Ferreira,
Rosa Arruabarrena Santos y Olatz Ansa Osteriz, de la Universidad del País Vasco, y han sido
ampliados y verificados por el profesor Antonio Guerrero Baquero de la UAH.

Todos los programas han sido comprobados y compilados con el compilador Quick-C 2.5 de
Microsoft bajo sistema operativo Windows de 32 bits. Puede descargar este compilador AQUÍ.
Una vez descargado y descomprimido en la carpeta C:\QC25, abra la ventana de comandos del
sistema operativo, sitúese en la carpeta C:\QC25\PROGRAMS y ejecute el compilador CL.BAT.
Ejemplo: CL BASEDAT.C (el ejecutable se llamará BASEDAT.EXE).

Fecha Actualización: 19/11/2015


EMPRESA DE COMPONENTES ELECTRÓNICOS
En una empresa de montaje de aparatos electrónicos se desea un programa que calcule ciertas
características de los productos de la empresa. La empresa monta 10 tipos diferentes de aparatos
electrónicos, con código de 0 a 9, cada uno de los cuales incluye un número de componentes diferentes. En
total la empresa utiliza 20 componentes electrónicos diferentes, con código de 0 a 19. Cada aparato puede
tener una o más unidades de cada uno de los componentes que lo forman.
Hay que construir un programa que realice las siguientes funciones:
1. En primer lugar se procederá a la lectura de los datos que indican cuáles y cuántos son los componentes
de cada aparato electrónico. El usuario introducirá los datos relativos a los 10 aparatos, indicando primero
para cada aparato el número de componentes que tiene.
2. A continuación, el programa leerá el número de unidades que se montan mensualmente de cada aparato.
3. Para realizar los pedidos mensuales correspondientes, se debe contabilizar el número de componentes
que se necesitan cada mes y escribirlos en la pantalla.
4. Finalmente el programa deberá identificar el componente eléctrico que más se utiliza.

Ejemplo: (en negrita los datos introducidos por el usuario)


Apartado 1)
Introduce los componentes de cada aparato:

Número de componentes del Aparato 0: 3


Código del Componente 1 (0 a 19): 1
Número de unidades del componente 1: 5
Código del Componente 2 (0 a 19): 3
Número de unidades del componente 2: 12
Código del Componente 3 (0 a 19): 19
Número de unidades del componente 3: 1

Número de componentes del Aparato 1: 20


Código del Componente 1 (0 a 19): 1
Número de unidades del componente 1: 3
Código del Componente 2 (0 a 19): 3
Número de unidades del componente 2: 5
...
Código del Componente 20 (0 a 19): 19
Número de unidades del componente 20: 2
...
Número de componentes del Aparato 9: 1
Código del Componente 1 (0 a 19): 15
Número de unidades del componente 1: 12

Apartado 2)
Introduce el número de aparatos montados mensualmente:
Aparato 0: 100
Aparato 1: 1000
Aparato 2: 200
...
Aparato 9: 300

Apartado 3)
Número de unidades de cada componente utilizados mensualmente:
Componente 0: 100
Componente 1: 300
Componente 2: 500
...
Componente 99: 100

Apartado 4)
El componente electrónico 7 es el más utilizado, se necesitan 10000 unidades.
ANÁLISIS DEL PROBLEMA

Constantes del enunciado:


1. NumAparatos=10. Es el número de aparatos distintos que se montan en la empresa.
2. NumComponentes=20. Es el número de componentes electrónicos que se utilizan para montar los
diferentes aparatos.

Variables necesarias para la entrada:


3. Necesitaremos una matriz (array bidimensional) llamado desglose de NumAparatos X NumComponentes
posiciones para almacenar por cada aparato los componentes electrónicos que contiene, de manera que el
elemento desglose[a][c] indicará el número de unidades del componente c que tiene el aparato a.

desglose: 0 1 2 ….. NumComponentes-1 <=


COMPONENTE
0 4 3 1
1 2 5
… 2
NumAparatos-1 1 2 3
APARATO

4. Necesitaremos un array montajes de NumAparatos posiciones para almacenar por cada aparato el
número de montajes que se hacen del mismo cada mes.

montajes: 0 1 2 ….. NumAparatos-1 <= APARATO


100 200 150 200

Variables necesarias para los resultados:


5. Necesitaremos un array totales de NumComponentes posiciones para almacenar por cada componente el
número total del citado componente que se requiere para montar todos los aparatos pedidos de un mes.

totales: 0 1 2 ….. NumComponentes-1 <=


COMPONENTE

Pasos a seguir en la resolución del problema:


1. Inicializar el array desglose a 0, ello indicará que cada aparato inicialmente no tiene componente alguno
asociado.

2. Leer ordenadamente la composición de todos los aparatos:


a. Por cada aparato primeramente leer el número de componentes que lo contienen, en la variable
TieneComp.
b. Posteriormente uno a uno leer y registrar en el array desglose los TieneComp códigos de los
componentes concretos del aparato y el número de unidades de dicho componente. Para registrar que un
aparato a tiene num unidades de un componente de código Comp, se almacena en la celda desglose[a]
[Comp] el valor num.

3. Leer por cada aparato cuántos aparatos se van a montar en un mes, registrando dichos valores en el array
montajes.

4. Calcular en el array totales por cada tipo de componente cuántos componentes se van a emplear entre
todos los montajes de todos los aparatos, combinando para ello los datos del array desglose y el array
montajes.
Para determinar el número de componentes de tipo c que se necesitarán en un mes y registrarlo en
totales[c]:
a. Se inicializa a 0 el acumulador totales[c].
b. Por cada tipo de aparato a se calcula el número de componentes de tipo c que se emplearán en un mes
para montar todos los aparatos a: desglose[a][c]*montajes[a], ya que si el aparato a no contiene el
componente c entonces desglose[a][c] tendrá el valor 0. El número calculado de componentes c que se
emplearán en los montajes de los aparatos se acumula en totales[c].
Los dos pasos anteriores se repiten por cada tipo de componente c y se muestra en pantalla.
5. Para calcular el componente más empleado, basta con determinar en qué posición está el valor máximo
del array totales:
a. Inicialmente considerar que el primer valor del array totales es el máximo hasta el momento (posMax).
b. Con el resto de componentes (sea c el índice para denotar cada uno de ellos), se repite una y otra vez:
I. Se comprueba si el número de componentes totales de tipo c es mayor que el máximo hasta el
momento: totales[c]>totales[posMax].
II. Si es mayor, se actualiza la posición en la que se ubica el nuevo máximo, es decir, la variable
posMax con el componente actual c.
c. Se imprime un mensaje en pantalla indicando que el componente posMax es el componente más
empleado, utilizándose un total de totales[posMax] unidades.

CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumAparatos 10
#define NumComponentes 20
main()
{
int desglose[NumAparatos][NumComponentes];
int montajes[NumAparatos], totales[NumComponentes];
int a, c, totalComp, nc, posMax, num;
// Inicializar desglose: ningún componente por aparato
for (a = 0; a<NumAparatos; a++)
{ for(c = 0; c<NumComponentes; c++)
{ desglose[a][c]=0; }
}
// Lectura de los componentes de cada uno de los aparatos
system("CLS"); //borrar pantalla
printf("Introduce los componentes de cada aparato:\n");
for (a = 0; a<NumAparatos; a++)
{ printf("\nNumero de componentes del aparato %d: ",a); scanf("%d", &totalComp); fflush(stdin);
for (nc = 1; nc<=totalComp; nc++)
{ printf("Codigo del Componente %d (0 a %d): ", nc, NumComponentes-1); scanf ("%d", &c); fflush(stdin);
printf(" Numero de unidades del componente %d: "); scanf("%d", &num); fflush(stdin);
desglose[a][c]=num; //El aparato a tiene num unidades del componente c.
}
}
// Lectura de los aparatos montados mensualmente
printf("\nIntroduce el numero de aparatos montados mensualmente:\n");
for (a = 0; a<NumAparatos; a++)
{ printf("Aparato %d: ",a); scanf("%d", &montajes[a]); fflush(stdin); }
// Cálculo del número de componentes mensuales
printf("\nNumero de componentes utilizados mensualmente:\n ");
for (c = 0; c<NumComponentes; c++)
{ totales[c]=0;
for (a=0; a<NumAparatos; a++)
{ totales[c] = totales[c] + desglose[a][c] * montajes[a]; }
printf("Componente %d: %d\n", c, totales[c]);
}
// El componente más empleado entre todos los montajes del mes.
posMax = 0; //posicion donde se encuentra el valor máximo del array hasta el momento
for (c=1; c<NumComponentes; c++)
{ if (totales[c]>totales[posMax]) posMax=c; } //nueva posicion de un Nuevo máximo encontrado
printf("\nEl componente electronico %d es el mas utilizado, se necesitan %d unidades.\n\n", posMax,
totales[posMax]);
system ("PAUSE"); //mensaje "Pulse una tecla para continuar"
}
AMPLIACIONES PROPUESTAS

1. Al finalizar el programa, salvar el array desglose en un fichero en disco de nombre "compon1.dat" y el


array montajes en otro fichero "compon2.dat".

2. Si al entrar al programa existen en el disco los ficheros anteriores, cargarlos en los arrays, mostrarlos en
pantalla y preguntar si se desea modificar alguno de sus datos (ya no es necesario introducirlos todos de
nuevo).

3. Realizar la introducción de componentes de cada aparato mediante una función específica leeAparato().
que reciba como argumento de entrada el array bidimensional desglose.

4. Emitir el listado de componentes utilizados mensualmente también en un fichero de texto en disco de


nombre listado.txt, para que pueda ser posteriormente imprimido por la impresora o enviado a los
proveedores.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#define NumAparatos 10
#define NumComponentes 20
// Declaraciones prototipo de funciones auxiliares
void leeAparato(int a, int desglose[][NumComponentes]);
char sino(char *mensaje);

main()
{
int desglose[NumAparatos][NumComponentes];
int montajes[NumAparatos], totales[NumComponentes];
int a=-1, c, nc, posMax;
char resp;
FILE *pf; //puntero de control de un fichero
system("CLS");
if ((pf=fopen("compon1.dat","rb"))==NULL) //intentamos abrir el fichero de desglose en modo lectura
{ //No existe fichero desglose, inicializar a 0 el array desglose
for (a = 0; a<NumAparatos; a++)
for (c = 0; c<NumComponentes; c++) desglose[a][c]=0;
//Lectura de los componentes de cada uno de los aparatos
printf("Introduce los componentes de cada aparato:\n");
for (a = 0; a<NumAparatos; a++)
{ leeAparato(a, desglose); } //llamada a la función de lectura de los componentes de cada aparato
}
else
{ //Existe el fichero desglose, cargarlo en el array desglose y mostrarlo en pantalla
fread(desglose,sizeof(desglose),1,pf); //leemos todo el array con una única instrucción
fclose(pf); //cerramos el fichero
printf("Desglose de aparatos:"); //Mostrar el desglose de todos los aparatos actuales
for (a = 0; a<NumAparatos; a++)
{ printf("\nAparato %d, Componente/Cantidad: ", a);
for (c = 0; c<NumComponentes; c++)
if (desglose[a][c]>0) printf("%d/%d ", c, desglose[a][c]);
}
//Posible modificación de los datos del desglose de uno o más aparatos
while (1) //bucle infinito, se termina con "break"
{ if (sino("\nDesea modificar los datos de desglose de algun aparato?")=='N') //pide respuesta S/N
break; //salir del bucle
do
{ printf("Indique codigo del Aparato (0 a %d): ", NumAparatos-1); //pedimos aparato a modificar
scanf("%d", &a); fflush(stdin);
} while (a<0 || a>=NumAparatos);
leeAparato(a, desglose); //llamada a la función de lectura de componentes del aparato
}
}
if ((pf=fopen("compon2.dat","rb"))==NULL) //intentamos abrir el fichero de montajes en modo lectura
resp = 'S'; //No existe fichero montajes
else
{ //Existe el fichero montajes, cargarlo en el array montajes
fread(montajes,sizeof(montajes),1,pf); fclose(pf); //leemos todo el array en una única operación
printf("\nMontajes mensuales de los aparatos:"); //Mostrar los montajes actuales
for (a = 0; a<NumAparatos; a++)
printf("\nAparato %d: %d", a, montajes[a]);
resp = sino("\nDesea modificar los datos de montajes mensuales de los aparatos?");
}
if (resp=='S') //si respondimos que sí o si no existía fichero montajes
{ //Introducción del número de montajes mensuales en el array montajes
printf("\nIntroduce el numero de aparatos montados mensualmente:\n");
for (a = 0; a<NumAparatos; a++)
{ printf("Aparato %d: ",a); scanf("%d", &montajes[a]); fflush(stdin); }
}
//Cálculo del número de componentes mensuales
if ((pf = fopen("listado.txt","w"))==NULL) //abrimos el fichero de texto para listado en disco
printf("\nNo se puede generar listado de componentes en el disco.\n");
else
{ printf("\nNumero de componentes utilizados mensualmente:\n");
fprintf(pf, "Numero de componentes utilizados mensualmente:\n"); //repetimos el texto hacia el fichero
for (c=0; c<NumComponentes; c++)
{ for (totales[c]=a=0; a<NumAparatos; a++)
totales[c] += desglose[a][c]*montajes[a];
if (totales[c]>0)
{ printf("Componente %d: %d\n", c, totales[c]);
fprintf(pf, "Componente %d: %d\n", c, totales[c]); //repetimos el texto hacia el fichero
}
}
fclose(pf); //cerramos fichero de listado en disco
}
//El componente más empleado entre todos los montajes del mes.
for (c=1,posMax=0; c<NumComponentes; c++)
{ if (totales[c]>totales[posMax]) posMax=c; }
printf("\nEl componente electronico %d es el mas utilizado, se necesitan %d unidades.\n\n", posMax,
totales[posMax]);
//Grabar ficheros en disco
if ((pf = fopen("compon1.dat","wb"))==NULL) printf("\nERROR al grabar ficheros.\n");
else { fwrite(desglose,sizeof(desglose),1,pf); fclose(pf); }
if ((pf = fopen("compon2.dat","wb"))==NULL) printf("\nERROR al grabar ficheros.\n");
else { fwrite(montajes,sizeof(montajes),1,pf); fclose(pf); }
system ("PAUSE");
}

//Funcion de lectura de componentes de un aparato.


//Recibe dos argumentos de entrada: el numero del componente a leer (a) y el array desglose
void leeAparato(int a, int desglose[][NumComponentes])
{ int totalComp, c, num, nc, sc;
do
{ printf("\nNumero de componentes del aparato %d: ",a); sc=scanf("%d", &totalComp); fflush(stdin);
} while (sc!=1 || totalComp<0 || totalComp>100);
for (nc=1; nc<=totalComp; nc++)
{ do
{ printf("Codigo del Componente %d (0 a %d): ", nc, NumComponentes-1);
sc=scanf ("%d", &c); fflush(stdin);
} while (sc!=1 || c<0 || c>=NumComponentes);
do
{ printf(" Numero de unidades del componente %d: ", nc); sc=scanf("%d", &num); fflush(stdin);
} while (sc!=1 || num<0 || num>1000);
desglose[a][c]=num; //El aparato a tiene num unidades del componente c.
}
}

//Función de presentación de un mensaje y lectura de una respuesta tipo S/N


//Recibe como argumento de entrada la pregunta a presentar en pantalla
char sino(char *mensaje)
{ char resp;
fflush(stdin);
do
{ printf("%s (S/N): ", mensaje); //presenta el mensaje
resp=toupper(getche()); //lee la respuesta sin necesidad de Enter y la convierte a mayúscula
} while (resp!='N' && resp!='S');
return resp; //devuelve la respuesta pulsada
}
HÁBITOS DE CONSUMO DE BEBIDAS
El Gobierno provincial quiere hacer un estudio de hábitos de consumo de alcohol y bebida entre la juventud
de la provincia. Para ello, ha escogido 20 pueblos donde llevará a cabo la consulta. El ayuntamiento de cada
uno de estos pueblos recogerá el número de litros consumidos durante el pasado año de los 8 tipos de
bebidas nombrados a continuación:

Tipos De Bebidas:
0. Naturales: agua, leche, zumos, mostos, infusiones, ...
1. Gaseosos: Refrescos
2. Vinos
3. Cervezas
4. Whisky
5. Licores
6. Energéticos: Aquarius, Red Bull,...
7. Combinados: Cubatas, GinTonics,..

Mediante un programa en C, se pide realizar un estudio que estará compuesto por los siguientes pasos:

1. Recoger y almacenar la información, para cada pueblo, sobre los litros consumidos de los tipos de bebidas
mencionados. Recuerda que 20 pueblos aportarán información a tu estudio. No obstante, la información no te
la tienen por qué dar ordenada por tipo de bebida o número de litros y puede que de algún tipo de bebida no
se tenga información. Así, será preciso introducir pares de datos (tipo de bebida y litros) y para indicar que no
hay más datos de un pueblo, bastará con introducir como tipo de bebida el texto FIN. Ver ejemplo para cada
uno de los apartados al final del enunciado.

2. Recoger y almacenar cuáles de las clases de bebidas tienen alcohol. Para ello, te dan únicamente la lista
de los tipos de bebidas que contienen alcohol, lista acabada con un texto FIN para indicar que no hay más
tipos de bebida que tengan alcohol. Por ejemplo: 7 2 5 4 3 FIN

3. Determinar el tipo de bebida más consumida entre todos los pueblos, es decir, el tipo de bebida del que
más litros se hayan bebido.

4. Determinar, de los tipos de bebidas con alcohol, cuál es el más consumido.

5. Determinar en qué pueblo se bebe más alcohol en total.

Ejemplo: (En letra normal lo que el programa imprime y en negrita lo que el usuario teclea)
Para comenzar el estudio recogemos los datos por pueblos.
Por cada pueblo: Introduce pares (tipoBebida y litros). Para acabar teclea FIN.

Pueblo 0:
08
47
20
3 50
1 10
FIN

Pueblo 1:
0 18
1 15
40
26
3 36
FIN

Pueblo 2:
5 16
FIN
...
Pueblo 19:
35
1 12
FIN

Ahora necesitamos que enumeres SÓLO los tipos de bebida CON alcohol, teclea FIN para acabar:
7 2 5 4 3 FIN

El tipo de bebida más consumida es la: 3


(Suponiendo que lo que más se ha bebido en litros sean cervezas)

El tipo de bebida con alcohol más consumida es la: 3


(Suponiendo que así sea en litros entre: “combinados”,“vinos”, “licores”, “whiskies” y “cervezas”. En general,
el “tipo de bebida” y el “tipo de bebida con alcohol” más consumidas no tiene por qué coincidir).

El pueblo con mayor consumo de alcohol es: X


(Suponiendo que entre “combinados”, “vinos”, “licores”, “whiskies” y “cervezas”, X sea la población que más
litros haya vendido).

ANÁLISIS DEL PROBLEMA

Constantes del enunciado:


1. NumPueblos=20. Es el número de pueblos con los que se va a hacer el estudio de hábitos de consumo.
2. NumTipoBebidas=8. Es el número de tipos de bebidas.

Representación del las variables necesarias para la entrada:


3. Necesitaremos un array bidimensional consumo de NumPueblos X NumTipoBebidas posiciones para
almacenar, por cada pueblo y por cada tipo de bebida, los litros consumidos, de manera que si consumo[i]
[j]=z indica que el pueblo i ha consumido z litros del tipo de bebida j.

consumo: 0 1 2 ….. NumTipoBebidas-1 <= TIPO DE


BEBIDA
0 20 60 30 40
1 80 90 50 70
… 70 300 400 250
NumPueblos-1 200 180 250 300
PUEBLOS

4. Necesitaremos un array conAlcohol de NumTipoBebidas posiciones para almacenar si el tipo de bebida


es o no alcohólica (1 para indicar que tiene alcohol y 0 en caso contrario).

conAlcohol: 0 1 2 ….. NumTipoBebidas-1 <= TIPO DE


BEBIDA
0 0 1 1

Representación de las varables necesarias para los resultados:


5. Necesitaremos un array consumoXTipo de NumTipoBebidas posiciones para almacenar, por cada tipo de
bebida, el número total de litros consumidos en los NumPueblos de la provincia.

consumoXTipo: 0 1 2 ….. NumTipoBebidas-1 <= TIPO DE


BEBIDA

6. Necesitaremos un array consumoXPueblo de NumPueblos posiciones para almacenar, por cada pueblo,
el número total de litros alcohólicos consumidos entre todos los tipos de bebidas.

consumoXPueblo: 0 1 2 ….. NumPueblos-1 <= PUEBLO

Pasos a seguir en la resolución del problema:


1. Inicializar la matriz consumo a 0. Esto indicará que cada pueblo, por cada tipo de bebida, aún no tiene
litros consumidos asociados.

2. Leer ordenadamente por pueblos, los pares que indican tipo de bebida y litros de la misma consumidos. En
el supuesto de que se repita un par (pueblo y tipo de bebida), los litros consumidos del último par serán los
que prevalezcan (es decir, no se hace acumulación de litros consumidos por tipo de bebida).
Para ello, por cada pueblo p:
a. Leer un par de valores de tipo de "bebida y litros consumidos" (tb y lt).
b. Mientras el tipo de bebida no sea FIN: asignar al pueblo p en el tipo de bebida tb los lt litros consumidos
(consumo[p][tb]=lt) y leer otro par de valores de tipo de "bebida y litros consumidos".
c. Si el tipo de bebida es FIN, indica que los datos de consumo del pueblo p ya han sido proporcionados.

3. Leer los tipos de bebidas que tienen alcohol. Las operaciones a realizar para ello son:
a. Se inicializa a 0 el array conAlcohol, indicando que inicialmente se consideran todas las bebidas no
alcohólicas.
b. Se lee un tipo de bebida tb.
c. Mientras que el tipo de bebida no sea FIN: se actualiza la bebida tb como alcohólica (conAlcohol[tb]=1)
y se lee otro tipo de bebida.
d. Cuando el tipo de bebida es FIN, la identificación de bebidas alcohólicas ha finalizado y con ello la
lectura de los tipos de bebida con alcohol.

4. Calcular por cada tipo de bebida los litros consumidos entre todos los pueblos y determinar la bebida más
consumida. Por cada tipo de bebida b:
a. Inicializar a 0 los litros consumidos en su acumulador (consumoXTipo[b]=0).
b. Incrementar el contador de bebida tipo b con los litros consumidos en todos los pueblos
(consumoXTipo[b]=consumo[p][b] + consumoXTipo[b], por cada pueblo p).
Una vez que se tienen calculados los litros consumidos por tipos de bebidas y recogidos en el array
consumoXTipo, se determina la bebida (índice del array) con mayor contenido (mayor consumo de litros) y
se imprime en pantalla. El proceso consiste en:
c. Inicialmente se considera que el mayor consumo de litros lo tiene la bebida 0 (maxTB).
d. Para el resto de bebidas se comprueba si los litros consumidos de la bebida actual b, supera los litros
consumidos por la bebida líder hasta el momento maxTB (determinado mediante la comparación
consumoXTipo[b]>consumoXTipo[maxTB]); en cuyo caso se registra la nueva bebida líder en consumo.
En caso contrario, la bebida líder hasta el momento sigue manteniéndose líder, y no hay que hacer nada
más.
e. Se imprime en pantalla un mensaje indicando cuál es la bebida de mayor consumo.

5. Calcular la bebida alcohólica más consumida. Ello se hace combinando los datos de los arrays
consumoXTipo y conAlcohol.
a. Se inicializa a 0 los litros máximos de alcohol consumidos (maxAlcohol).
b. Así, por cada bebida b, y sólo si ésta tiene alcohol (conAlcohol[b]==1) se comprueba si los litros
consumidos de la misma (consumoXTipo[b]) superan el mayor consumo hasta el momento (maxAlcohol)
(ambas condiciones se comprueban mediante la comparación (conAlcohol[b]==1 and
consumoXTipo[b]>=maxAlcohol)). Si la comparación es cierta, se actualiza el nuevo máximo: la bebida
alcohólica líder en consumo (identificada por la posición del array) y los litros consumidos de la misma
(posMaxAlcohol=b y maxAlcohol=consumoXTipo[b]).
c. Se imprime en pantalla un mensaje indicando cuál es la bebida alcohólica con mayor consumo
(posMaxAlcohol).

6. Calcular el pueblo con mayor consumo de alcohol. Se calcula de forma análoga pero, en lugar de por tipos
de bebidas, por pueblos. Es decir, por cada pueblo p:
a. Inicializar a 0 los litros con alcohol consumidos en su acumulador (consumoXPueblo[p]=0).
b. Incrementar dicho contador con los litros consumidos en el pueblo p de todas los tipos de bebidas
alcohólicas (consumoXPueblo[p]= consumo[p][b] + consumoXPueblo[p], por cada tipo de bebida b siendo
b con alcohol (conAlcohol[b]==1)).
c. Una vez que se tienen calculados los litros con alcohol consumidos por pueblos y recogidos en el array
consumo, se determina el pueblo (índice del array) con mayor contenido (mayor consumo de litros
alcohólicos) y se imprime en pantalla. El cálculo es análogo al recogido en el paso anterior pero ahora con
el array consumoXPueblo, en lugar de consumoXTipo).
CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumPueblos 20
#define NumTipoBebidas 8
main ()
{
int consumo[NumPueblos][NumTipoBebidas], consumoXPueblo[NumPueblos];
int consumoXTipo[NumTipoBebidas], conAlcohol[NumTipoBebidas];
int p, b, lt, tb, tp, sc, maxP, maxTB, maxAlcohol;
int posMaxAlcohol, posPMaxAlcohol;

//Inicializar array Consumo a 0 litros por pueblo y tipo bebida.


for (p=0; p<NumPueblos; p++)
for (b=0; b<NumTipoBebidas; b++)
consumo[p][b]=0;

//Lectura de los litros consumidos, ordenadamente por pueblos.


system("CLS");
printf("Recogemos los datos por pueblos:\n");
printf("Por cada pueblo, introduce pares (TipoBebida y Litros).\n");
printf("Para acabar, escribe FIN y pulsa Enter.\n\n");
for (p=0; p<NumPueblos; p++)
{ printf("Pueblo %d:\n", p);
sc = scanf("%d %d", &tb, &lt); fflush(stdin); //leemos tipoBebida y litros de la misma en el pueblo p
while (sc==2 && tb>=0 && tb<NumTipoBebidas && lt>=0)
{ consumo[p][tb] = lt;
//Si el tipoBebida tb se ha repetido, prevalecerán los últimos litros introducidos
sc = scanf("%d %d", &tb, &lt); fflush(stdin);
}
}

/*Bebidas alcohólicas: Iniciar todas las bebidas como NO alcohólicas (conAlcohol[x]=0)


Posteriormente, las que sean CON alcohol se anotan a 1*/
for (b=0; b<NumTipoBebidas; b++)
conAlcohol[b]=0;
printf("\nAhora enumera SOLO los tipos de bebida CON alcohol, FIN para acabar:\n");
sc = scanf("%d", &tb); fflush(stdin);
while (sc==1 && tb>=0 && tb<NumTipoBebidas)
{ conAlcohol[tb]=1;
sc = scanf("%d",&tb); fflush(stdin);
}

//Cálculo de la bebida más consumida entre todos los pueblos


//acumulamos el consumo por cada tipo de bebida
for (b=0; b<NumTipoBebidas; b++)
{ consumoXTipo[b]=0;
for (p=0; p<NumPueblos; p++)
consumoXTipo[b] = consumoXTipo[b] + consumo[p][b];
}
//localizamos el valor máximo de dichos consumos
maxTB=0;
for (b=1; b<NumTipoBebidas; b++)
{ if (consumoXTipo[b]>consumoXTipo[maxTB])
maxTB=b;
}
printf("\nEl tipo de bebida mas consumida es la: %d \n", maxTB);

//Encontrar la bebida alcohólica más consumida


maxAlcohol=0; //cantidad máxima de alcohol hasta el momento
for (b=0; b<NumTipoBebidas; b++)
{ if (conAlcohol[b]==1 && consumoXTipo[b]>=maxAlcohol)
{ posMaxAlcohol=b; maxAlcohol=consumoXTipo[b]; }
}
printf("\nEl tipo de bebida con alcohol mas consumida es: %d\n", posMaxAlcohol);

//Pueblo con mayor consumo de alcohol:


//Acumular consumos alcohólicos de cada pueblo
for (p=0; p<NumPueblos; p++)
{ consumoXPueblo[p]=0;
for (b=0; b<NumTipoBebidas; b++)
{ if (conAlcohol[b]==1) //si es bebida alcohólica
consumoXPueblo[p] = consumoXPueblo[p] + consumo[p][b];
}
}
//Encontrar el consumo máximo
maxAlcohol=posPMaxAlcohol=0;
for (p=0; p<NumPueblos; p++)
{ if (consumoXPueblo[p]>maxAlcohol)
{ posPMaxAlcohol=p; maxAlcohol=consumoXPueblo[p]; }
}
printf("\nEl pueblo con mayor consumo de alcohol es: %d\n", posPMaxAlcohol);
system ("PAUSE");
}

AMPLIACIONES PROPUESTAS

1. Al comienzo de la primera ejecución del programa, preguntar el número de pueblos a procesar. Esto
permitirá utilizar la aplicación en otras provincias o comarcas. El programa creará entonces un "array
bidimensional dinámico" de nombre consumo para el número de pueblos especificado.

2. Al finalizar el programa, salvar el array consumo en un fichero en disco "consumo.dat".

2. Si al entrar al programa existe ya en el disco el fichero anterior, medir su tamaño para determinar el
número de pueblos que contiene, crear el array dinámico consumo y cargarlo con los datos del fichero.

3. Inicializar el array conAlcohol al principio del programa de forma fija, no es necesario cargarlo desde el
teclado.

4. En la toma inicial de datos de consumo, pedir por teclado primero el código del pueblo y luego sus parejas
TipoBebida y Litros. Teclear FIN como código de pueblo para terminar la toma de datos y mostrar las
estadísticas finales. Esto permite ir introduciendo los consumos de los pueblos en sucesivas sesiones del
programa, y con cualquier orden de entrada de los pueblos.

5. Al introducir un código de pueblo, averiguar y notificar si ya han sido introducidos los datos de bebidas del
mismo.

6. Al terminar la introducción de datos, mostar en pantalla en forma tabular el contenido del array consumo.

7. Mostrar el nombre de las bebidas anotadas en las estadísticas finales del programa, mediante una función
auxiliar nombreBebida.

8. Al finalizar el programa, indicar en pantalla cuántos y cuáles pueblos faltan aún por introducir.
CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#define NumTipoBebidas 8
//Declaraciones prototipo de las funciones auxiliares
int **crearArrayBidimensional(int filas, int columnas);
char *nombreBebida(int n);

main ()
{
int consumoXTipo[NumTipoBebidas];
int conAlcohol[NumTipoBebidas] = {0,0,1,1,1,1,0,1}; //array ya cargado con valores fijos conocidos
int NumPueblos=0; //numero de pueblos, a introducir por teclado
int **consumo; //puntero doble necesario para crear un array bidimensional dinámico
int *consumoXPueblo; //puntero simple necesario para crear un array unidimensional dinámico
int p, b, lt, tb, tp, sc, maxP, maxTB, maxAlcohol, posMaxAlcohol, posPMaxAlcohol;
FILE *pf; //puntero de control de un fichero
system("CLS");

if ((pf=fopen("consumo.dat","rb"))==NULL) //intentamos abrir el fichero en modo lectura


{ //No existe fichero consumo, creamos el array dinámico bidimensional y lo inicializamos a 0:
do
{ printf("Indique el numero de pueblos a procesar: "); sc=scanf("%d", &NumPueblos);
} while (NumPueblos<0 || NumPueblos>1000 || sc!=1); //pedimos el numero de pueblos
consumo = crearArrayBidimensional(NumPueblos, NumTipoBebidas); //llamada a la función auxiliar
if (consumo==NULL) exit(1); //si no hay memoria libre salimos del programa
for (p=0; p<NumPueblos; p++)
for (b=0; b<NumTipoBebidas; b++) consumo[p][b]=0; //ponemos a cero todos los elementos del array
}
else
{ //Existe el fichero consumo, creamos el array bidimensional y lo cargamos desde el fichero:
//averiguamos el numero de pueblos que tiene almacenados el fichero
fseek(pf, 0, SEEK_END); NumPueblos = ftell(pf)/(NumTipoBebidas*sizeof(int)); rewind(pf);
//creamos el array bidimensional con la ayuda de la función auxiliar
if ((consumo = crearArrayBidimensional(NumPueblos, NumTipoBebidas))==NULL) exit(1);
//leemos los datos del array desde el fichero
for (p=0; p<NumPueblos; p++)
fread(consumo[p],NumTipoBebidas,sizeof(int),pf); //leemos cada fila del array de una sola vez
fclose(pf);
}
//Creamos el array unidimensional dinámico consumoXPueblo
if ((consumoXPueblo=(int *)malloc(NumPueblos*sizeof(int)))==NULL) //si falta memoria
{ printf("ERROR: Falta memoria. "); system("PAUSE");
for (p=0; p<NumPueblos; p++) free(consumo[p]); //liberamos todo el array bidimensional consumo
free(consumo); exit(1); //salimos del programa
}

//Lectura de los litros consumidos por pueblos.


printf("Recogemos los datos por pueblos. Escribe FIN y Enter para terminar la toma de datos. ");
printf("Por cada pueblo, introduce pares (TipoBebida y litros).\n");
//pedimos el código del pueblo a procesar
printf("\nCodigo del pueblo (0 a %d, FIN=Terminar): ", NumPueblos-1); sc = scanf("%d", &p); fflush(stdin);
while (sc==1 && p>=0 && p<NumPueblos)
{ //Averiguar si ya hay datos introducidos de este pueblo
for (tb=b=0; b<NumTipoBebidas; b++) tb += consumo[p][b]; //acumulamos todas las bebidas del pueblo
if (tb>0) printf("Atencion: Este pueblo ya ha sido introducido.\n");
//Introducir pares TipoBebida y Litros
printf("TipoBebida y Litros (FIN=Terminar): "); sc = scanf("%d %d", &tb, &lt); fflush(stdin);
while (sc==2 && tb>=0 && tb<NumTipoBebidas && lt>=0)
{ consumo[p][tb] = lt;
printf("TipoBebida y Litros (FIN=Terminar): "); sc = scanf("%d %d", &tb, &lt); fflush(stdin);
}
//pedimos el siguiente pueblo
printf("\nCodigo del pueblo (0 a %d, FIN=Terminar): ", NumPueblos-1); sc = scanf("%d", &p); fflush(stdin);
}

//Mostar el array consumo en pantalla en forma de tabla


printf("\nPueblo\t");
for (b=0; b<NumTipoBebidas; b++) printf("Bebida%d\t", b);
for (p=0; p<NumPueblos; p++)
{ printf("\n%d\t", p);
for (b=0; b<NumTipoBebidas; b++)
printf("%d\t", consumo[p][b]);
}
printf("\n\n");

//Cálculo de la bebida más consumida entre todos los pueblos


for (b=0; b<NumTipoBebidas; b++)
for (consumoXTipo[b]=p=0; p<NumPueblos; p++)
consumoXTipo[b] += consumo[p][b];
for (maxTB=0,b=1; b<NumTipoBebidas; b++)
if (consumoXTipo[b]>consumoXTipo[maxTB]) maxTB=b;
printf("\nEl tipo de bebida mas consumida es la: %d-%s\n", maxTB, nombreBebida(maxTB));

//Encontrar la bebida alcohólica más consumida


for (maxAlcohol=b=0; b<NumTipoBebidas; b++)
if (conAlcohol[b]==1 && consumoXTipo[b]>=maxAlcohol)
{ posMaxAlcohol=b; maxAlcohol=consumoXTipo[b]; }
printf("\nEl tipo de bebida con alcohol mas consumida es: %d-%s\n", posMaxAlcohol,
nombreBebida(posMaxAlcohol));

//Pueblo con mayor consumo de alcohol:


//Acumular consumos alcohólicos de cada pueblo
for (p=0; p<NumPueblos; p++)
for (consumoXPueblo[p]=b=0; b<NumTipoBebidas; b++)
if (conAlcohol[b]==1) consumoXPueblo[p] += consumo[p][b];
//Encontrar el consumo máximo
for (posPMaxAlcohol=maxAlcohol=p=0; p<NumPueblos; p++)
if (consumoXPueblo[p]>maxAlcohol)
{ posPMaxAlcohol=p; maxAlcohol=consumoXPueblo[p]; }
printf("\nEl pueblo con mayor consumo de alcohol es: %d\n", posPMaxAlcohol);

//Mostrar los pueblos que faltan por introducir


printf("\nLos pueblos que faltan por introducir son los siguientes: ");
for (tp=p=0; p<NumPueblos; p++)
{ for (tb=b=0; b<NumTipoBebidas; b++) tb+=consumo[p][b]; //acumulamos todas las bebidas del pueblo
if (tb==0) { printf("%d ", p); tp++; } //imprimimos el pueblo e incrementamos el contador de pueblos
}
printf("\nEn total faltan %d pueblos por introducir.\n\n", tp);

//Grabar fichero en disco


if ((pf = fopen("consumo.dat","wb"))==NULL) printf("\nERROR al grabar fichero.\n");
else
{ for (p=0; p<NumPueblos; p++)
fwrite(consumo[p],NumTipoBebidas,sizeof(int),pf); //grabamos fila por fila todo el array
fclose(pf);
}
//Liberar memoria de los arrays dinámicos
for (p=0; p<NumPueblos; p++) free(consumo[p]);
free(consumo); free(consumoXPueblo);
system ("PAUSE");
}

//Función de creación de un array bidimensional dinámico de tipo int


//Acepta dos argumentos: numero de filas y numero de columnas
int **crearArrayBidimensional(int filas, int columnas)
{
int **punt, i;
if ((punt=(int **)malloc(filas*sizeof(int *)))==NULL) //creamos el array de punteros auxiliares
{ printf("ERROR: Falta memoria. "); system("PAUSE"); return NULL; }
for (i=0; i<filas; i++)
{ if ((punt[i]=(int *)malloc(columnas*sizeof(int)))==NULL) //creamos cada una de las filas
{ printf("ERROR: Falta memoria. "); system("PAUSE");
while (--i>=0) { free(punt[i]); } //si faltó memoria, liberamos todo lo que llevábamos reservado
free(punt); return NULL;
}
}
return punt; //retornamos el puntero maestro doble que apunta al array de punteros auxiliares
}

//Función para imprimir el nombre de una bebida


//Acepta como argumento el código de la bebida
char *nombreBebida(int n)
{
char *nombres[] = { "Naturales", "Gaseosos", "Vinos", "Cervezas", "Whisky", "Licores", "Energeticos",
"Combinados" };
return nombres[n];
}
CONCURSO DE CANCIONES DE RADIO
Una emisora de radio quiere hacer un concurso en el que proponen a sus oyentes los títulos de 10
canciones, a las que ha numerado internamente del 0 al 9 (del 1 al 10 de cara al público). Cada participante
debe llamar para dar los números de 3 títulos por orden de preferencia decreciente. Se le dan 3 puntos a la
canción que el oyente nombra en primer lugar, 2 puntos a la que indica en 2º lugar y 1 punto a la 3ª.

Se pide hacer un programa que realice las siguientes tareas:

1. Leer y almacenar los votos emitidos por cada oyente, suponemos que como máximo pueden concursar
100 oyentes. A medida que llaman los concursantes se les asigna un número interno de forma correlativa del
0 al 99 (del 1 al 100 de cara al público). La entrada de datos se realizará en forma de tríos, con los números
de las canciones que vota cada oyente. Para finalizar se introducirá el valor 0 en el primer dato del trio.
Ejemplo:
Oyente 1: canciones 7 3 2 (internamente es Oyente 0, canciones 6 2 1)
Oyente 2: canciones 4 8 6 (internamente es Oyente 1, canciones 3 7 5)
Oyente 3: canciones 4 1 2 (internamente es Oyente 2, canciones 3 0 1)
Oyente 4: canciones 1 6 3 (internamente es Oyente 3, canciones 0 5 2)
Oyente 5: 0

2. Calcular los votos obtenidos por cada canción e indicar cuáles son la 1ª y 2ª canción más votada.
Según el ejemplo anterior:
Canción 1: 5 votos (internamente es la canción 0)
Canción 2: 2 votos (internamente es la canción 1)
Canción 3: 3 votos (internamente es la canción 2)
Canción 4: 6 votos (internamente es la canción 3)
Canción 5: 0 votos (internamente es la canción 4)
Canción 6: 3 votos (internamente es la canción 5)
Canción 7: 3 votos (internamente es la canción 6)
Canción 8: 2 votos (internamente es la canción 7)
Canción 9: 0 votos (internamente es la canción 8)
Canción 10: 0 votos (internamente es la canción 9)
La 1ª canción es: 4
La 2ª canción es: 1

3. Al final de la emisión se reparten puntos entre los oyentes que han concursado de la siguiente manera: 30
puntos si entre las 3 canciones votadas está la 1ª, 20 puntos si está la 2ª y 10 puntos suplementarios si han
acertado los dos títulos más votados. Se desea obtener el número del oyente que más puntos ha obtenido,
ya que se le dará un premio.
En el ejemplo:
Oyente 1: 0 puntos
Oyente 2: 30 puntos
Oyente 3: 60 puntos
Oyente 4: 20 puntos
Ganador: el oyente número 3

ANÁLISIS DEL PROBLEMA

Constantes del enunciado:


1. NumOyentes = 100. El número máximo de oyentes que van a poder participar en el consurso.
2. NumCanciones = 10. Número de canciones que participan en el concurso.
3. NumVotos = 3 . Número de votos que puede emitir cada participante.

Representación del las variables necesarias para la entrada:


4. Necesitaremos un array votosOyentes de NumOyentes X NumVotos posiciones para almacenar, por cada
oyente participante, los votos emitidos en el concurso de canciones, de manera que si la casilla
votosOyentes[i][j]=X indica que el j-ésimo voto del participante i es a la canción X.
votosOyentes: 0 1 NumVotos-1 <= NUMERO DE VOTO
0 6 2 1
1 3 7 5
… 3 0 1
NumOyentes-1 0 5 2
OYENTE

Representación de las variables necesarias para los resultados:


5. Necesitaremos un array votosXCancion de NumCanciones posiciones para acumular por cada canción
los votos dados por los oyentes participantes.

votosXCancion: 0 1 2 ….. NumCanciones-1 <=


CANCION
5 2 3 0

Pasos a seguir en la resolución del problema:


1. Leer los votos de los oyentes:
a. Inicializar a 0 el contador de oyentes participantes en el concurso (p).
b. Leer los tres votos del participante (v1, v2, v3).
c. Mientras la tripleta de votos sea válida (primer voto distinto de 0):
I. Registrar los votos conservando el orden de emisión (votosOyentes[p][0], votosOyentes[p][1],
votosOyentes[p][2]).
II. Incrementar en 1 el contador p de participantes.
III. Leer otra tripleta (v1, v2, v3) de votos a canciones.
d. Determinar el número de participantes que ha habido en el concurso (numParticipantes), siendo éste p-
1 (debido a que la última tripleta leída al tener 0 no corresponde a ningún participante).

2. Calcular las dos canciones más votadas.


a. Primeramente, se calculan las puntuaciones de las canciones (votosXCancion). Para ello realizar los
siguientes pasos:
I. Inicializar los contadores de votos de las canciones a 0; es decir, el array votosXCancion a 0.
II. Por cada oyente participante p, acumular sus tres votos emitidos (votosOyentes[p][j]), sabiendo que la
primera canción obtiene 3 puntos, la segunda 2 y la tercera 1 punto. Estos incrementos se acumulan a
los puntos que ya tienen registrados en el array votosXCancion. Recalcar que han participado los
oyentes del 0 al numParticipantes y que numParticipantes ≤ NumOyentes.
III. Imprimir en pantalla la puntuación de cada una de las canciones.
b. Posteriormente, se calculan las dos canciones con puntuación más elevada:
I. Se comparan los votos obtenidos por las canciones 0 y 1. La que tiene más puntos es la primera y la
otra la segunda.
II. Con cada una de las canciones restantes c:
(1) Si c ha obtenido más puntos que la máxima puntuada hasta el momento (primera), actualizar los dos
máximos del siguiente orden: segunda con primera y primera con c.
(2) Si no, si c ha obtenido más puntuación que segunda, actualizar sólo el segundo máximo
(segunda=c).
III. Escribir en pantalla las dos canciones más votadas.

3. Calcular el oyente ganador.


a. Se inicializa a 0 los puntos máximos actuales (maxPuntos).
b. Por cada oyente participante:
I. Se determina si ha obtenido 0 puntos, 20 puntos, 30 puntos o bien 60 puntos.
II. Si la puntuación supera el máximo de puntos actual, actualizar el máximo de puntos actual
(maxPuntos) y el participante que los ha obtenido (oyenteGanador).
c. Imprimir en pantalla el oyente que más puntos ha conseguido.

CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumOyentes 100
#define NumCanciones 10
#define NumVotos 3
main ()
{
int votosOyentes[NumOyentes][NumVotos], votosXcancion[NumCanciones];
int p=0, numParticipantes, sc, c, v, v1, v2, v3, primera, segunda;
int votosP, maxPuntos, oyenteGanador;

//Introduccion de votos de los oyentes participantes:


system("CLS");
printf("Concurso LA CANCION DEL VERANO:\n");
printf("Cada concursante votará a tres canciones, en orden de preferencia.\n");
printf("Cada cancion identificada con un numero del 1 al %d.\n", NumCanciones);
printf("Para acabar, introducir 0 en la primera canción votada.\n\n");
while (p<NumOyentes)
{ printf("Oyente %d: ", p+1); sc=scanf("%d %d %d", &v1, &v2, &v3); fflush(stdin);
if (v1==0) break;
if (sc!=3 || v1<0 || v1>NumCanciones || v2<1 || v2>NumCanciones || v3<1 || v3>NumCanciones)
{ printf("Datos incorrectos. Introduzcalos de nuevo.\n"); continue; }
votosOyentes[p][0]=v1-1; votosOyentes[p][1]=v2-1; votosOyentes[p][2]=v3-1;
p++; //Este será el siguiente participante
}
numParticipantes=p;

//Determinar la puntuación de cada canción:


for (c=0; c<NumCanciones; c++) { votosXcancion[c]=0;} //Poner a cero todo el array
for (p=0; p<numParticipantes; p++)
{ for (v=0; v<NumVotos; v++) //acumular todos los votos en cada canción
{ votosXcancion[votosOyentes[p][v]] += (NumVotos-v); } //(NumVotos-v) genera los valores 3, 2 y 1
}
for (c=0; c<NumCanciones; c++) //presentar los resultados en pantalla
{ printf("\nCanción %d: %d votos", c+1, votosXcancion[c]); }

// Determinar las dos canciones más votadas:


if (votosXcancion[0]>=votosXcancion[1])
{ primera=0; segunda=1; }
else
{ primera=1; segunda=0; }
for (c=2; c<NumCanciones; c++)
{ if (votosXcancion[c]>votosXcancion[primera])
{ segunda=primera; primera=c; }
else if (votosXcancion[c]>votosXcancion[segunda])
segunda=c;
}
printf("\n\nLa 1ª cancion es: %d\n", primera+1); printf("La 2ª cancion es: %d\n", segunda+1);

// Oyente participante que ha acertado las canciones más votadas:


maxPuntos=0; //Inicialización de la puntuación más elevada conseguida por los participantes
for (p=0; p<numParticipantes; p++)
{ votosP=0;
for (v=0; v<NumVotos; v++)
{ if (votosOyentes[p][v] == primera) votosP+=30;
else if (votosOyentes[p][v] == segunda) votosP+=20;
}
if (votosP == 50) votosP=60; //La puntuación es 60 si ha votado a la Primera y la Segunda más votadas
printf("\nOyente participante %d: %d puntos", p+1, votosP);
if (votosP>maxPuntos)
{ maxPuntos=votosP; oyenteGanador=p; } //Se actualiza el máximo con p y con sus respectivos puntos
}
printf("\n\nEl ganador es el participante: %d\n\n", oyenteGanador+1);
system("PAUSE");
}

AMPLIACIONES PROPUESTAS

1. En la primera ejecución del programa, pedir por teclado los dos datos fundamentales de número máximo
de oyentes (NumOyentes) y número de canciones (NumCanciones), y grabarlos en un fichero
"oyentes1.dat". En futuras entradas al programa, estos dos datos se tomarán desde este fichero y ya no
desde el teclado.

2. Tomar los datos de los oyentes en un "array dinámico bidimensional de tamaño creciente" de nombre
votosOyentes cuyo tamaño vaya creciendo en memoria a medida que tomamos nuevos datos de oyentes
desde el teclado.

3. Al finalizar el programa, salvar el array votosOyentes en un fichero en disco "oyentes2.dat". En las


siguientes entradas al programa, cargar dicho fichero en el array, una vez averiguado el número actual de
oyentes participantes que contiene. Esto permite ir introduciendo los datos en sucesivas sesiones del
programa.

4. Al presentar en pantalla las canciones 1ª y 2ª más votadas, considerar la posibilidad de que haya varias
canciones empatadas a puntos en cada categoría, y en tal caso mostrarlas todas.

5. Al presentar en pantalla el participante ganador, considerar la posibilidad de que haya varios empatados a
puntos, y en tal caso mostrarlos todos.

6. Al finalizar el programa, indicar en pantalla cuántos participantes tenemos y cuántos faltan aún por
introducir hasta llegar al límite máximo NumOyentes.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#define NumVotos 3
//Declaraciones prototipo de funciones auxiliares
int **crearArrayBidimensional(int filas, int columnas);
void sinMemoria(void);

main ()
{
int NumOyentes=0, NumCanciones=0; //valores a introducir por teclado
int **votosOyentes=NULL, **aux; //punteros dobles para manipular el array bidimensional dinamico
int *votosXcancion, *puntosXoyente; //punteros simples necesarios para los arrays unidimensionales
int p, numParticipantes=0, sc, c, v, v1, v2, v3, primera, segunda, maxPuntos, salir=0;
FILE *pf;
system("CLS");
if ((pf=fopen("oyentes1.dat","rb"))==NULL) //intentamos abrir el fichero en modo lectura
{ //No existe el fichero oyentes1.dat, pedimos los valores por teclado
do
{ printf("Indica el numero maximo de oyentes a procesar: "); sc=scanf("%d", &NumOyentes);
} while (NumOyentes<=0 || NumOyentes>1000 || sc!=1);
do
{ printf("Indica el numero de canciones a votar: "); sc=scanf("%d", &NumCanciones);
} while (NumCanciones<=0 || NumCanciones>100 || sc!=1);
//grabamos estos dos valores en el fichero
if ((pf=fopen("oyentes1.dat","wb"))==NULL)
{ printf("ERROR al grabar fichero. "); system("PAUSE"); exit(1); }
fwrite(&NumOyentes, sizeof(int), 1, pf); fwrite(&NumCanciones, sizeof(int), 1, pf); fclose(pf);
}
else
//el fichero oyentes1.dat existe, cargamos sus valores y cerramos el fichero
{ fread(&NumOyentes, sizeof(int), 1, pf); fread(&NumCanciones, sizeof(int), 1, pf); fclose(pf); }

if ((pf=fopen("oyentes2.dat","rb"))!=NULL) //intentamos abrir el fichero en modo lectura


{ //Existe el fichero oyentes2.dat
//averiguar el numero actual de participantes que contiene,
fseek(pf, 0, SEEK_END); numParticipantes=ftell(pf)/(NumVotos*sizeof(int)); rewind(pf);
//crear el array dinámico con este número de participantes
if ((votosOyentes=crearArrayBidimensional(numParticipantes, NumVotos))==NULL) exit(1);
//cargar el array con los datos del fichero, fila por fila
for (p=0; p<numParticipantes; p++) fread(votosOyentes[p], NumVotos*sizeof(int), 1, pf);
fclose(pf); //cerramos el fichero
}
// Creamos los dos arrays dinámicos unidimensionales votosXcancion y puntosXoyente
if ((votosXcancion = (int *)malloc(NumCanciones*sizeof(int)))==NULL) salir=1;
else if ((puntosXoyente = (int *)malloc(numParticipantes*sizeof(int)))==NULL)
{ free(votosXcancion); salir=1; }
if (salir) //No hubo memoria suficiente
{ sinMemoria(); //emitimos mensaje
for (p=0; p<numParticipantes; p++) free(votosOyentes[p]); //liberar el array bidimensional y terminar
free(votosOyentes); exit(1);
}
p = numParticipantes;

//Hay p oyentes participantes. Introduccion de votos de los oyentes participantes:


system("CLS");
printf("Concurso LA CANCION DEL VERANO:\n");
printf("Cada concursante votara a %d canciones, en orden de preferencia.\n", NumVotos);
printf("Cada cancion identificada con un numero del 1 al %d.\n", NumCanciones);
printf("Para acabar, introducir 0 en la primera cancion votada.\n\n");
while (p<NumOyentes)
{ printf("Oyente %d: ", p+1); sc=scanf("%d %d %d", &v1, &v2, &v3); fflush(stdin);
if (v1==0) break;
if (sc!=3 || v1<0 || v1>NumCanciones || v2<1 || v2>NumCanciones || v3<1 || v3>NumCanciones)
{ printf("Datos incorrectos. Introduzcalos de nuevo.\n"); continue; }
//ampliación del numero de filas del array bidimensional
if ((aux = (int **)realloc(votosOyentes, (p+1)*sizeof(int *)))==NULL) //ampliamos el array de punteros
sinMemoria();
else
{ votosOyentes = aux;
//creación de una nueva fila del array bidimensional
if ((votosOyentes[p] = (int *)malloc(NumVotos*sizeof(int)))==NULL)
{ sinMemoria();
votosOyentes = (int **)realloc(votosOyentes, p*sizeof(int *)); //dejar el nº de filas como estaba
}
else //introducción de los datos en la nueva fila recién creada
{ votosOyentes[p][0]=v1-1; votosOyentes[p][1]=v2-1; votosOyentes[p][2]=v3-1; }
}
p++; //este será el siguiente participante
}
numParticipantes = p;
if (numParticipantes==NumOyentes) //anunciar si ya hemos concluido el concurso
{ printf("Toma de datos concluida, tenemos %d participantes. ", NumOyentes); system("PAUSE"); }

//Determinar la puntuación de cada canción:


for (c=0; c<NumCanciones; c++) { votosXcancion[c]=0;} //Poner a cero todo el array
for (p=0; p<numParticipantes; p++)
{ for (v=0; v<NumVotos; v++)
{ votosXcancion[votosOyentes[p][v]]+=(NumVotos-v); } //(NumVotos-v) genera los valores 3, 2 y 1
}
for (c=0; c<NumCanciones; c++) { printf("\nCanción %d: %d votos", c+1, votosXcancion[c]); }

//Determinar las dos canciones más votadas:


if (votosXcancion[0]>=votosXcancion[1]) { primera=0; segunda=1; }
else { primera=1; segunda=0; }
for (c=2; c<NumCanciones; c++)
{ if (votosXcancion[c]>votosXcancion[primera])
{ segunda=primera; primera=c; }
else if (votosXcancion[c]>votosXcancion[segunda] && votosXcancion[c]!=votosXcancion[primera])
segunda=c;
}
printf("\n\nLa 1ª cancion es: ");
for (c=0; c<NumCanciones; c++) //mostramos todas las canciones que tienen la máxima puntuación
if (votosXcancion[c]==votosXcancion[primera]) printf("%d ", c+1);
printf("\nLa 2ª cancion es: ");
for (c=0; c<NumCanciones; c++) //mostramos todas las canciones que tienen la 2ª puntuación máxima
if (votosXcancion[c]==votosXcancion[segunda]) printf("%d ", c+1);
printf("\n");

//Oyente participante que ha acertado las canciones más votadas:


for (maxPuntos=p=0; p<numParticipantes; p++)
{ for (puntosXoyente[p]=v=0; v<NumVotos; v++)
{ if (votosXcancion[votosOyentes[p][v]] == votosXcancion[primera]) puntosXoyente[p]+=30;
else if (votosXcancion[votosOyentes[p][v]] == votosXcancion[segunda]) puntosXoyente[p]+=20;
}
if (puntosXoyente[p]==50) puntosXoyente[p]=60;
printf("\nOyente participante %d: %d puntos", p+1, puntosXoyente[p]);
if (puntosXoyente[p]>maxPuntos) maxPuntos=puntosXoyente[p];
}
printf("\n\nEl ganador es el participante: ");
for (p=0; p<numParticipantes; p++) //mostramos todos los participantes que tienen puntuación máxima
if (puntosXoyente[p]==maxPuntos) printf("%d ", p+1);
printf("\n\n");

//Grabar fichero en disco


if ((pf = fopen("oyentes2.dat","wb"))==NULL) printf("\nERROR al grabar fichero.\n");
else
{ for (p=0; p<numParticipantes; p++) fwrite(votosOyentes[p], NumVotos*sizeof(int), 1, pf);
fclose(pf);
}
//Liberar memoria de los arrays dinámicos
for (p=0; p<numParticipantes; p++) free(votosOyentes[p]); //liberamos las filas del array bidimensional
free(votosOyentes); free(votosXcancion); free(puntosXoyente);
system("PAUSE");
}

//Función para creación de un array bidimensional dinámico de tipo int


int **crearArrayBidimensional(int filas, int columnas)
{ int **punt, i;
if ((punt=(int **)malloc(filas*sizeof(int *)))==NULL) //creamos el array de punteros auxiliares
{ sinMemoria(); return NULL; }
for (i=0; i<filas; i++)
{ if ((punt[i]=(int *)malloc(columnas*sizeof(int)))==NULL) //creamos cada una de las filas
{ sinMemoria();
while (--i>=0) { free(punt[i]); } //si no hubo memoria, liberamos todo lo que llevábamos reservado
free(punt); return NULL;
}
}
return punt;
}

//Función auxiliar para emitir mensaje frecuente en pantalla


void sinMemoria(void)
{ printf("ERROR: Falta memoria. "); system("PAUSE"); }
CONSUMO DE SURTIDORES EN GASOLINERA
En una gasolinera nos han pedido que realicemos un estudio sobre el uso de los distintos surtidores de
combustible a lo largo de una semana. En la gasolinera hay 12 surtidores numerados del 0 al 11, que cada
noche se rellenan a 5000 litros.
A lo largo de cada día, el operario introduce parejas de datos "surtidor y litros solicitados". Si el tanque del
que se ha solicitado el combustible tiene suficientes litros se suministrarán todos ellos; si no, tan sólo se
suministrarán los existentes emitiendo un mensaje en el que se indique los litros que se pueden suministrar.
Al final de la jornada el operario introducirá el texto FIN, indicando el fin de datos de ese día. Este proceso se
repetirá para cada día de la semana. El programa permanecerá funcionando sin descanso durante toda la
semana (dia y noche).

Ejemplo:
Día 0 (lunes):
Surtidor, litros: 1 40
Surtidor, litros: 11 300
Surtidor, litros: 11 400
Surtidor, litros: 0 36
...
Surtidor, litros: 11 400
Se llenará con 100 litros
Surtidor, litros: 0 27
Surtidor, litros: 11 300
Se llenará con 0 litros
Surtidor, litros: 2 57
Surtidor, litros: FIN

Día 1 (martes):
...
Día 6 (domingo):
...

Además de los datos recogidos diariamente, al principio de la semana se solicitará la siguiente información:
1. Para cada surtidor se pedirá el tipo de combustible que almacena, sabiendo que hay cinco tipos distintos
de combustible codificados de la siguiente manera:
0) EuroSuper’95 1) Extra’98 2) Star’97 3) ExtraDiesel 4) Gasoleo-A
Ejemplo:
Introduce el tipo de combustible de cada surtidor:
Surtidor 0: 0
Surtidor 1: 1
Surtidor 2: 0

Surtidor 11: 4

2. Se pedirá también, por cada tipo de combustible, la ganancia por litro (en Euros) y se almacenará en otra
tabla.
Ejemplo:
Dame la ganancia por litro de cada tipo de combustible:
Tipo 0: 0.02
Tipo 1: 0.03

Tipo 4: 0.02

Al finalizar la semana, se calculará lo siguiente:


a) Visualizar qué días y qué surtidores se han vaciado completamente.
b) Independientemente del tipo de combustible, indicar qué día se han vendido más litros.
c) Indicar qué tipo de combustible ha dado más beneficio esta semana, y cuánto ha sido este beneficio.
ANÁLISIS DEL PROBLEMA

Constantes del enunciado:


1. NumSurtidores = 12. Número de surtidores que tiene la gasolinera.
2. DiasSemana = 7. Número de días para los que se va ha realizar el estudio.
3. NumCombustibles = 5. Número de diferentes combustibles que vende la gasolinera.

Representación de las variables necesarias para la entrada:


4. Necesitaremos un array bidimensional litros de DiasSemana x NumSurtidores posiciones, dónde se
almacenará la cantidad de litros que le quedan por vender a cada surtidor. Al inicio de cada jornada laboral
todos los surtidores tendrán 5000 litros por vender.

litros: 0 1 2 ... NumSurtidores-1 <= SURTIDOR


0 3600 3800 2300 4010
1 3200 3500 2700 3090

DiasSemana-1 5000 5000 5000 5000
DIA SEMANA

5. Necesitaremos un array unidimensional tipoSurtidor de NumSurtidores posiciones para almacenar el tipo


de combustible que vende cada surtidor.

tipoSurtidor: 0 1 2 ….. NumSurtidores-1 <= SURTIDOR


0 1 0 4

6. Necesitaremos un array unidimensional tipoGanancias de NumCombustibles posiciones para almacenar


la ganancia por litro de cada tipo de combustible.

tipoGanancias: 0 1 2 ….. NumCombustibles-1 <= COMBUSTIBLE


0.02 0.03 0.01 0.02

Representación de las variables necesarias para los resultados:


7. Necesitaremos un array unidimensional ventasDia de DiasSemana posiciones para almacenar los litros
vendidos cada día de la semana, teniendo en cuenta todos los tipos de combustible.

ventasDia: 0 1 2 ….. DiasSemana-1 <= DIA SEMANA

8. Necesitamos un array unidimensional ganancias de NumCombustibles posiciones para almacenar los


litros de cada tipo de combustible vendidos. Finalmente utilizaremos esta información para calcular las
ganancias de cada tipo de combustible.

ganancias: 0 1 2 ….. NumCombustibles-1 <= COMBUSTIBLE

Pasos a seguir en la resolución del problema:


1. Al principio de la semana, para cada surtidor leer el tipo de combustible que vende y almacenarlo en el
array tipoSurtidor.

2. Al principio de la semana, para cada tipo de combustible leer la ganancia que nos da cada litro vendido y
almacenarlo en el array tipoGanancias.

3. Inicializar la matriz litros a 5000 para todos los dias de la semana.

4. Para cada día de la semana:


a. Leer la primera venta de surtidor y litros (sur, lit).
b. Mientras no se introduzca FIN, hacer:
I. Si tenemos suficientes litros en el surtidor, entonces restar los litros que se han pedido; si no, escribir
un mensaje con los litros que se le dan y dejar a 0 el surtidor para ese día.
II. Leer siguiente venta (sur, lit).

5. Al finalizar la semana, recorrer el array litros y detectar las posiciones dónde encontramos un 0, ya que
esto indicará el día y el surtidor que ha vendido todo el combustible.

6. Para cada día de la semana, sumar lo que se ha vendido entre todos los surtidores. Para calcular lo que
ha vendido un surtidor habrá que restarle a 5000 el valor almacenado en el array litros para ese día y surtidor.
Los valores obtenidos se almacenarán en la array ventasDia. Finalmente, buscar y escribir la posición del
valor máximo en el array ventasDia.

7. Para cada surtidor:


a. Contar cuántos litros ha vendido entre todos los días (recordar que para calcular los litros vendidos hay
que restarle a 5000 el valor del array litros) y almacenarlo en la variable surtidor.
b. Mirar el tipo de combustible que vende el surtidor (en el array tipoSurtidor) y almacenarlo en la variable
combustible.
c. Acumular los litros vendidos (calculados en el paso 7a, surtidor) en el array ganancias en la posición que
corresponda al tipo de combustible vendido (calculado en el paso 7b, combustible).
Utilizar la expresión: ganancias[combustible]+=surtidor;

8. Para cada tipo de combustible, multiplicar el valor almacenado en el array ganancias con el valor
acumulado en el array tipoGanancias y dejarlo en el vector ganancias.

9. Calcular el combustible que ha dado mayor ganancia, es decir, calcular la posición del valor máximo en el
array ganancias.

CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define DiasSemana 7
#define NumSurtidores 12
#define NumCombustibles 5
char *diaSemana(int d);
char *nombreCombustible(int c);

main()
{
int litros[DiasSemana][NumSurtidores], tipoSurtidor[NumSurtidores], ventasDia[DiasSemana];
float tipoGanancias[NumCombustibles], ganancias[NumCombustibles];
int g, s, sc, sur, lit, d, dMax, dMaxLitros, gMax, combustible, diario,surtidor;

system("CLS");
printf("DATOS FIJOS DE LA SEMANA:\n\n");
// Comienzo de semana, lectura del tipo de combustible que tiene cada surtidor:
printf("Introduce el tipo de combustible que tiene cada surtidor:\n");
for (g=0; g<NumCombustibles; g++)
printf("%d=%s ", g, nombreCombustible(g));
printf("\n\n");
for (s=0; s<NumSurtidores; s++)
{ printf(" Surtidor %d: ", s); sc=scanf("%d", &tipoSurtidor[s]); fflush(stdin);
if (sc!=1 || tipoSurtidor[s]<0 || tipoSurtidor[s]>=NumCombustibles)
{ printf("Tipo incorrecto.\n"); s--; }
}

// Lectura de las ganancias por cada litro de combustible vendido:


printf("\nIntroduce la ganancia en Euros de cada litro de combustible:\n");
for (g=0; g<NumCombustibles; g++)
{ printf(" Tipo %d (%s): ", g, nombreCombustible(g)); sc=scanf("%f", &tipoGanancias[g]); fflush(stdin);
if (sc!=1 || tipoGanancias[g]<0 || tipoGanancias[g]>10)
{ printf("Ganancia incorrecta.\n"); g--; }
}

// Inicializar todos los surtidores en todos los días a 5000 litros:


for (d=0; d<DiasSemana; d++)
for (s=0; s<NumSurtidores; s++)
litros[d][s]=5000;

// Para cada día de la semana, leer sus ventas:


for (d=0; d<DiasSemana; d++)
{ // Leer ventas del día d
system("CLS");
printf("VENTAS SEMANALES:\n\n");
printf("Dia %d (%s):\n", d+1, diaSemana(d));
printf(" Surtidor, litros: "); sc=scanf("%d %d", &sur, &lit); fflush(stdin);
while (sc>0) // Mientras no se escriba FIN
{
if (sc!=2 || sur<0 || sur>=NumSurtidores || lit<0 || lit>1000) // Confirmar valores correctos
printf("\tDatos incorrectos.\n");
else
{
if (litros[d][sur]>=lit) // Comprobar si el surtidor tiene suficientes litros
litros[d][sur] = litros[d][sur]-lit;
else
{ // No hay suficientes litros, se dan los que hay
printf("\tSe llenará con %d litros.\n", litros[d][sur]);
litros[d][sur]=0 ;
}
}
printf(" Surtidor, litros: "); sc=scanf("%d %d", &sur, &lit); fflush(stdin);
}
}

// Es final de semana, indicar qué días y qué surtidores se han vaciado completamente:
system("CLS");
printf("ESTADISTICAS SEMANALES:\n\n");
for (d=0; d<DiasSemana; d++)
for (s=0; s<NumSurtidores; s++)
if (litros[d][s]==0)
printf("El dia %d (%s) el surtidor %d (%s) se ha quedado sin combustible.\n ", d+1, diaSemana(d), s,
nombreCombustible(tipoSurtidor[s]));

// Indicar qué día se han vendido más litros:


for (d=0; d<DiasSemana; d++) // Calcular para cada día los litros vendidos
{ ventasDia[d]=0; // Los litros vendidos el día d son la suma de lo vendido por todos los surtidores
for (s=0; s<NumSurtidores; s++)
ventasDia[d] = ventasDia[d] + (5000-litros[d][s]);
}
// Calcular el día que se ha vendido más
dMax=0;
for (d=0; d<DiasSemana; d++)
{ if (ventasDia[d]>ventasDia[dMax]) dMax=d; }
printf("El dia de la semana que se han vendido mas litros es %d (%s) con %d litros.\n", dMax+1,
diaSemana(dMax), ventasDia[dMax]);

// Indicar qué tipo de gasolina ha dado más beneficio esta semana, y cuánto ha sido:
// Inicializar a cero el array de ganancias
for (g=0; g<NumCombustibles; g++) ganancias[g]=0;
for (s=0; s<NumSurtidores; s++)
{ // Calcular los litros que ha vendido el surtidor s
surtidor=0;
for (d=0; d<DiasSemana; d++)
surtidor = surtidor+(5000-litros[d][s]);
combustible=tipoSurtidor[s]; // Calcular el tipo de gasolina que vende el surtidor s
ganancias[combustible]=ganancias[combustible]+surtidor; // Acumular litros vendidos por tipo de combustible
}
// Calcular ganancias de cada tipo de combustible
for (g=0; g<NumCombustibles; g++)
ganancias[g] = tipoGanancias[g] * ganancias[g];
// Calcular el combustible que ha dado mayor ganancia
gMax=0;
for (g=1; g<NumCombustibles; g++)
if (ganancias[g]>ganancias[gMax]) gMax=g;
printf("El tipo de combustible que ha dado mayor ganancia es %d (%s) con una ganancia de %.2f
euros.\n", gMax, nombreCombustible(gMax), ganancias[gMax]);
system ("PAUSE");
}

char *diaSemana(int d)
{
char *dia[] = {"lunes","martes","miercoles","jueves","viernes","sabado","domingo"};
return dia[d];
}

char *nombreCombustible(int c)
{
char *nombre[] = {"EuroSuper-95","Extra-98","Star-97","ExtraDiesel","Gasoleo-A"};
return nombre[c];
}

AMPLIACIONES PROPUESTAS

1. Al principio de semana introducir, además del tipo de ganancia de cada combustible, también su precio en
euros. Ambos datos se almacenarán en un array de estructuras.

2. En las ventas semanales, introducir cada venta bien en litros o bien en euros. Para ello se pedirán tres
datos (ya no dos): nº surtidor, la letra L (litros) o la E (euros), y la cantidad vendida en litros o en euros.

3. Acumular la cantidad de euros recibidos cada día e imprimirla al finalizar la toma de datos de cada día,
para facilitar la comprobación de la caja diaria. También se imprimirá el total de ventas semanal en euros al
final de la semana.

4. Se podrá cerrar el programa en mitad de la semana, guardando antes todos los datos semanales
registrados hasta el momento en dos ficheros en disco: uno "gasolin1.dat" para los datos más estables de
tipos de surtidores y precio+ganancia de combustibles, y otro "gasolin2.dat" para los datos variables de
ventas semanales. Al comenzar la siguiente sesión del día siguiente, si existen esos ficheros en disco se
cargarán en los diversos arrays de memoria, para continuar con el proceso normal. Al finalizar la semana, el
fichero "gasolin2.dat" se elimina para comenzar la siguiente semana desde cero.

5. Al finalizar la semana, las estadísticas finales obtenidas se guardarán también en el disco, en un archivo
de texto cuyo nombre de fichero sea coincidente con la fecha del día actual de emisión de las estadísticas
(dd-mm-aa.txt). Esto permitirá revisar los datos de semanas pasadas.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#define DiasSemana 7
#define NumSurtidores 12
#define NumCombustibles 5
//Prototipos de funciones auxiliares
char *diaSemana(int d);
char *nombreCombustible(int c);
char sino(char *mensaje);
char *fechaActual(void);

main()
{
struct tipoCombus
{ float precio, tipoGanancia; } combus[NumCombustibles]; //array de estructuras
float litros[DiasSemana][NumSurtidores];
float ventasDia[DiasSemana], ganancias[NumCombustibles], ventasEuros[DiasSemana];
int tipoSurtidor[NumSurtidores];
int g, s, sc, sur, d, dini=0, dMax, dMaxLitros, gMax, combustible, diario, surtidor, hayFich1=0;
char le, resp, fecha[15]="";
float lit, pvp, totVentas;
FILE *pf;

system("CLS");
printf("DATOS FIJOS DE LA SEMANA:\n\n");
if ((pf=fopen("gasolin1.dat","rb"))!=NULL)
//Existe el fichero gasolin1.dat, lo cargamos en los arrays de surtidores y combustibles
{ fread(tipoSurtidor,sizeof(tipoSurtidor),1,pf); fread(combus,sizeof(combus),1,pf);
fclose(pf); hayFich1=1;
resp=sino("Desea modificar los datos de tipo de combustible por surtidor?");
}
if (!hayFich1 || resp=='S')
{ //Comienzo de semana, lectura del tipo de combustible que tiene cada surtidor:
printf("Introduce el tipo de combustible que tiene cada surtidor:\n");
for (g=0; g<NumCombustibles; g++) printf("%d=%s ", g, nombreCombustible(g));
printf("\n");
for (s=0; s<NumSurtidores; s++)
{ printf(" Surtidor %d: ", s); sc=scanf("%d", &tipoSurtidor[s]); fflush(stdin);
if (sc!=1 || tipoSurtidor[s]<0 || tipoSurtidor[s]>=NumCombustibles)
{ printf("Tipo incorrecto.\n"); s--; }
}
}

if (hayFich1)
resp=sino("\nDesea modificar los datos de precio y ganancia por combustible?");
if (!hayFich1 || resp=='S')
{ //Lectura de los precios y las ganancias por cada litro de combustible vendido
printf("\nIntroduce el precio y la ganancia en Euros de cada litro de combustible:\n");
for (g=0; g<NumCombustibles; g++)
{ printf(" Tipo %d (%s): Precio, ganancia: ", g, nombreCombustible(g));
sc=scanf("%f %f", &combus[g].precio, &combus[g].tipoGanancia); fflush(stdin);
if (sc!=2 || combus[g].precio<0 || combus[g].precio>10 || combus[g].tipoGanancia<0 ||
combus[g].tipoGanancia>10)
{ printf("Datos incorrectos.\n"); g--; }
}
}

if ((pf=fopen("gasolin2.dat","rb"))==NULL) //Si no existe el fichero gasolin2.dat


{ //Inicializar los contadores de euros diarios vendidos
for (d=0; d<DiasSemana; d++) ventasEuros[d]=0;
//Inicializar todos los surtidores en todos los días a 5000 litros
for (d=0; d<DiasSemana; d++)
for (s=0; s<NumSurtidores; s++) litros[d][s]=5000;
}
else //Existe el fichero gasolin2.dat, lo cargamos en los arrays de ventas y litros
{ fread(ventasEuros,sizeof(ventasEuros),1,pf); fread(litros,sizeof(litros),1,pf);
fclose(pf); system("CLS");
do //Pedir el dia actual de la semana
{ printf("Que dia de la semana es hoy? (1 a %d): ", DiasSemana); scanf("%d", &dini); fflush(stdin);
} while (dini<1 || dini>DiasSemana);
dini--;
}

//Para cada día de la semana, leer sus ventas


for (d=dini; d<DiasSemana; d++)
{ //Leer ventas del día d
system("CLS");
printf("VENTAS SEMANALES:\n\n");
printf("Dia %d (%s):\n", d+1, diaSemana(d));
printf(" Surtidor, L/E, cantidad: "); sc=scanf("%d %c %f", &sur, &le, &lit); fflush(stdin);
while (sc>0) //Mientras no se escriba FIN
{ le = toupper(le); //Convertimos la letra a mayúsculas
if (sc!=3 || sur<0 || sur>=NumSurtidores || lit<0 || lit>1000 || (le!='L' && le!='E')) //Confirmar valores
printf("\tDatos incorrectos.\n");
else
{ if (le=='E') //lit contiene la cantidad de euros pagada
{ ventasEuros[d] += lit; //Se acumulan los euros pagados
lit = (int)(lit/combus[tipoSurtidor[sur]].precio*100)/100.0; //Se calculan los litros, con 2 decimales
printf("\tLitros: %.2f", lit);
}
else //lit contiene los litros vendidos
{ pvp = (int)(lit*combus[tipoSurtidor[sur]].precio*100)/100.0; //Cálculo del precio en euros con 2 decimales
ventasEuros[d] += pvp; //Se acumulan los euros pagados
printf("\tEuros: %.2f", pvp);
}
if (litros[d][sur]>=lit) //Comprobar si el surtidor tiene suficientes litros
litros[d][sur]-=lit;
else
{ //No hay suficientes litros, se dan los que hay
printf("\tSe llenara con %.2f litros", litros[d][sur]);
litros[d][sur]=0 ;
}
printf("\tLitros Restantes Surtidor: %.2f\n", litros[d][sur]);
}
printf(" Surtidor, L/E, cantidad: "); sc=scanf("%d %c %f", &sur, &le, &lit); fflush(stdin);
}
printf("\nTotal ventas del dia: %.2f\n", ventasEuros[d]);
if (d<DiasSemana-1)
if (sino("Terminar por hoy el programa?")=='S') break;
}

if (d<DiasSemana-1)
{ //Grabación de ficheros entre semana
if ((pf=fopen("gasolin1.dat","wb"))==NULL) printf("ERROR de grabacion de fichero gasolin1.dat.\n");
else //Grabar el fichero gasolin1.dat con los datos fijos de surtidores y combustibles
{ fwrite(tipoSurtidor,sizeof(tipoSurtidor),1,pf); fwrite(combus,sizeof(combus),1,pf);
fclose(pf);
printf("Datos fijos de surtidores y combustibles guardados.\n");
}

if ((pf=fopen("gasolin2.dat","wb"))==NULL) printf("ERROR de grabacion de fichero gasolin2.dat.\n");


else //Grabar el fichero gasolin2.dat con los datos variables de cada semana (ventas y litros)
{ fwrite(ventasEuros,sizeof(ventasEuros),1,pf); fwrite(litros,sizeof(litros),1,pf);
fclose(pf);
printf("Datos de ventas y litros semanales guardados.\n");
}
}
else
{ //Es final de semana, obtener estadísticas finales
strcpy(fecha, fechaActual()); strcat(fecha, ".txt"); //Obtener nombre del fichero de texto de salida
if ((pf=fopen(fecha,"w"))==NULL) printf("ERROR al crear informe de salida.\n"); //Abrir el fichero
system("CLS");
printf("ESTADISTICAS SEMANALES:\n\n");
if (pf!=NULL) fprintf(pf, "ESTADISTICAS SEMANALES:\n\n");
//Indicar las ventas totales semanales en euros
for (totVentas=d=0; d<DiasSemana; d++)
totVentas+=ventasEuros[d];
printf("Ventas totales de la semana: %.2f Euros\n", totVentas);
if (pf!=NULL) fprintf(pf, "Ventas totales de la semana: %.2f Euros\n", totVentas);

//Indicar qué días y qué surtidores se han vaciado completamente


for (d=0; d<DiasSemana; d++)
for (s=0; s<NumSurtidores; s++)
if (litros[d][s]==0)
{ printf("El dia %d (%s) el surtidor %d (%s) se ha quedado sin combustible.\n", d+1, diaSemana(d), s,
nombreCombustible(tipoSurtidor[s]));
if (pf!=NULL) fprintf(pf, "El dia %d (%s) el surtidor %d (%s) se ha quedado sin combustible.\n", d,
diaSemana(d), s, nombreCombustible(tipoSurtidor[s]));
}

//Indicar qué día se han vendido más litros


for (d=0; d<DiasSemana; d++) //Calcular para cada día los litros vendidos
{ for (ventasDia[d]=s=0; s<NumSurtidores; s++)
ventasDia[d] += (5000-litros[d][s]);
}
for (dMax=d=0; d<DiasSemana; d++) //Calcular el día que se ha vendido más
{ if (ventasDia[d]>ventasDia[dMax]) dMax=d; }
printf("El dia de la semana que se han vendido mas litros es %d (%s) con %.2f litros.\n", dMax+1,
diaSemana(dMax), ventasDia[dMax]);
if (pf!=NULL) fprintf(pf, "El dia de la semana que se han vendido mas litros es %d (%s) con %.2f
litros.\n", dMax, diaSemana(dMax), ventasDia[dMax]);

//Indicar qué tipo de gasolina ha dado más beneficio esta semana, y cuánto ha sido
//Inicializar a cero el array de ganancias
for (g=0; g<NumCombustibles; g++) ganancias[g]=0;
for (s=0; s<NumSurtidores; s++)
{ // Calcular los litros que ha vendido el surtidor s
for (surtidor=d=0; d<DiasSemana; d++) surtidor += (5000-litros[d][s]);
combustible=tipoSurtidor[s]; //Calcular el tipo de gasolina que vende el surtidor s
ganancias[combustible]+=surtidor; //Acumular litros vendidos por tipo de combustible
}
//Calcular ganancias de cada tipo de combustible
for (g=0; g<NumCombustibles; g++) ganancias[g] *= combus[g].tipoGanancia;
for (gMax=g=0; g<NumCombustibles; g++) //Calcular el combustible que ha dado mayor ganancia
if (ganancias[g]>ganancias[gMax]) gMax=g;
printf("El tipo de combustible que ha dado mayor ganancia es %d (%s) con una ganancia de %.2f
Euros.\n", gMax, nombreCombustible(gMax), ganancias[gMax]);
if (pf!=NULL) fprintf(pf, "El tipo de combustible que ha dado mayor ganancia es %d (%s) con una
ganancia de %.2f Euros.\n", gMax, nombreCombustible(gMax), ganancias[gMax]);
fclose(pf);
remove("gasolin2.dat"); //Borrar fichero de ventas y litros para comenzar la siguiente semana
}
system ("PAUSE");
}

char *diaSemana(int d) //devuelve el nombre del dia de la semana en función del nº de día
{ char *dia[] = {"lunes","martes","miercoles","jueves","viernes","sabado","domingo"};
return dia[d];
}

char *nombreCombustible(int c) //devuelve el nombre del combustible en función de su código


{ char *nombre[] = {"EuroSuper-95","Extra-98","Star-97","ExtraDiesel","Gasoleo-A"};
return nombre[c];
}

char sino(char *mensaje) //Presenta una pregunta en pantalla y lee una respuesta de tipo S/N
{ char resp;
fflush(stdin);
do
{ printf("%s (S/N): ", mensaje); resp=toupper(getchar()); fflush(stdin);
} while (resp!='N' && resp!='S');
return resp;
}

char *fechaActual(void) //devuelve la fecha actual en formato texto de tipo dd/mm/aa


{ static char fecha[11]="SinFecha"; FILE *pf;
system("DATE /T >FIC.TXT");
if ((pf=fopen("FIC.TXT","r"))!=NULL)
{ fgets(fecha, 11, pf); fecha[6]=fecha[8]; fecha[7]=fecha[9]; fecha[8]=0; fclose(pf); remove("FIC.TXT"); }
printf("Fecha: %s\n", fecha); system("PAUSE");
return fecha;
}
ESTADÍSTICA DE ENERGÍAS EN CENTRAL ELECTRICA
Una central eléctrica desea realizar un estudio sobre la cantidad de energía que suministra diariamente. Para
ello, el programa informático que se ha de desarrollar deberá permitir recoger los datos de las energías en
megavatios-hora (MWh) suministradas diariamente durante un período máximo de 52 semanas (1 año).

1. La entrada de datos se deberá programar de forma que, para cada semana, se introduzcan las energías
suministradas durante los 7 días. Cuando se desee finalizar la entrada de datos (por ejemplo, en el caso de
realizar el estudio para un periodo inferior a las 52 semanas) se tecleará FIN como dato de energía en el
primer día de la semana.
Ejemplo de entrada de datos:
Semana 1:
Energía suministrada del día 1: 207
Energía suministrada del día 2: 301
Energía suministrada del día 3: 222
Energía suministrada del día 4: 302
Energía suministrada del día 5: 22
Energía suministrada del día 6: 167
Energía suministrada del día 7: 125

Semana 2:
Energía suministrada del día 1: 367
Energía suministrada del día 2: 60
Energía suministrada del día 3: 120
Energía suministrada del día 4: 111
Energía suministrada del día 5: 301
Energía suministrada del día 6: 400
Energía suministrada del día 7: 434

Semana 3:
Energía suministrada del día 1: 211
Energía suministrada del día 2: 72
Energía suministrada del día 3: 441
Energía suministrada del día 4: 102
Energía suministrada del día 5: 21
Energía suministrada del día 6: 203
Energía suministrada del día 7: 317

Semana 4:
Energía suministrada del día 1: 401
Energía suministrada del día 2: 340
Energía suministrada del día 3: 161
Energía suministrada del día 4: 297
Energía suministrada del día 5: 441
Energía suministrada del día 6: 117
Energía suministrada del día 7: 206

Semana 5:
Energía suministrada del día 1: FIN

2. Para cada día de la semana, calcular y escribir la energía media e indicar cuál ha sido el día de mayor
energía media.

3. Calcular y escribir la energía media de todo el periodo sometido a estudio.

4. Calcular y escribir el número de días en los que la energía suministrada ha sido superior a la energía
media de todo el periodo (calculado en el apartado anterior).
5. Debido al libre mercado, semanalmente se establecen los precios de ganancia por megavatio-hora.
Introducir en un array la ganancia (€/megavatio) para cada semana del periodo estudiado, y calcular y
escribir la ganancia semanal y total de la central.

ANÁLISIS DEL PROBLEMA

Constantes del enunciado


1. NumDias = 7. Número de días para los que se va a realizar el estudio.
2. NumSemanas = 52. Número de semanas para las que se va a realizar el estudio.

Representación de las variables necesarias para la entrada


3. Necesitaremos una matriz (array bidimensional) energias de NumSemanas X NumDias posiciones para
almacenar las energías consumidas cada día de la semana.

energias: 0 1 2 ... NumDias-1 <= DIA


0 207 301 222 125
1 367 60 120 434

NumSemanas-1
SEMANA

4. Necesitamos un array unidimensional gananciaPS de NumSemanas posiciones para almacenar el precio


en euros del megavatio-hora en cada semana.

gananciaPS: 0 1 2 ….. NumSemanas-1 <= SEMANA

Representación de las variables necesarias para los resultados


5. Necesitaremos un array mediaD de NumDias posiciones para almacenar la energía media consumida
cada día de la semana.

mediaD: 0 1 2 ….. NumDias-1 <= DIA

Pasos a seguir en la resolución del problema


1. Inicializar el contador semanas a 0 (semanas).

2. Leer la energía correspondiente al primer día de la primera semana (valorLunes).

3. Mientras la energía leída (valorLunes) sea distinta de FIN y el contador de semanas (semanas) sea menor
a NumSemanas, hacer:
a. Almacenar la energía leída en la matriz potencias, en la fila semana y columna 0 (lunes).
b. Para el resto de los días de la semana (dia), leer la energía y almacenarla en la matriz potencias, en la
fila semana y columna dia.
c. Incrementar el contador semanas.
d. Leer la energía correspondiente al primer día de la semana (valorLunes).

4. Concluida la introducción semanal, decrementar en 1 el contador semanas para que indique el número de
la última semana hasta la que se han introducido datos.

5. Calcular la energía media de la semana y, para cada día, la energía media consumida y almacenarlo en el
array mediaD, de la siguiente forma:
a. Inicializar la energía media de la semana a 0 (enerMedia).
b. Para cada día de la semana:
I) Inicializar la suma de energías del día a 0 (mediaD[dia]=0).
II) Para cada semana tratada, acumular la energía gastada ese día de esa semana en la suma de
energías (mediaD).
III) Dividir la suma de las energías consumidas entre las semanas tratadas.
IV) Acumular la energía del día a la energía media de la semana.
6. Calcular la energía media de la semana. Para ello dividir la suma de las energías medias diarias
(enerMedia) entre el número de días. Escribir el resultado por pantalla.

7. Calcular el día de mayor consumo de la semana. Para ello hay que buscar la posición del valor máximo en
el array mediaD.

8. Inicializar el contador de días que superan la energía media a 0 (diasPM).

9. Para cada día de la semana, si la energía consumida esa semana y ese día ( energias[sem][dia]) es mayor
a la energía media (enerMedia) entonces incrementar el contador (diasPM).

10. Escribir por pantalla el valor del contador diasPM.

11. Calcular la ganancia semanal y la ganancia de todo el periodo. Para ello, inicializar a 0 la ganancia total
(gananciaTotal), y luego para cada semana:
a. Poner a 0 la ganancia de la semana (gananciaSemanal).
b. Para cada día acumular la energía consumida y almacenarlo en la variable gananciaSemanal.
c. Multiplicar la ganancia semanal (gananciaSemanal) con el precio del megavatio por cada semana
(almacenado en el array gananciaPS), y escribir por pantalla el resultado obtenido.
d. Acumular la ganancia semanal (gananciaSemanal) a la ganancia total (gananciaTotal).

12. Escribir por pantalla la ganancia total (gananciaTotal) de la central.

CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumDias 7
#define NumSemanas 52
char *diaSemana(int d);

main()
{
int energias[NumSemanas][NumDias];
float mediaD[NumDias], gananciaPS[NumSemanas];
float enerMedia, gananciaTotal, gananciaSemanal;
int semanas, diasPM, valor, dia, sem, dMax, sc;

// Lectura de los datos


system("CLS");
printf("Introduzca los consumos de energia semanales en MWh:\n");
for (semanas=0; semanas<NumSemanas; semanas++)
{ printf("\nSemana %d:\n", semanas+1);
for (dia=0; dia<NumDias; dia++)
{ printf("Energia suministrada el dia %d (%s): ", dia+1, diaSemana(dia));
sc=scanf("%d", &valor); fflush(stdin);
if (sc==0 && dia==0) break;
if (sc!=1 || valor<0) { printf("Dato incorrecto.\n"); dia--; }
else energias[semanas][dia]=valor;
}
if (sc==0 && dia==0) break;
}
printf("\n");

// Media de los lunes, de los martes,... y la media del periodo.


enerMedia=0;
for (dia=0; dia<NumDias; dia++)
{ mediaD[dia]=0;
for (sem=0; sem<semanas; sem++)
mediaD[dia] = mediaD[dia]+energias[sem][dia];
mediaD[dia] = mediaD[dia]/semanas;
printf("La media del dia %d (%s) es %.2f MWh\n", dia+1, diaSemana(dia), mediaD[dia]);
enerMedia = enerMedia+mediaD[dia];
}
enerMedia=enerMedia/NumDias;
printf("\nLa energia media de todo el periodo es %.2f MWh\n", enerMedia);

// Calcular el día con mayor energia.


dMax=0;
for (dia=1; dia<NumDias; dia++)
if (mediaD[dMax]<mediaD[dia]) dMax=dia;
printf("El dIa de la semana con media mayor es: %d (%s)\n", dMax+1, diaSemana(dMax));

// Numero de días que superan la energia media.


diasPM=0;
for (dia=0; dia<NumDias; dia++)
for (sem=0; sem<semanas; sem++)
if (energias[sem][dia]>enerMedia) diasPM++;
printf("NUmero de dIas que superan la energia media: %d\n", diasPM);

// Introducción de las ganancias semanales


printf("Introduzca la ganancia en Euros por MWh suministrado de cada semana:\n");
for (sem=0; sem<semanas; sem++)
{ printf("Semana %d: ", sem+1); sc=scanf("%f", &gananciaPS[sem]); fflush(stdin);
if (sc!=1 || gananciaPS[sem]<0)
{ printf("Dato incorrecto.\n"); sem--; }
}

// Calculo de ganancias
printf("\nLas ganancias semanales son:\n");
gananciaTotal=0;
for (sem=0; sem<semanas; sem++)
{ gananciaSemanal=0;
for (dia=0; dia<NumDias; dia++)
gananciaSemanal = gananciaSemanal+energias[sem][dia];
gananciaSemanal = gananciaSemanal*gananciaPS[sem];
printf("Semana %d - Ganancia: %.2f Euros\n", sem, gananciaSemanal);
gananciaTotal = gananciaTotal+gananciaSemanal;
}
printf("\nLa ganancia total conseguida es: %.2f Euros\n\n", gananciaTotal);
system("PAUSE");
}

char *diaSemana(int d)
{
char *dia[] = {"lunes","martes","miercoles","jueves","viernes","sabado","domingo"};
return dia[d];
}

AMPLIACIONES PROPUESTAS

1. Hacer que el programa solicite por teclado el número máximo de semanas a procesar (ya no será fijo 52
semanas), cuando se ejecute por primera vez. Luego se crearán y utilizarán "arrays dinámicos" del tamaño
indicado por este número de semanas.

2. Permitir la terminación prematura del programa sin haber introducido todos los datos, guardando en un
fichero en disco de nombre "central.dat" todos los datos de energías y precios introducidos hasta el momento.
Esto permitirá introducir los datos en varias sesiones del programa, cargando los datos del fichero al empezar
cada sesión.
3. Controlar los valores introducidos por teclado y emitir pitidos (\a) si son incorrectos, para volverlos a
introducir.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#define NumDias 7
char *diaSemana(int d);
int **crearArrayBidimensional(int filas, int columnas);

main()
{
int NumSemanas=0, **energias;
float mediaD[NumDias], *gananciaPS;
float enerMedia, gananciaTotal, gananciaSemanal;
int semanas, diasPM, valor, dia, sem=0, semini=0, seminiG=0, dMax, sc;
FILE *pf;
system("CLS");

//Lectura del fichero central1.dat, si existe


if ((pf=fopen("central1.dat", "rb"))==NULL) //El fichero no existe
do
{ printf("Indique el número de semanas a procesar: "); scanf("%d", &NumSemanas);
} while (NumSemanas<=0);
else //El fichero existe, averiguamos el número de semanas que contiene
{ fseek(pf, 0, SEEK_END); NumSemanas = ftell(pf)/sizeof(float); rewind(pf); }

//Crear array dinámico gananciaPS


gananciaPS = (float *)malloc(NumSemanas*sizeof(float));
if (gananciaPS==NULL) { printf("Falta memoria.\a\a"); getch(); exit(0); } //el mensaje emite 2 pitidos \a
//Crear matriz dinámica bidimensional energias
energias = crearArrayBidimensional(NumSemanas, NumDias);
if (energias==NULL) { printf("Falta memoria.\a\a"); getch(); free(gananciaPS); exit(0); }

if (pf==NULL) //El fichero no existe


{ //Poner a cero ambos arrays dinámicos
for (sem=0; sem<NumSemanas; sem++)
{ gananciaPS[sem]=0;
for (dia=0; dia<NumDias; dia++) energias[sem][dia]=0;
}
}
else //El fichero existe, cargamos los datos en los arrays
{ fread(gananciaPS, NumSemanas*sizeof(float), 1, pf); fclose(pf);
if ((pf=fopen("central2.dat", "rb"))==NULL) //El fichero central2.dat no existe
{ printf("ERROR: No existe fichero central2.dat.\a\a"); energias[0][0]=0; }
else
{ for (sem=0; sem<NumSemanas; sem++)
{ fread(energias[sem], NumDias*sizeof(int), 1, pf);
if (feof(pf)) { printf("ERROR en fichero central2.dat."); getch(); energias[sem][0]=0; break; }
}
fclose(pf);
}
while (energias[semini][0]>0) semini++; //Buscamos la primera semana vacía en energias
while (gananciaPS[seminiG]>0) seminiG++; //Buscamos la primera semana vacía en gananciasPS
}

//Lectura de los datos


system("CLS");
printf("Introduzca los consumos de energia semanales en MWh:\n");
for (semanas=semini; semanas<NumSemanas; semanas++)
{ printf("\nSemana %d:\n", semanas+1);
for (dia=0; dia<NumDias; dia++)
{ printf("Energia suministrada el dia %d (%s): ", dia+1, diaSemana(dia));
sc=scanf("%d", &valor); fflush(stdin);
if (sc==0 && dia==0) break;
if (sc!=1 || valor<0) { printf("Dato incorrecto.\a\a\n"); dia--; }
else energias[semanas][dia]=valor;
}
if (sc==0 && dia==0) break;
}
printf("\n");

//Media de los lunes, de los martes,... y la media del periodo.


enerMedia=0;
for (dia=0; dia<NumDias; dia++)
{ mediaD[dia]=0;
for (sem=0; sem<semanas; sem++)
mediaD[dia] = mediaD[dia]+energias[sem][dia];
mediaD[dia] = mediaD[dia]/semanas;
printf("La media del dia %d (%s) es %.2f MWh\n", dia+1, diaSemana(dia), mediaD[dia]);
enerMedia = enerMedia+mediaD[dia];
}
enerMedia=enerMedia/NumDias;
printf("\nLa energia media de todo el periodo es %.2f MWh\n", enerMedia);

//Calcular el día con mayor energia.


dMax=0;
for (dia=1; dia<NumDias; dia++)
if (mediaD[dMax]<mediaD[dia]) dMax=dia;
printf("El dia de la semana con media mayor es: %d (%s)\n", dMax+1, diaSemana(dMax));

//Numero de días que superan la energia media.


diasPM=0;
for (dia=0; dia<NumDias; dia++)
for (sem=0; sem<semanas; sem++)
if (energias[sem][dia]>enerMedia) diasPM++;
printf("Numero de dias que superan la energia media: %d\n", diasPM);

//Introducción de las ganancias semanales


printf("Introduzca la ganancia en Euros por MWh suministrado de cada semana:\n");
for (sem=seminiG; sem<semanas; sem++)
{ printf("Semana %d: ", sem+1); sc=scanf("%f", &gananciaPS[sem]); fflush(stdin);
if (sc!=1 || gananciaPS[sem]<0)
{ printf("Dato incorrecto.\a\a\n"); sem--; }
}

//Calculo de ganancias
printf("\nLas ganancias semanales son:\n");
gananciaTotal=0;
for (sem=0; sem<semanas; sem++)
{ gananciaSemanal=0;
for (dia=0; dia<NumDias; dia++)
gananciaSemanal = gananciaSemanal+energias[sem][dia];
gananciaSemanal = gananciaSemanal*gananciaPS[sem];
printf("Semana %d - Ganancia: %.2f Euros\n", sem, gananciaSemanal);
gananciaTotal = gananciaTotal+gananciaSemanal;
}
printf("\nLa ganancia total conseguida es: %.2f Euros\n\n", gananciaTotal);
//Grabar los ficheros
if ((pf=fopen("central1.dat", "wb"))==NULL) printf("ERROR al grabar fichero central1.dat.\a\a\n");
else { fwrite(gananciaPS, NumSemanas*sizeof(float), 1, pf); fclose(pf); }
if ((pf=fopen("central2.dat", "wb"))==NULL) printf("ERROR al grabar fichero central2.dat.\a\a\n");
else
{ for (sem=0; sem<NumSemanas; sem++) fwrite(energias[sem], NumDias*sizeof(int), 1, pf);
fclose(pf);
}
system("PAUSE");
}

char *diaSemana(int d) //devuelve el nombre del dia de la semana en función de su numero


{
char *dia[] = {"lunes","martes","miercoles","jueves","viernes","sabado","domingo"};
return dia[d];
}

//Función para creación de un array bidimensional dinámico de tipo int


int **crearArrayBidimensional(int filas, int columnas)
{
int **punt, i;
if ((punt=(int **)malloc(filas*sizeof(int *)))==NULL) //creamos el array de punteros auxiliares
{ printf("ERROR: Falta memoria. "); system("PAUSE"); return NULL; }
for (i=0; i<filas; i++)
{ if ((punt[i]=(int *)malloc(columnas*sizeof(int)))==NULL) //creamos cada una de las filas
{ printf("ERROR: Falta memoria. "); system("PAUSE");
while (--i>=0) { free(punt[i]); } //si faltó memoria, liberamos todo lo que llevábamos reservado
free(punt); return NULL;
}
}
return punt; //retornamos el puntero maestro doble que apunta al array de punteros auxiliares
}
ESTADÍSTICA DE VENTAS EN UNA TIENDA
Una pequeña tienda guarda información de las ventas de sus artículos a lo largo del año 2015. La tienda
dispone sólo de 10 artículos diferentes, codificados del 0 al 9. Se pide escribir un programa que realice las
siguientes tareas:

1. Leer las ventas de los artículos (en unidades) a lo largo de los 12 meses del año 2015.
Ejemplo de ejecución:
Introduce las ventas de los artículos de la siguiente forma (en negrita los datos tecleados por el usuario):
Artículo, mes, unidades vendidas: 1 5 800
Artículo, mes, unidades vendidas: 0 4 700
Artículo, mes, unidades vendidas: 4 5 100
Artículo, mes, unidades vendidas: 6 5 800
Artículo, mes, unidades vendidas: 6 11 800
..............
Artículo, mes, unidades vendidas: 1 0 800
Artículo, mes, unidades vendidas: FIN
Los datos se introducen a través de tríos desordenados (Artículo, mes, unidades vendidas). Sólo se
introducen los datos de los meses y artículos que han tenido ventas. Las ventas indicarán el total de
unidades vendidas de ese artículo en ese mes.

2. Leer la lista de precios por artículo y obtener el mes que más ventas en euros ha tenido.
Ejemplo de ejecución:
Introduce los precios de los artículos (en negrita los datos tecleados por el usuario):
Precio del artículo 0: 123,50
Precio del artículo 1: 12,03
Precio del artículo 2: 1,73
............
Precio del artículo 9: 129
El mes 3 es el mes que más ventas ha tenido: 1000,50 euros.

3. Por cada artículo leer el total de ventas en euros del periodo comprendido entre los meses de julio y
diciembre del año 2014.
Ejemplo de ejecución:
Introduce las ventas en euros realizadas entre los meses de Julio y Diciembre del 2014:
Ventas del artículo 0: 970,52
Ventas del artículo 1: 8870,75
Ventas del artículo 2: 1170
...................
Ventas del artículo 9: 909870

4. Obtener estadísticas finales comparando estos datos de 2014 con los del mismo periodo del 2015 (leídos
en el apartado 1) e indicando cuántos artículos han superado las ventas en euros en el año 2015 y cuáles
son estos artículos.
Ejemplo de ejecución:
Los artículos que han superado las ventas, en el periodo comprendido entre los meses de Julio a Diciembre,
respecto al año 2014 son: 2, 5, 6, 9
Total artículos: 4

ANÁLISIS DEL PROBLEMA

Constantes del enunciado:


1. NumMeses = 12. Número de meses para los que se va ha realizar el estudio.
2. NumArticulos = 10. Número de artículos que vende la tienda.
3. Julio = 7. Es el mes a partir del cual nos piden que comparemos con las ventas del año 2014.

Representación del las variables necesarias para la entrada:


4. Necesitaremos una matriz (array bidimensional) ventas de NumArticulos x NumMeses posiciones, dónde
se almacenarán las unidades de cada artículo vendidas cada mes.
ventas: 0 1 2 ... NumMeses-1 <= MES
0 450 520 700 150
1 220 370 430 200

NumArticulos-1 460 330 220 100
ARTICULO

5. Necesitaremos un array unidimensional precio de NumArticulos posiciones dónde almacenaremos el


precio de cada artículo.

precio: 0 1 2 ….. NumArticulos-1 <= ARTICULO


23,50 12,60 8,75 14,30

6. Necesitaremos un array unidimensional ventas2014 de NumArticulos posiciones donde almacenaremos


las ventas en euros de cada artículo correspondientes a los meses de Julio – Diciembre del año 2014.

ventas2014: 0 1 2 ….. NumArticulos-1 <= ARTICULO


850,50 720,00 1200,00 450,30

Representación de las variables necesarias para los resultados:


7. Necesitamos un array unidimensional ventasMes de NumMeses posiciones, dónde almacenaremos las
ventas en euros realizadas cada mes teniendo en cuenta todos los artículos.

ventasMes: 0 1 2 ….. NumMeses-1 <= MES

8. Necesitaremos un array unidimensional ventas2015 de NumArticulos posiciones, dónde almacenaremos


las ventas en euros de cada artículo correspondientes a los meses de Junio – Diciembre del año 2015.

ventas2015: 0 1 2 ….. NumArticulos-1 <= ARTICULO

Pasos a seguir en la resolución del problema:


1. Inicializar la matriz ventas a 0.

2. Leer primera tripleta (art, mes, vent).

3. Mientras no se teclee FIN, hacer:


a. Almacenar las ventas en la matriz ventas, en la fila art y columna mes.
b. Leer siguiente tripleta (art, mes, vent).

4. Para cada artículo leer su precio y almacenarlo en el array precio.

5. Para cada mes:


a. Inicializar las ventas en euros del mes a 0 (ventasMes).
b. Para cada artículo (art), sumar a las ventas del mes (mes). Para calcular las ventas del mes en euros,
multiplicar las unidades vendidas del artículo en ese mes (almacenado en la matriz ventas[art][mes]) con
el precio del artículo (almacenado en el array precio[art]).

6. Calcular y escribir el mes de mayor ganancia, es decir, calcular la posición del valor máximo del array
ventasMes (calculado en el apartado 5).

7. Leer las ventas en euros de cada artículo correspondiente a los meses de Julio-Diciembre del año 2014 y
almacenarlo en el array ventas2014.

8. Calcular las ventas en euros de cada artículo correspondientes a los meses de Julio-diciembre del año
2015. Para ello, realizaremos para cada artículo los siguientes pasos:
a. Inicializar ventas del artículo a 0 (ventas2015)
b. Para cada mes entre los meses de Julio a Diciembre sumar la cantidad de artículos vendidos ese mes
(almacenada en la matriz ventas) a los ya acumulados.
c. Multiplicar la cantidad de artículos vendidos por el precio del artículo (almacenado en el array precio).

9. Inicializar el contador de artículos con mayor venta en 2015 a 0 (num).

10. Para cada artículo (art), si las ventas del año 2015 (ventas2015[art]) son mayores que las del año 2014
(ventas2014[art]) entonces escribir el número del artículo e incrementar contador (num) en 1.

11. Escribir contador (num) de artículos con mayor ganancia en 2015.

CÓDIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumArticulos 10
#define NumMeses 12
#define Julio 7

main()
{
int ventas[NumArticulos][NumMeses];
float ventas2014[NumArticulos], ventas2015[NumArticulos], ventasMes[NumMeses];
float precio[NumArticulos];
int mVentaMax, art, mes, vent, num, sc;

// Inicializar a 0 la matriz Ventas para que todas las posiciones tengan valores válidos tras la lectura
for (art=0; art<NumArticulos; art++)
for (mes=0; mes<NumMeses; mes++)
ventas[art][mes]=0;

// Introducción de los datos de ventas


system("CLS");
printf("VENTA DE ARTICULOS:\nTeclee FIN para terminar\n\n");
printf("Articulo, Mes, Unidades vendidas: "); sc=scanf("%d %d %d", &art, &mes, &vent); fflush(stdin);
while (sc>0) // Mientras no se escriba FIN
{ ventas[art][mes]=vent;
printf("Articulo, Mes, Unidades vendidas: "); sc=scanf("%d %d %d", &art, &mes, &vent); fflush(stdin);
}

// Lectura de los precios de los artículos


printf("\nDame los precios de los articulos:\n");
for (art=0; art<NumArticulos; art++)
{ printf("Precio del articulo %d: ", art); scanf("%f", &precio[art]); fflush(stdin); }

// Cálculo de la ganancia mensual por producto


for (mes=0; mes<NumMeses; mes++)
{ ventasMes[mes]=0;
for (art=0; art<NumArticulos; art++)
ventasMes[mes] = ventasMes[mes] + (ventas[art][mes] * precio[art]);
}

// Posición del array con máximo valor


mVentaMax=0;
for (mes=0; mes<NumMeses; mes++)
if (ventasMes[mVentaMax]<ventasMes[mes]) mVentaMax = mes;
printf("\nEl mes con mayor ganancia es %d, con unas ventas de %.2f euros.\n", mVentaMax,
ventasMes[mVentaMax]);

// Lectura de ventas por artículo entre Julio-Diciembre del 2014


printf("\nDame las ventas en euros realizadas entre Julio y Diciembre del 2014:\n");
for (art=0; art<NumArticulos; art++)
{ printf("Ventas del articulo %d: ", art); scanf("%f", &ventas2014[art]); fflush(stdin); }

// Cálculo de las ventas por artículo entre Julio-Dic del 2015


for (art=0; art<NumArticulos; art++)
{ ventas2015[art]=0;
for (mes=Julio; mes<NumMeses; mes++)
ventas2015[art] = ventas2015[art] + ventas[art][mes];
ventas2015[art] = ventas2015[art]*precio[art];
}

// Comparar las ventas del periodo de Julio-Diciembre del año 2014 y 2015
printf("\nLos articulos que han superado las ventas en el periodo comprendido entre los meses de Julio y
Diciembre de 2015, respecto al año 2014, son: ");
num=0;
for (art=0; art<NumArticulos; art++)
if (ventas2014[art]<ventas2015[art])
{ printf("%d ", art); num++; }
printf("\nTotal articulos: %d\n\n", num);
system ("PAUSE");
}

AMPLIACIONES PROPUESTAS

1. Manejar el programa mediante un Menú principal con las siguientes opciones: "1-Leer Ventas 2015", "2-
Leer Precios 2015", "3-Leer Ventas 2014", "4-Mostrar Estadísticas", "0-Salir".

2. Controlar los valores introducidos por teclado y emitir pitidos si son incorrectos, para volverlos a introducir.

3. Permitir la terminación prematura del programa sin haber introducido todos los datos y precios de artículos,
guardando en un fichero en disco de nombre "tienda.dat" todos los datos introducidos hasta el momento. Esto
permitirá introducir los datos en varias sesiones del programa, cargando los datos del fichero al empezar
cada sesión.

4. Las estadísticas finales sólo se emitirán cuando estén introducidos todos los precios de los 10 artículos.

5. Escribir el nombre del mes en el mensaje de salida del mes con mayor ganancia.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#include <graph.h> //necesario para la función _settextposition
#define cursor(a,b) _settextposition(a,b) //Macro para posicionar el cursor de texto en la pantalla
#define NumArticulos 10
#define NumMeses 12
#define Julio 7
//declaraciones prototipo de funciones auxiliares
char *nombreMes(int d);
char menu(void);
void marco(int fil1, int col1, int fil2, int col2);

main()
{
int ventas[NumArticulos][NumMeses];
float ventas2014[NumArticulos], ventas2015[NumArticulos], ventasMes[NumMeses];
float precio[NumArticulos];
int mVentaMax, art, mes, vent, num, sc, leido;
FILE *pf; char opc=' ';
if ((pf=fopen("tienda.dat","rb"))!=NULL) //Cargar fichero de datos en los arrays
{ fread(ventas, sizeof(ventas), 1, pf); fread(precio, sizeof(precio), 1, pf); fclose(pf); }
else //Inicializar a 0 los arrays
{ for (art=0; art<NumArticulos; art++)
for (mes=0; mes<NumMeses; mes++)
ventas[art][mes]=0;
for (art=0; art<NumArticulos; art++) precio[art]=0;
}

//BUCLE DEL MENU


while (opc!='0')
{ opc = menu();
if (opc=='1') //LEER VENTAS 2015
{
//Introducción de los datos de ventas
printf("LEER VENTAS DE ARTICULOS EN 2015:\nTeclee FIN para terminar\n\n");
printf("Articulo, Mes, Unidades vendidas: "); sc=scanf("%d %d %d", &art, &mes, &vent); fflush(stdin);
while (sc>0) //Mientras no se escriba FIN
{ if (art<0 || art>=NumArticulos || mes<0 || mes>=NumMeses || vent<0)
printf("Datos incorrectos.\a\a\n"); //Cada \a emite un pitido
else
ventas[art][mes]=vent;
printf("Articulo, Mes, Unidades vendidas: "); sc=scanf("%d %d %d", &art, &mes, &vent); fflush(stdin);
}
}
else if (opc=='2') //LEER PRECIOS DE ARTICULOS
{
//Lectura de los precios de los artículos
printf("LEER PRECIOS DE ARTICULOS:\n");
printf("Introduce los precios de los articulos (FIN=Terminar):\n");
for (art=leido=0; art<NumArticulos; art++)
{ if (precio[art]==0) //Leer sólo los articulos aun no leidos
{ leido=1;
printf("Precio del articulo %d: ", art); sc=scanf("%f", &precio[art]); fflush(stdin);
if (sc==0) break;
}
}
if (!leido) { printf("Ya estan introducidos todos los precios.\n"); system("PAUSE"); }
}
else if (opc=='3') //LEER VENTAS 2014
{
//Lectura de ventas por artículo entre Julio-Diciembre del 2014
printf("LEER VENTAS DE ARTICULOS EN 2014:\n");
printf("Introduce las ventas en euros realizadas entre Julio y Diciembre del 2014:\n");
for (art=0; art<NumArticulos; art++)
{ printf("Ventas del articulo %d: ", art); sc=scanf("%f", &ventas2014[art]); fflush(stdin);
if (sc!=1) { printf("Dato incorrecto.\a\a\n"); art--; } //Se emiten dos pitidos
}
}
else if (opc=='4') //MOSTRAR ESTADISTICAS
{
printf("MOSTRAR ESTADISTICAS:\n");
if (precio[NumArticulos-1]==0)
{ printf("\nNo se han introducido todos los precios.\n\a\a"); getch(); continue; }
//Cálculo de la ganancia mensual por producto
for (mes=0; mes<NumMeses; mes++)
{ for (ventasMes[mes]=art=0; art<NumArticulos; art++)
ventasMes[mes] += (ventas[art][mes] * precio[art]);
}
//Posición del array con máximo valor
for (mVentaMax=mes=0; mes<NumMeses; mes++)
if (ventasMes[mVentaMax]<ventasMes[mes]) mVentaMax = mes;
printf("\nEl mes con mayor ganancia es %d (%s), con unas ventas de %.2f euros.\n", mVentaMax,
nombreMes(mVentaMax), ventasMes[mVentaMax]);
//Cálculo de las ventas por artículo entre Julio-Dic del 2015
for (art=0; art<NumArticulos; art++)
{ for (ventas2015[art]=0,mes=Julio; mes<NumMeses; mes++)
ventas2015[art] += ventas[art][mes];
ventas2015[art] = ventas2015[art]*precio[art];
}
//Comparar las ventas del periodo de Julio-Diciembre del año 2014 y 2015
printf("\nLos articulos que han superado las ventas en el periodo comprendido entre los meses de Julio
y Diciembre de 2015, respecto al año 2014, son: ");
for (num=art=0; art<NumArticulos; art++)
if (ventas2014[art]<ventas2015[art])
{ printf("%d ", art); num++; }
printf("\nTotal articulos: %d\n\n", num);
system ("PAUSE");
}
}

//Grabar los datos en el fichero tienda.dat


if ((pf=fopen("tienda.dat", "wb"))==NULL) printf("ERROR al grabar los datos en el fichero.\a\a\n");
else
{ fwrite(ventas, sizeof(ventas), 1, pf); fwrite(precio, sizeof(precio), 1, pf); fclose(pf); }
}

char *nombreMes(int d) //devuelve el nombre del mes en función de su número


{ char *mes[] = {"enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre",
"noviembre","diciembre"};
return mes[d];
}

char menu(void) //Pintar el menú y leer tecla


{ char op='0';
do
{ system("cls");
marco(1,1,24,80); marco(8,26,14,53);
cursor(9,28); printf("1. Leer Ventas 2015.");
cursor(10,28); printf("2. Leer Precios 2015.");
cursor(11,28); printf("3. Leer Ventas 2014.");
cursor(12,28); printf("4. Mostrar Estadisticas.");
cursor(13,28); printf("0. Salir del programa.");
cursor(16,28); printf("Elija opcion: ");
op = toupper(getch()); system("cls");
} while (op!='1' && op!='2' && op!='3' && op!='4' && op!='0');
return (op);
}

void marco(int fil1, int col1, int fil2, int col2) //Pintar un marco de asteriscos
{ int i;
cursor(fil1,col1); for (i=0; i<col2-col1+1; i++) printf("*");
for (i=fil1+1; i<fil2; i++)
{ cursor(i,col1); printf("*"); cursor(i,col2); printf("*"); }
cursor(fil2,col1); for (i=0; i<col2-col1+1; i++) printf("*");
}
CONTROL DE PEAJES EN AUTOPISTA
Una autopista desea un programa informático que recoja mensualmente datos sobre los consumos de sus
clientes habituales y realice los cálculos que abajo se enumeran. El programa recogerá el número de veces
que pasan los clientes habituales por los distintos peajes de la autopista, todo ello con vistas a poder
realizarles una serie de descuentos y poder realizar también un estudio estadístico.
Esta autopista tiene actualmente 1000 clientes reconocidos como habituales a través de un contrato, y el
número de peajes en este trayecto es de 15. En un array tendremos que introducir los precios de cada uno
de los 15 peajes. Para ello el programa le pedirá al usuario el precio de cada peaje de forma secuencial.
Después se introducirán los datos de los clientes mediante pares de datos que indiquen número de cliente y
número de peaje por el que ha pasado. Tenemos que tener en cuenta que puede haber más de una entrada
para el mismo cliente y número de peaje, con lo que habrá que acumular el número de veces que ha pasado
por el mismo peaje.
Además, a la vez que introducimos estos datos, habrá que calcular en dos arrays el número total de viajes
que lleva realizados el cliente y el importe que va acumulando por todos sus tránsitos, teniendo en cuenta
que al precio del peaje se le aplica un descuento en función del siguiente criterio:
• a los 8 primeros viajes un 25% sobre el precio del peaje.
• del 9º al 20º viaje un 55% sobre el precio del peaje.
• a partir del 20º un 75% sobre el precio del peaje.

Ejemplo: (en negrita los datos introducidos por el usuario)


Introducir código de cliente y código de peaje (escriba FIN para terminar):
Cliente, peaje: 1 2
Cliente, peaje: 8 4
Cliente, peaje: 1 2
...
Cliente, peaje: FIN

Las tareas a realizar son:


1. Obtener cuál es el peaje más transitado por los clientes habituales.
2. Para cada cliente obtener el número de peaje que más utiliza.
3. Calcular para cada cliente el ahorro que ha obtenido este mes, por ser cliente habitual.
4. Listar por pantalla para cada cliente, el número total de viajes que ha realizado este mes, el importe total a
pagar y el ahorro que ha obtenido. El listado tendrá que presentar el siguiente formato ejemplo:

Cliente Total viajes Importe Ahorro


0 20 120 30
1 10 79 15

ANÁLISIS DEL PROBLEMA

Constantes del enunciado


1. NumPeajes = 15. Número de peajes que se van a controlar en el programa.
2. NumClientes = 10. Número de clientes habituales.

Representación de las variables necesarias para la entrada


3. Necesitaremos una matriz viajes de NumClientes x NumPeajes posiciones para almacenar los peajes por
los que pasa cada uno de los clientes habituales.
viajes: 0 1 2 ... NumPeajes-1 <= PEAJE
0 5 9 12 6
1 8 4 10 7

NumClientes-1
CLIENTE

4. Necesitaremos un array precioPeajes de NumPeajes posiciones para almacenar el precio en euros de


cada peaje.
precioPeajes: 0 1 2 ….. NumPeajes-1 <= PEAJE

Representación de las variables necesarias para los resultados


5. Necesitamos un array viajesTotales de NumClientes posiciones para almacenar el número total de pasos
por los peajes que tiene un cliente habitual.
viajesTotales: 0 1 2 ….. NumClientes-1 <= CLIENTE

6. Necesitaremos un array debePagar de NumClientes posiciones para almacenar los euros que tiene que
pagar cada uno de los clientes habituales.
debePagar: 0 1 2 ….. NumClientes-1 <= CLIENTE

7. Necesitamos un array pasoPeajes de NumPeajes posiciones para almacenar el número de veces que se
ha pasado por cada uno de los peajes.
pasoPeajes: 0 1 2 ….. NumPeajes-1 <= PEAJE

8. Necesitaremos un array deberiaHaberPagado de NumClientes posiciones para almacenar la cantidad de


euros que debería pagar cada cliente habitual si no se le aplica ningún descuesto.
deberiaHaberPagado: 0 1 2 ….. NumClientes-1 <= CLIENTE

9. Necesitamos un array ahorro de NumClientes posiciones para almacenar la cantidad de euros que ahorra
cada uno de los clientes habituales.
ahorro: 0 1 2 ….. NumClientes-1 <= CLIENTE

Pasos a seguir en la resolución del problema


1. Inicializar la matriz viajes a 0.

2. Para cada peaje, leer el precio y guardarlo en el array precioPeajes.

3. Inicializar a 0 los arrays viajesTotales y debePagar.

4. Leer el primer par de cliente y peaje (c, p).

5. Mientras no se teclee FIN, hacer:


a. Guardar el viaje leído.
b. Sumar al cliente el viaje leído.
c. Calcular el precio que tiene que pagar el cliente teniendo en cuenta los datos introducidos hasta el
momento.
d. Leer otro par (c, p).

6. Inicializar a 0 el array pasoPeajes.

7. Para cada peaje, calcular el número de veces que han pasado el conjunto de los clientes habituales por él.

8. Calcular el mayor valor del array pasoPeajes para saber cuál ha sido el peaje por el que han pasado más
clientes habituales.

9. Para cada cliente, buscar cuál es el peaje por donde ha pasado más veces.

10. Inicializar el array deberiaHaberPagado.

11. Para cada cliente, calcular cuánto deberían haber pagado sin descuentos.

12. Para cada cliente, calcular cuánto ha ahorrado.


13. Para cada cliente:
a. Escribir los viajes realizados.
b. Escribir lo que debe pagar.
c. Escribir lo que ha ahorrado.

CODIGO C

#include <stdio.h>
#include <stdlib.h>
#define NumPeajes 15
#define NumClientes 10

main()
{
int viajes[NumClientes][NumPeajes];
float precioPeajes[NumPeajes], debePagar[NumClientes];
int viajesTotales[NumClientes], pasoPeajes[NumPeajes];
float deberiaHaberPagado[NumClientes], ahorro[NumClientes];
int c, p, maxPeaje, sc;
system("CLS");

//Inicializamos la matriz viajes a 0


for (c=0; c<NumClientes; c++)
for (p=0; p<NumPeajes; p++)
viajes[c][p]=0;

//Leer el precio de cada uno de los peajes


for (p=0; p<NumPeajes; p++)
{ printf("Introduce el precio del peaje %d: ", p);
scanf("%f", &precioPeajes[p]);
}

//Inicializamos el array viajesTotales y debePagar a 0.


for (c=0; c<NumClientes; c++)
viajesTotales[c]=debePagar[c]=0;

//Leemos y guardamos los viajes que ha hecho cada cliente.


printf("\nIntroduce el codigo del cliente y del peaje (para terminar teclea FIN):\n");
printf("Cliente, Peaje: "); sc=scanf ("%d %d", &c, &p);
while (sc==2)
{ if (c<0 || c>=NumClientes || p<0 || p>=NumPeajes)
printf("Datos incorrectos.\a\a\n");
else
{ viajes[c][p]++; viajesTotales[c]++;
if (viajesTotales[c]<=8)
debePagar[c]=debePagar[c]+precioPeajes[p]*0.75;
else if (viajesTotales[c]<=20)
debePagar[c]=debePagar[c]+precioPeajes[p]*0.45;
else
debePagar[c]=debePagar[c]+precioPeajes[p]*0.25;
}
printf("Cliente, Peaje: "); sc=scanf ("%d %d", &c, &p);
}

// Calculamos el número de veces que se ha pasado por cada peaje


for (p=0; p<NumPeajes; p++)
{ pasoPeajes[p]=0; // Inicializamos la posición a 0.
for (c=0; c<NumClientes; c++)
pasoPeajes[p]=pasoPeajes[p]+viajes[c][p];
}
//Calculamos el peaje por el que más han pasado los clientes.
maxPeaje=0;
for (p=1; p<NumPeajes; p++)
if (pasoPeajes[p]>pasoPeajes[maxPeaje]) maxPeaje=p;
printf("\n\nEl peaje mas utilizado es el %d.\n\n", maxPeaje);

//Escribir el peaje que más utiliza cada uno de los clientes.


for (c=0; c<NumClientes; c++)
{ if (viajesTotales[c]==0)
printf("El cliente %d no ha utilizado ningun peaje.\n", c);
else
{ maxPeaje=0;
for (p=1; p<NumPeajes; p++)
if (viajes[c][p] > viajes[c][maxPeaje]) maxPeaje=p;
printf("El peaje que mas utiliza el cliente %d es el %d.\n", c, maxPeaje);
}
}
printf("\n");
system("PAUSE"); system("CLS");

//Calcular el ahorro de este mes por ser cliente habitual.


//Primero calculamos para cada cliente, cuánto debería haber pagado
for (c=0; c<NumClientes; c++)
{ deberiaHaberPagado[c]=0; // Inicializamos a 0.
for (p=0; p<NumPeajes; p++)
deberiaHaberPagado[c]=deberiaHaberPagado[c] + precioPeajes[p]*viajes[c][p];
}
//Restamos lo que deberían haber pagado con lo que han pagado.
for (c=0; c<NumClientes; c++)
ahorro[c]=deberiaHaberPagado[c]-debePagar[c];
//Escribir resultados.
printf("\nTABLA DE RESULTADOS:\n");
printf("Cliente\tViajes\tImporte\t Ahorro\n");
for (c=0; c<NumClientes; c++)
printf("%d\t%d\t%7.2f\t%7.2f\n", c, viajesTotales[c], debePagar[c], ahorro[c]);
printf("\n");
system("PAUSE");
}

AMPLIACIONES PROPUESTAS

1. Manejar el programa mediante un Menú principal con las siguientes opciones: "P-Leer precios de Peajes",
"C-Leer datos de Clientes", "M-Mostrar peajes más utilizados", "L-Listar resultados de clientes", "S-Salir". El
menú se podrá utilizar mediante las teclas de cursor-arriba, cursor-abajo y Enter, además de poder utilizar las
letras identificativas de cada opción (PCMLS).

2. Al terminar el programa, guardar en un fichero el array de precios de los peajes y la matriz de viajes
realizados. En la siguiente sesión del programa, si tal fichero existe, cargarlo en los arrays de memoria para
continuar leyendo nuevos datos de viajes realizados.

CÓDIGO C AMPLIADO
(Las ampliaciones están marcadas en color rojo)

#include <stdio.h>
#include <stdlib.h>
#include <graph.h> //necesario para la función _settextposition
#define cursor(a,b) _settextposition(a,b) //Macro para posicionar el cursor de texto en la pantalla
#define NumPeajes 15
#define NumClientes 10
//declaraciones prototipo de funciones auxiliares
char sino(char *msg);
char menu(void);
void marco(int fil1, int col1, int fil2, int col2);
void marcoDoble(int fil1, int col1, int fil2, int col2);
int incluido(char car, char *cars);

main()
{
int viajes[NumClientes][NumPeajes];
float precioPeajes[NumPeajes], debePagar[NumClientes];
int viajesTotales[NumClientes], pasoPeajes[NumPeajes];
float deberiaHaberPagado[NumClientes], ahorro[NumClientes];
int c, p, maxPeaje, sc;
FILE *pf; char opc=' ';
system("CLS");

//Inicializamos los arrays a 0


for (c=0; c<NumClientes; c++)
{ viajesTotales[c]=debePagar[c]=0;
for (p=0; p<NumPeajes; p++) viajes[c][p]=0;
}

if ((pf=fopen("autopis.dat","rb"))!=NULL)
{ fread(precioPeajes,sizeof(precioPeajes),1,pf);
fread(viajes,sizeof(viajes),1,pf); fread(viajesTotales,sizeof(viajesTotales),1,pf);
fclose(pf);
}

//BUCLE DEL MENU


while (opc!='S')
{ opc = menu();
if (opc=='P') //LEER PRECIOS DE PEAJES
{
printf("LEER PRECIOS DE PEAJES:\n\n");
for (p=0; p<NumPeajes; p++)
{ printf("Introduce el precio del peaje %d: ", p); scanf("%f", &precioPeajes[p]);
if (precioPeajes[p]<0 || precioPeajes[p]>100)
{ printf("Precio incorrecto.\a\a\n"); p--; }
}
}
else if (opc=='C') //LEER DATOS DE CLIENTES
{
printf("LEER DATOS DE CLIENTES:\n\n");
//Leemos y guardamos los viajes que ha hecho cada cliente
printf("Introduce el codigo del cliente y del peaje (para terminar teclea FIN):\n");
printf("Cliente, Peaje: "); sc=scanf ("%d %d", &c, &p);
while (sc==2)
{ if (c<0 || c>=NumClientes || p<0 || p>=NumPeajes)
printf("Datos incorrectos.\a\a\n");
else
{ viajes[c][p]++; viajesTotales[c]++;
if (viajesTotales[c]<=8) debePagar[c]=debePagar[c]+precioPeajes[p]*0.75;
else if (viajesTotales[c]<=20) debePagar[c]=debePagar[c]+precioPeajes[p]*0.45;
else debePagar[c]=debePagar[c]+precioPeajes[p]*0.25;
}
printf("Cliente, Peaje: "); sc=scanf ("%d %d", &c, &p);
}
}
else if (opc=='M') //MOSTRAR PEAJES MAS UTILIZADOS
{
printf("MOSTRAR PEAJES MAS UTILIZADOS:\n\n");
//Calculamos el número de veces que se ha pasado por cada peaje
for (p=0; p<NumPeajes; p++)
{ for (pasoPeajes[p]=c=0; c<NumClientes; c++)
pasoPeajes[p] += viajes[c][p];
}
//Calculamos el peaje por el que más han pasado los clientes
for (maxPeaje=0,p=1; p<NumPeajes; p++)
if (pasoPeajes[p]>pasoPeajes[maxPeaje]) maxPeaje=p;
printf("El peaje mas utilizado es el %d.\n\n", maxPeaje);

//Escribir el peaje que más utiliza cada uno de los clientes


for (c=0; c<NumClientes; c++)
{ if (viajesTotales[c]==0)
printf("El cliente %d no ha utilizado ningun peaje.\n", c);
else
{ for (maxPeaje=0,p=1; p<NumPeajes; p++)
if (viajes[c][p] > viajes[c][maxPeaje]) maxPeaje=p;
printf("El peaje que mas utiliza el cliente %d es el %d.\n", c, maxPeaje);
}
}
printf("\n"); system("PAUSE");
}
else if (opc=='L') //LISTAR RESULTADOS DE CLIENTES
{
printf("LISTAR RESULTADOS DE CLIENTES:\n\n");
//Calcular el ahorro de este mes por ser cliente habitual
//Primero calculamos para cada cliente, cuánto debería haber pagado
for (c=0; c<NumClientes; c++)
{ for (deberiaHaberPagado[c]=p=0; p<NumPeajes; p++)
deberiaHaberPagado[c] += precioPeajes[p]*viajes[c][p];
}
//Restamos lo que deberían haber pagado con lo que han pagado
for (c=0; c<NumClientes; c++)
ahorro[c]=deberiaHaberPagado[c]-debePagar[c];
//Escribir resultados en forma tabular
printf("TABLA DE RESULTADOS:\n");
printf("Cliente\tViajes\tImporte\t Ahorro\n");
for (c=0; c<NumClientes; c++)
printf("%d\t%d\t%7.2f\t%7.2f\n", c, viajesTotales[c], debePagar[c], ahorro[c]);
printf("\n"); system("PAUSE");
}
}

//grabamos fichero autopis.dat


if ((pf=fopen("autopis.dat","wb"))!=NULL)
{ fwrite(precioPeajes,sizeof(precioPeajes),1,pf);
fwrite(viajes,sizeof(viajes),1,pf); fwrite(viajesTotales,sizeof(viajesTotales),1,pf);
fclose(pf);
}
else
{ printf("ERROR al grabar datos en disco.\n"); system("PAUSE"); }
}

char sino(char *mensaje) //muestra pregunta en pantalla y acepta respuesta de tipo S/N
{ char resp;
fflush(stdin);
do
{ printf("%s (S/N): ", mensaje); resp=toupper(getchar()); fflush(stdin);
} while (resp!='N' && resp!='S');
return resp;
}

void marco(int fil1, int col1, int fil2, int col2) //Pinta un marco con linea simple
{ int i;
cursor(fil1,col1); printf("\xDA");
for (i=0; i<col2-col1-1; i++) printf("\xC4");
printf("\xBF");
for (i=fil1+1; i<fil2; i++)
{ cursor(i,col1); printf("\xB3"); cursor(i,col2); printf("\xB3"); }
cursor(fil2,col1); printf("\xC0");
for (i=0; i<col2-col1-1; i++) printf("\xC4");
printf("\xD9");
}

void marcoDoble(int fil1, int col1, int fil2, int col2) //Pinta un marco con linea doble
{ int i;
cursor(fil1,col1); printf("\xC9");
for (i=0; i<col2-col1-1; i++) printf("\xCD");
printf("\xBB");
for (i=fil1+1; i<fil2; i++)
{ cursor(i,col1); printf("\xBA"); cursor(i,col2); printf("\xBA"); }
cursor(fil2,col1); printf("\xC8");
for (i=0; i<col2-col1-1; i++) printf("\xCD");
printf("\xBC");
}

#define NumOpciones 5
char menu(void) //MENU CONTROLADO POR LAS TECLAS DE CURSOR
{
char menus[NumOpciones][40]={" P. Leer precios de Peajes. "," C. Leer datos de Clientes. "," M.
Mostrar peajes mas utilizados. "," L. Listar resultados de clientes. "," S. Salir del programa. "};
char letras[ ]="PCMLS", op;
int i, actual=0;
system("cls");
marco(1,1,24,80); marcoDoble(8,22,14,58);
do
{ for (i=0; i<NumOpciones; i++) { cursor(i+9,23); _outtext(menus[i]); }
_settextcolor(0); _setbkcolor(7); //activar video inverso
cursor(actual+9,23); _outtext(menus[actual]); //imprime texto con atributos de colores
_settextcolor(7); _setbkcolor(0); //desactivar video inverso
cursor(16,22); printf("Seleccione la operacion a realizar: "); op = toupper(getch());
if (op==0x0D) { op=letras[actual]; break; } //Tecla ENTER
else if (op==0x1B) { op='S'; break; } //Tecla ESC = Salir
else if (op==0) //Teclas especiales
{ op=getch();
if (op==0x50) //Cursor abajo
{ if (actual==NumOpciones-1) actual=0; else actual++; }
else if (op==0x48) //Cursor arriba
{ if (actual==0) actual=NumOpciones-1; else actual--; }
op=' ';
}
} while (!incluido(op,letras));
system("cls");
return (op);
}

int incluido(char car, char *cars) //devuelve cierto si el caracter car está incluido en la cadena cars
{ int i, n=strlen(cars);
for (i=0; i<n; i++)
if (car==cars[i]) return 1;
return 0;
}
APLICACIÓN DE BASE DE DATOS
Programa de base de datos para un fichero con número de registros ilimitado, registros compuestos por los
siguientes campos:
* Nombre (hasta 40 caracteres, formato "Apellidos, Nombre")
* DNI (8 dígitos y letra final calculada automáticamente)
* Fecha nacimiento (dd/mm/aaaa)
* Direccion (hasta 40 caracteres)
* Código Postal (5 dígitos)
* Poblacion (hasta 30 caracteres)
* Teléfono fijo (9 dígitos)
* Teléfono móvil (9 dígitos)
* Email (hasta 30 caracteres)
* Cuenta bancaria IBAN (XX99-9999-9999-99-9999999999, Pais-Banco-Sucursal-Control-Cuenta, con
verificación automática de los dígitos de Control)

El programa mostrará el registro actual en la parte superior de la pantalla (utilizando colores en pantalla) y
debajo el menú principal de mantenimiento de datos y navegación en el fichero, con las siguientes opciones:
- Añadir nuevos registros
- Modificar el registro actual
- Eliminar el registro actual
- Listar los registros en pantalla
- Ordenar los registros por nombre o por DNI
- Buscar registros por nombre o por DNI
- Ir al siguiente registro
- Ir al anterior registro
- Ir al primer registro del fichero
- Ir al último registro del fichero
- Saltar un número de registros adelante o atrás
- Ir a un registro por su número
- Ver u ocultar los registros eliminados
- Borrar definitivamente todos los registros eliminados
- Exportar fichero a formato Excel CSV
- Salir de la aplicación

La eliminación de registros se realiza de forma rápida mediante un campo adicional en el registro (campo
"Eliminado"), que es puesto a valor "S" cuando el registro es eliminado y eso ocultará el registro en el resto
del programa. Existe también una operación especial para eliminar definitivamente todos los registros
marcados como "eliminados", creando un nuevo fichero sin registros basura.

CÓDIGO C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graph.h>
#define cursor(a,b) _settextposition(a,b) //Macro para posicionar el cursor de texto

//declaración del tipo estructura de un registro


struct tipofecha
{ char dia, mes;
short anyo; };

struct tipocuenta
{ char pais[5];
short banco, sucursal;
char control;
double cuenta; };

struct registro
{ char nombre[41], dni[10], direccion[41], poblacion[31], email[31];
long codpostal, telefono, movil;
struct tipofecha fechanac;
struct tipocuenta cuentaiban;
char eliminado;
};
void verregistro(void); //Prototipos de funciones auxiliares
void nuevoreg(void);
void limpiarReg(void);
int introducir(int esModif);
int oknombre(char *cad);
int okdni(char *cad);
int okfecha(struct tipofecha fecha);
int oktelefono(long tfno);
int okmovil(long tfno);
int okcuenta(struct tipocuenta cta);
char digControl(short banco, short sucursal, double cuenta);
void modireg(void);
void elimreg(void);
void listareg(void);
void siguiente(void);
void anterior(void);
void primero(void);
void ultimo(void);
void saltar(void);
void iranumero(void);
void ordenar(int esnombre);
void buscarnom(void);
void buscardni(void);
void verelim(void);
void borraelim(void);
void aexcel(void);
char sino(char *cad);
void leecad(char *cad, int n);
char *conAcentos(char *cad);
int incluido(char c, char *cad);
void marco(int fil1, int col1, int fil2, int col2);
void marcoDoble(int fil1, int col1, int fil2, int col2);
void color(char lapiz, char fondo);
void caja(int fil1, int col1, int fil2, int col2, char fondo);

//Variables globales:
int numregs=0; // Nº total de registros (incluyendo eliminados)
int regnum=0; // Nº del registro activo actual
int tamreg=sizeof(struct registro); // Tamaño en bytes de un registro
struct registro dato; // Registro auxiliar en memoria
char *nomfile="datos.dat"; // Nombre del fichero en disco
char *msg="Pulse una tecla para continuar..."; // Mensaje habitual
FILE *pf; // Puntero controlador del fichero
int verelims=0; // Valor 1 = Permite ver los registros eliminados

main() //PROGRAMA PRINCIPAL


{
int salir=0; char menu=0;
system("cls"); //borrar pantalla
if ((pf=fopen(nomfile,"rb+"))==NULL) //Abrir fichero datos.dat
{ //El fichero no existe, lo creamos
if ((pf=fopen(nomfile, "wb+"))==NULL) { printf("Error de apertura de %s",nomfile); exit(1); }
}
else
{ //El fichero ya existe
fseek(pf,0,SEEK_END); //Apuntador L/E al final del fichero
numregs = (int)ftell(pf)/tamreg; //obtenemos el nº de registros del fichero
rewind(pf); //Nos posicionamos en el primer registro
}

while (!salir) //Bucle del menú principal


{
system("cls");
verregistro(); // Mostrar registro actual en la parte superior de la pantalla
color('r','N'); marco(11,1,21,80); // Mostar menú de opciones del programa
cursor(11,32); color('A','N'); _outtext(" MENU PRINCIPAL "); color('B','N');
cursor(12,10); printf(conAcentos("A. AÑADIR Nuevos Registros +. Ir al SIGUIENTE Registro"));
cursor(13,10); printf("M. MODIFICAR Registro Actual -. Ir al ANTERIOR Registro");
cursor(14,10); printf("E. ELIMINAR Registro Actual P. Ir al Registro PRIMERO");
cursor(15,10); printf("L. LISTAR Registros U. Ir al Registro ULTIMO");
cursor(16,10); printf("O. ORDENAR por NOMBRE T. SALTAR Registros");
cursor(17,10); printf("D. ORDENAR por DNI N. Ir a Registro NUMERO");
cursor(18,10); printf("B. BUSCAR por NOMBRE R. %s ELIMINADOS",(verelims?"Ocultar":"Ver"));
cursor(19,10); printf("V. BUSCAR por DNI Z. BORRAR Eliminados");
cursor(20,10); printf("S. Salir X. Exportar a EXCEL");

do //Leer opción elegida por el usuario


{ cursor(22,1); printf("Elija opcion: "); menu=toupper(getche()); if (menu==27) menu='S'; }
while (!incluido(menu,"AMEL+-TPUNODBVRZXS"));
system("cls"); cursor(1,1);

if ((numregs==0 || feof(pf)) && !incluido(menu,"ARS")) continue; //Control de fichero vacío

switch (menu) //Llamadas a las diversas funciones dependiendo del menu elegido
{ case 'A': nuevoreg(); break;
case 'M': modireg(); break;
case 'E': elimreg(); break;
case 'L': listareg(); break;
case '+': siguiente(); break;
case '-': anterior(); break;
case 'T': saltar(); break;
case 'P': primero(); break;
case 'U': ultimo(); break;
case 'N': iranumero(); break;
case 'O': ordenar(1); break;
case 'D': ordenar(0); break;
case 'B': buscarnom(); break;
case 'V': buscardni(); break;
case 'R': verelim(); break;
case 'Z': borraelim(); break;
case 'X': aexcel(); break;
case 'S': salir=1; break;
}
}
fclose(pf); //Cerrar fichero y terminar
}

void verregistro(void) // Mostrar registro actual 'dato' en la pantalla


{
char cad[80];
fread(&dato, tamreg, 1, pf); //Leer registro actual
while (!verelims && dato.eliminado=='S' && !feof(pf)) //Si eliminado, buscar siguiente registro
{ fread(&dato, tamreg, 1, pf); regnum++; }
if (feof(pf)) //Si no hay siguiente registro, buscar primer registro del fichero no eliminado
{ rewind(pf); regnum=0;
fread(&dato, tamreg, 1, pf);
while (!verelims && dato.eliminado=='S' && !feof(pf))
{ fread(&dato, tamreg, 1, pf); regnum++; }
}
cursor(1,1); color('v','N'); _outtext("BASE DE DATOS");
color('B','Z'); caja(2,1,10,80,'Z'); marcoDoble(2,1,10,80);
cursor(2,32); color('N','B'); _outtext(" REGISTRO ACTUAL "); color('B','Z');
if (feof(pf) || numregs==0) //Si no hay registros activos en el fichero, mostrar aviso
{ cursor(6,25); _outtext("No hay registros en el fichero"); regnum=0; }
else
{ fseek(pf,-tamreg,SEEK_CUR); //Volver apuntador L/E al comienzo del registro actual recien leido
//Mostrar en pantalla todos los campos del registro actual
if (dato.eliminado=='S') { cursor(1,50); printf("ELIMINADO"); }
cursor(1,60); printf("Registro: %d de %d", regnum+1, numregs);

cursor(3,3); color('B','Z'); _outtext("Nombre: ");


color('A','Z'); sprintf(cad, "%-40s", dato.nombre); _outtext(cad);
color('B','Z'); _outtext(" DNI: ");
color('A','Z'); sprintf(cad, "%-10s", dato.dni); _outtext(cad);

cursor(4,3); color('B','Z'); _outtext("Fecha Nacimiento: ");


color('A','Z'); sprintf(cad, "%2d/%02d/%4d", dato.fechanac.dia, dato.fechanac.mes, dato.fechanac.anyo);
_outtext(cad);

cursor(5,3); color('B','Z'); sprintf(cad, conAcentos("Dirección: ")); _outtext(cad);


color('A','Z'); sprintf(cad, "%-40s", dato.direccion); _outtext(cad);

cursor(6,3); color('B','Z'); sprintf(cad, conAcentos("Código Postal: ")); _outtext(cad);


color('A','Z'); sprintf(cad, "%05ld", dato.codpostal); _outtext(cad);
color('B','Z'); sprintf(cad, conAcentos(" Población: ")); _outtext(cad);
color('A','Z'); sprintf(cad, "%-30s", dato.poblacion); _outtext(cad);

cursor(7,3); color('B','Z'); sprintf(cad, conAcentos("Teléfono fijo: ")); _outtext(cad);


color('A','Z'); sprintf(cad, "%9ld", dato.telefono); _outtext(cad);
color('B','Z'); sprintf(cad, conAcentos(" Teléfono móvil: ")); _outtext(cad);
color('A','Z'); sprintf(cad, "%9ld", dato.movil); _outtext(cad);

cursor(8,3); color('B','Z'); _outtext("Email: ");


color('A','Z'); sprintf(cad, "%-30s", dato.email); _outtext(cad);

cursor(9,3); color('B','Z'); _outtext("Cuenta bancaria IBAN: ");


if (dato.cuentaiban.banco!=0)
{ color('A','Z'); sprintf(cad, "%4s-%04d-%04d-%02d-%10.0lf", dato.cuentaiban.pais, dato.cuentaiban.banco,
dato.cuentaiban.sucursal, dato.cuentaiban.control, dato.cuentaiban.cuenta); _outtext(cad); }
}
cursor(11,1); color('B','N');
}

void nuevoreg(void) // Añadir nuevos registros


{
printf(conAcentos("AÑADIR NUEVOS REGISTROS:\n"));
fseek(pf,0,SEEK_END); //Apuntador L/E al final del fichero
do //Bucle de introducción de sucesivos registros
{ limpiarReg(); // Poner a cero todos los campos del registro 'dato'
printf("\nRegistro Num. %d:\n", numregs+1);
if (introducir(0))
{ fwrite(&dato, tamreg, 1, pf); numregs++; } //grabar registro e incrementar numregs
else break; //salimos del bucle
} while (!ferror(pf));
if (ferror(pf)) { printf("Error en fichero %s\n", nomfile); clearerr(pf); }
rewind(pf); regnum=0; //Terminamos moviendo el apuntador L/E al primer registro del fichero
}

void limpiarReg(void) // Poner a cero todos los campos del registro 'dato'
{
int i;
for (i=0; i<41; i++) { dato.nombre[i]=' '; dato.direccion[i]=' '; } //Rellenamos con blancos
for (i=0; i<31; i++) { dato.poblacion[i]=' '; dato.email[i]=' '; }
for (i=0; i<10; i++) dato.dni[i]=' ';
dato.eliminado=' ';
dato.codpostal=dato.telefono=dato.movil=0; //Rellenamos con ceros
dato.fechanac.dia=dato.fechanac.mes=dato.fechanac.anyo=0;
dato.cuentaiban.banco=dato.cuentaiban.sucursal=dato.cuentaiban.control=dato.cuentaiban.cuenta=0;
for (i=0; i<5; i++) dato.cuentaiban.pais[i]=' ';
}

// Introducción de datos por teclado en el registro 'dato', esModif=1 si viene desde 'Modificar Registro'
int introducir(int esModif)
{
char *txt = esModif ? " (Vacio=Sin Modificar)" : ""; // Mensaje de texto auxiliar
char cad[50];
printf("\nIntroduzca los%s datos del registro:\n", esModif ? " nuevos" : "");

do //Bucle de lectura del campo Nombre


{ printf("Apellidos, Nombre (Vacio=%s): ", esModif ? "Sin Modificar" : "Terminar");
leecad(dato.nombre,41); strupr(dato.nombre);
} while (!oknombre(dato.nombre));
if (!esModif && dato.nombre[0]==0) return 0; //retorna 0 para terminar si dejamos el Nombre vacio

do //Bucle de lectura del campo DNI


{ printf("DNI%s: ", txt); leecad(dato.dni,10); strupr(dato.dni);
} while (!okdni(dato.dni));

do //Bucle de lectura del campo Fecha Nacimiento


{ printf("Fecha de Nacimiento (dd/mm/aaaa)%s: ", txt); leecad(cad,11);
if (cad[0]==0) dato.fechanac.dia = dato.fechanac.mes = dato.fechanac.anyo = 0;
else { dato.fechanac.dia = atoi(cad); dato.fechanac.mes = atoi(cad+3); dato.fechanac.anyo = atoi(cad+6); }
} while (!okfecha(dato.fechanac));

printf("%s%s: ", conAcentos("Dirección"), txt); leecad(dato.direccion,41); strupr(dato.direccion);

do //Bucle de lectura del campo Codigo Postal


{ printf("%s%s: ", conAcentos("Código Postal:"), txt); leecad(cad,6);
if (cad[0]==0) dato.codpostal=0; else dato.codpostal=atol(cad);
} while (dato.codpostal<0 || dato.codpostal>99999);

printf("%s%s: ", conAcentos("Población"), txt); leecad(dato.poblacion,31); strupr(dato.poblacion);

do //Bucle de lectura del campo Telefono


{ printf("%s%s: ", conAcentos("Teléfono fijo:"), txt); leecad(cad,10);
if (cad[0]==0) dato.telefono=0; else dato.telefono=atol(cad);
} while (!oktelefono(dato.telefono));

do //Bucle de lectura del campo Movil


{ printf("%s%s: ", conAcentos("Teléfono móvil"), txt); leecad(cad,10);
if (cad[0]==0) dato.movil=0; else dato.movil=atol(cad);
} while (!okmovil(dato.movil));

do //Bucle de lectura del campo Email


{ printf("Email%s: ", txt); leecad(dato.email,31); strlwr(dato.email); }
while (!incluido('@', dato.email) && dato.email[0]!=0);

do //Bucle de lectura del campo Cuenta Bancaria


{ printf("Cuenta IBAN (XX99-9999-9999-99-9999999999)%s:\n", txt); leecad(cad,30);
if (cad[0]==0)
{ strcpy(dato.cuentaiban.pais,"");
dato.cuentaiban.banco=dato.cuentaiban.sucursal=dato.cuentaiban.control=dato.cuentaiban.cuenta=0;
}
else
{ cad[4]=0; strcpy(dato.cuentaiban.pais,cad); strupr(dato.cuentaiban.pais);
dato.cuentaiban.banco=atoi(cad+5); dato.cuentaiban.sucursal=atoi(cad+10);
dato.cuentaiban.control=atoi(cad+15); dato.cuentaiban.cuenta=atof(cad+18);
}
} while (!okcuenta(dato.cuentaiban));
return 1; //retorna 1 para continuar con más registros
}

int oknombre(char *cad) // Verifica el formato correcto del nombre (Apellidos, Nombre)
{
int count=0;
if (*cad==0) return 1; //Si el campo se deja vacío
while (*cad!=0)
if (*cad++==',') count++; //Contar el número de caracteres 'coma'
if (count!=1) { printf("Error, el formato debe ser: Apellidos, Nombre\n"); return 0; }
return 1; //Retorna 1 si OK, retorna 0 si error
}

int okdni(char *cad) // Verifica el formato correcto del DNI (8 dígitos y una letra), calcula la letra correcta
{
int i=0; //Aquí se implementa el algoritmo de cálculo de la letra final de DNI
char letras[]=" RWAGMYFPDXBNJZSQVHLCKET", letra;
if (cad[0]==0) return 1;
while (cad[i]>='0' && cad[i]<='9') i++;
if (i!=8) { printf(conAcentos("Error: deben ser 8 dígitos\n")); return 0; }
i=atol(cad)%23; if (i==0) i=23;
letra=letras[i];
if (cad[8]!=0 && cad[8]!=letra) { printf("Error en la letra final.\n"); return 0; }
if (cad[8]==0) { printf("Anotamos la letra final %c\n", letra); cad[8]=letra; cad[9]=0; }
return 1; //Retorna 1 si OK, retorna 0 si error
}

int okfecha(struct tipofecha fecha) // Verifica el formato correcto de la fecha


{
int numdias, ret;
if (fecha.dia==0 && fecha.mes==0 && fecha.anyo==0) ret=1;
else if (fecha.anyo<1900 || fecha.anyo>3000) ret=0;
else if (fecha.mes<1 || fecha.mes>12) ret=0;
else
{ switch (fecha.mes)
{ case 1: case 3: case 5: case 7: case 8: case 10: case 12: numdias=31; break;
case 4: case 6: case 9: case 11: numdias=30; break;
case 2: if (fecha.anyo%4==0 && fecha.anyo%100!=0 || fecha.anyo%400==0) //Año bisiesto
numdias = 29;
else numdias = 28;
}
if (fecha.dia<1 || fecha.dia>numdias) ret=0;
}
if (ret==0) printf("Error: Fecha incorrecta.\n");
return ret;
}

int oktelefono(long tfno) // Verifica el valor correcto del número de Telefono


{
if (tfno<900000000 && tfno!=0) { printf(conAcentos("No es un número de teléfono fijo.\n")); return 0; }
return 1;
}

int okmovil(long tfno) // Verifica el valor correcto del número de Movil


{
if (tfno>=900000000 && tfno!=0) { printf(conAcentos("No es un número de teléfono móvil.\n")); return 0; }
return 1;
}

int okcuenta(struct tipocuenta cta) // Verifica el formato correcto de la cuenta bancaria


{
if (cta.pais[0]!=0&&(atoi(cta.pais)>0||atoi(cta.pais+2)==0)) { printf(conAcentos("Código de País incorrecto\n"));
return 0; }
if (cta.banco<0 || cta.banco>9999) { printf(conAcentos("Código de Banco incorrecto\n")); return 0; }
if (cta.sucursal<0 || cta.sucursal>9999) { printf(conAcentos("Código de Sucursal incorrecto\n")); return 0; }
if (cta.control<0 || cta.control>99) { printf(conAcentos("Dígitos de Control incorrectos\n")); return 0; }
if (digControl(cta.banco, cta.sucursal, cta.cuenta) != cta.control && cta.control!=0)
{ printf("Datos incorrectos\n"); return 0; }
if (cta.cuenta<0 || cta.cuenta>9999999999.0) { printf(conAcentos("Número de Cuenta incorrecto\n")); return 0; }
return 1;
}

char digControl(short banco, short sucursal, double cuenta) //Calcula los dígitos de control de la cuenta
{ //Aquí se implementa el algoritmo de cálculo de los dígitos de control
int tot, i, n;
char pesos[]="6379058421", cad[11], resul;
sprintf(cad, "%04d%04d", banco, sucursal); n=strlen(cad);
for (tot=i=0; i<n; i++) tot += (cad[n-i-1]-'0')*(pesos[i]=='0'?10:pesos[i]-'0');
tot = 11-tot%11;
if (tot==10) tot=1;
else if (tot==11) tot=0;
resul = tot*10;
sprintf(cad, "%10.0f", cuenta); n=strlen(cad);
for (tot=i=0; i<n; i++) tot += (cad[n-i-1]-'0')*( pesos[i]=='0'?10:pesos[i]-'0');
tot = 11-tot%11;
if (tot==10) tot=1;
else if (tot==11) tot=0;
resul += tot;
return resul;
}

void modireg(void) // Modificar registro actual


{
struct registro aux = dato; // Copia de salvaguarda del registro actual original 'dato' en 'aux'
verregistro(); // Mostrar registro actual 'dato' en la pantalla
limpiarReg(); // Vaciar registro actual 'dato'
printf("MODIFICAR REGISTRO ACTUAL:\n");
introducir(1); // Introducir nuevos valores del registro actual 'dato'
if (aux.eliminado=='S')
{ dato.eliminado=( sino("Registro Eliminado")=='N'?' ':'S'); }
// Copiar los campos no modificados desde el registro 'aux' en el registro 'dato'
if (dato.nombre[0]==0) strcpy(dato.nombre, aux.nombre);
if (dato.dni[0]==0) strcpy(dato.dni, aux.dni);
if (dato.direccion[0]==0) strcpy(dato.direccion, aux.direccion);
if (dato.poblacion[0]==0) strcpy(dato.poblacion, aux.poblacion);
if (dato.email[0]==0) strcpy(dato.email, aux.email);
if (dato.codpostal==0) dato.codpostal=aux.codpostal;
if (dato.telefono==0) dato.telefono=aux.telefono;
if (dato.movil==0) dato.movil=aux.movil;
if (dato.fechanac.dia==0) dato.fechanac.dia=aux.fechanac.dia;
if (dato.fechanac.mes==0) dato.fechanac.mes=aux.fechanac.mes;
if (dato.fechanac.anyo==0) dato.fechanac.anyo=aux.fechanac.anyo;
if (dato.cuentaiban.pais[0]==0) strcpy(dato.cuentaiban.pais, aux.cuentaiban.pais);
if (dato.cuentaiban.banco==0) dato.cuentaiban.banco=aux.cuentaiban.banco;
if (dato.cuentaiban.sucursal==0) dato.cuentaiban.sucursal=aux.cuentaiban.sucursal;
if (dato.cuentaiban.control==0) dato.cuentaiban.control=aux.cuentaiban.control;
if (dato.cuentaiban.cuenta==0) dato.cuentaiban.cuenta=aux.cuentaiban.cuenta;
fwrite(&dato, tamreg, 1, pf); //grabar registro 'dato' en el fichero
if (ferror(pf)) { printf("Error en fichero %s\n", nomfile); clearerr(pf); }
fseek(pf,-tamreg,SEEK_CUR); //volver apuntador L/E a su posición de inicio
}

void elimreg(void) // Eliminar registro actual


{
verregistro();
printf("ELIMINAR REGISTRO ACTUAL:\n");
if (dato.eliminado=='S') return; //Si ya está eliminado
if (sino("Eliminar registro. ¿SEGURO?")=='N') return; //Pedir confirmación
dato.eliminado='S'; fwrite(&dato, tamreg, 1, pf); //Marcamos el registro como Eliminado
regnum++; if (regnum==numregs) regnum=0; //Pasamos al siguiente registro del fichero
fseek(pf,regnum*tamreg,SEEK_SET); //Apuntador L/E al registro Nº regnum
}

void listareg(void) // Listar todos los registros en pantalla


{
int nreg=0,lin=0,nuevapag=1;
rewind(pf); //Desde el primer registro del fichero
fread(&dato, tamreg, 1, pf);
while (!feof(pf) && !ferror(pf)) //Bucle de lectura secuencial de registros hasta el último
{
if (nuevapag)
{ system("cls"); nuevapag=0;
printf("LISTAR REGISTROS:\n");
printf(conAcentos("Reg. Nombre DNI FechaNacim Teléfono Móvil \n"));
printf("---- --------------------------------- --------- ---------- --------- ---------");
}
if (verelims || dato.eliminado!='S') //Si no es un registro eliminado
{ printf("\n%4d %-33s %-9s %02d/%02d/%4d %9ld ", nreg+1, dato.nombre, dato.dni, dato.fechanac.dia,
dato.fechanac.mes, dato.fechanac.anyo, dato.telefono);
if (verelims && dato.eliminado=='S') printf("ELIMINADO");
else printf("%9ld", dato.movil);
}
nreg++; lin++;
if (lin==23) { lin=0; nuevapag=1; printf("\n\n%s", msg); if (getch()==27) break; }
fread(&dato, tamreg, 1, pf);
}
printf("\n\n");
if (ferror(pf)) { printf("Error de lectura en %s\n",nomfile); clearerr(pf); }
printf("%s",msg); getch();
fseek(pf,regnum*tamreg,SEEK_SET); //Apuntador L/E al registro Nº regnum
}

void ordenar(int esnombre) // Ordenar el fichero por Nombre o DNI (por Nombre si esnombre==1)
{
int x,j,cambio; char cad[60];
struct registro aux, aux2;
verregistro();
printf("ORDENAR POR %s:\n", esnombre?"NOMBRE":"DNI");
printf("Ordenando...\n");
for (x=numregs-1; x>0; x--) //metodo de ordenación de "la burbuja"
{
cambio=0; //indicador de "intercambio realizado"
for (j=0; j<x; j++) //j indica el nº de registro actual del fichero
{
fseek(pf,j*tamreg,SEEK_SET); //colocar L/E del fichero al principio del registro j
fread(&aux,tamreg,1,pf); //leemos en aux el registro j, y en aux2 el j+1
fread(&aux2,tamreg,1,pf);
if ((esnombre ? strcmp(aux.nombre,aux2.nombre) : strcmp(aux.dni,aux2.dni)) > 0)
{ //Si están en orden incorrecto
cambio=1;
fseek(pf,j*tamreg,SEEK_SET); //volver a colocar L/E del fichero en el registro j
fwrite(&aux2,tamreg,1,pf); //grabamos los dos registros intercambiados (aux2+aux)
fwrite(&aux,tamreg,1,pf);
}
}
if (!cambio) break; //si no ha habido ningún cambio, terminamos
}
rewind(pf); regnum=0;
printf("%s. %s", conAcentos("Ordenación realizada"), msg); getch();
}

void buscarnom(void) // Buscar un registro por las primeras letras de su Nombre


{
int nreg=0,n,lin=0,encontrado=0;
char buscado[40],aux[40];
verregistro();
printf("BUSCAR POR NOMBRE:\n");
printf("Nombre a buscar: "); leecad(buscado,40); strupr(buscado);
if (buscado[0]==0) return;
n = strlen(buscado);
rewind(pf); //Buscamos desde el primer registro del fichero
fread(&dato, tamreg, 1, pf);
while (!feof(pf) && !ferror(pf)) //Bucle de lectura secuencial de registros hasta el último
{ //Mostraremos en pantalla todos los registros que cumplan la condición del nombre
strcpy(aux,dato.nombre); aux[n]=0;
if (strcmp(aux,buscado)==0 && (verelims?1:dato.eliminado!='S'))
{ printf("Reg.Num.: %d\tNombre: %s\tDNI: %s", nreg+1, dato.nombre, dato.dni);
printf("\t%s\n", dato.eliminado=='S'?" ELIMINADO":"");
encontrado=1;
}
nreg++; lin++;
if (lin==23) { lin=0; printf("\n\n%s", msg); if (getch()==27) break; }
fread(&dato, tamreg, 1, pf);
}
printf("\n");
if (ferror(pf)) { printf("Error de lectura en %s\n",nomfile); clearerr(pf); }
if (!encontrado) { printf("Registro no encontrado. %s\n", msg); getch(); }
else
{ printf(conAcentos("Indique número de registro deseado (vacío=Salir): ")); leecad(aux,40); nreg=atoi(aux);
if (aux[0]!=0 && nreg>0 && nreg<=numregs) regnum=nreg-1;
}
fseek(pf,regnum*tamreg,SEEK_SET);
}

void buscardni(void) // Buscar un registro por su DNI


{
int nreg=0, encontrado=0; char buscado[10];
verregistro();
printf("BUSCAR POR DNI:\n");
printf("DNI a buscar: "); leecad(buscado,10); strupr(buscado);
if (buscado[0]==0) return;
rewind(pf);
fread(&dato, tamreg, 1, pf);
while (!feof(pf) && !ferror(pf))
{
if (strcmp(dato.dni,buscado)==0 && (verelims?1:dato.eliminado!='S'))
{ regnum=nreg; encontrado=1; break; }
fread(&dato, tamreg, 1, pf); nreg++;
}
printf("\n");
if (ferror(pf)) { printf("Error de lectura en %s\n",nomfile); clearerr(pf); printf("%s\n",msg); getch(); }
if (!encontrado) { printf("Registro no encontrado.\n"); printf("%s\n",msg); getch(); }
fseek(pf,regnum*tamreg,SEEK_SET);
}

void siguiente(void) // Pasar al siguiente registro


{
int nreg=regnum;
do
{ nreg++; fseek(pf,nreg*tamreg,SEEK_SET); //Buscar primer registro siguiente no eliminado
fread(&dato, tamreg, 1, pf);
} while (nreg<numregs && !verelims && dato.eliminado=='S');
if (nreg<numregs) regnum=nreg;
fseek(pf,regnum*tamreg,SEEK_SET);
}

void anterior(void) // Pasar al registro anterior


{
int nreg=regnum;
do
{ nreg--; fseek(pf,nreg*tamreg,SEEK_SET); //Buscar primer registro anterior no eliminado
fread(&dato, tamreg, 1, pf);
} while (nreg>=0 && !verelims && dato.eliminado=='S');
if (nreg>=0) regnum=nreg;
fseek(pf,regnum*tamreg,SEEK_SET);
}

void primero(void) // Ir al primer registro del fichero


{
rewind(pf); regnum=0;
}
void ultimo(void) // Ir al último registro del fichero
{
int nreg=numregs;
do
{ nreg--; fseek(pf,nreg*tamreg,SEEK_SET);
fread(&dato, tamreg, 1, pf);
} while (!verelims && dato.eliminado=='S' && nreg>=0);
if (nreg>=0) regnum=nreg;
fseek(pf,regnum*tamreg,SEEK_SET);
}

void saltar(void) // Saltar un Nº de registros (adelante a atrás)


{
int num=0;
verregistro();
printf("SALTAR REGISTROS:\n");
printf("\nNum. registros a saltar (positivo o negativo)(0=Salir): ");
scanf("%d", &num); fflush(stdin);
regnum+=num;
if (regnum >= numregs) ultimo(); //Iremos al último registro del fichero
else if (regnum < 0) primero(); //Iremos al primer registro del fichero
else fseek(pf,regnum*tamreg,SEEK_SET);
}

void iranumero(void) // Ir a un Nº de registro


{
int num=0;
verregistro();
printf("IR A REGISTRO NUMERO (0=Salir):\n");
do
{ printf("\nIr al Num. Registro (1-%d): ",numregs); scanf("%d", &num); fflush(stdin); }
while (num<0 || num>numregs);
if (num==0) return;
num--; fseek(pf,num*tamreg,SEEK_SET); fread(&dato, tamreg, 1, pf);
if (!verelims && dato.eliminado=='S') { printf("Registro eliminado. %s",msg); getch(); }
else regnum=num;
fseek(pf,regnum*tamreg,SEEK_SET);
}

void verelim(void) // Cambia el modo de visualizar los registros eliminados (visibles o no visibles)
{
verelims = !verelims;
}

void borraelim(void) // Borra definitivamente del fichero los registros eliminados


{
FILE *pf2; //Crearemos un 2º fichero 'datos2.dat' copiando de 'datos.dat' sólo los registros no eliminados
int nreg=0, hayerror=0;
verregistro();
printf("BORRAR ELIMINADOS:\n");
if (sino("\nBorrar definitivamente todos los registros eliminados. ¿SEGURO?")=='N') return;
if ((pf2 = fopen("datos2.dat","wb+"))==NULL)
{ printf("Error de apertura de fichero auxiliar\n"); return; }
rewind(pf);
fread(&dato, tamreg, 1, pf);
while (!feof(pf) && !ferror(pf) && !ferror(pf2))
{
if (dato.eliminado!='S') { fwrite(&dato, tamreg, 1, pf2); nreg++; }
fread(&dato, tamreg, 1, pf);
}
if (ferror(pf)) { printf("Error al leer fichero %s\n",nomfile); hayerror=1; }
if (ferror(pf2)) { printf("Error en fichero auxiliar\n"); hayerror=1; }
fclose(pf2);
if (!hayerror)
{ fclose(pf); //Eliminaremos el fichero 'datos.dat' y renombraremos a 'datos2.dat' como 'datos.dat'
if (remove(nomfile)==0) rename("datos2.dat", nomfile);
}
if ((pf=fopen(nomfile,"r+b"))==NULL)
if ((pf=fopen(nomfile, "w+b"))==NULL) { printf("Error de apertura de %s",nomfile); exit(1); }
numregs=nreg; regnum=0;
printf("\nBorrado realizado. %s",msg); getch();
fseek(pf,regnum*tamreg,SEEK_SET); //Apuntador L/E al registro Nº regnum
}

void aexcel(void) // Exportar a fichero Excel CSV (campos de texto separados por ';')
{
FILE *pf2;
int nreg=0;
verregistro();
printf("EXPORTAR A EXCEL:\n");
if ((pf2=fopen("datos.csv","w"))==NULL) { printf("Error de apertura en DATOS.CSV\n"); return; }
rewind(pf);
fprintf(pf2,"Reg.;Nombre;DNI;FechaNacim;Dirección;Cod.Postal;Población;Teléfono;Móvil;Email;Cuenta Bancaria\n");
fread(&dato, tamreg, 1, pf);
while (!feof(pf) && !ferror(pf) && !ferror(pf2)) //Bucle de lectura secuencial del fichero
{
if (verelims || dato.eliminado!='S')
{ fprintf(pf2,"\n%d;%s;%s;%d/%d/%d;%s;%5ld;%s;%ld;%ld;%s;%s-%04d-%04d-%02d-%10.0lf", nreg+1, dato.nombre,
dato.dni, dato.fechanac.dia, dato.fechanac.mes, dato.fechanac.anyo, dato.direccion, dato.codpostal, dato.poblacion,
dato.telefono, dato.movil, dato.email, dato.cuentaiban.pais, dato.cuentaiban.banco, dato.cuentaiban.sucursal,
dato.cuentaiban.control, dato.cuentaiban.cuenta);
if (dato.eliminado=='S') fprintf(pf2,";ELIMINADO");
}
nreg++; fread(&dato, tamreg, 1, pf);
}
if (ferror(pf)) { printf("Error de lectura en %s\n",nomfile); clearerr(pf); }
if (ferror(pf2)) printf("Error de escritura en datos.csv\n");
printf("Fichero Excel DATOS.CSV generado. %s\n",msg); getch();
fclose(pf2);
fseek(pf,regnum*tamreg,SEEK_SET); //Apuntador L/E al registro Nº regnum
}

char sino(char *msg) //Acepta respuestas de tipo S/N, convertidas a mayusculas


{
char resp, cad[80];
printf("%s (S/N): ", conAcentos(msg)); //imprimir mensaje (con posibles acentos)
do resp = toupper(getch()); //leer tecla y convertir a mayúscula
while (resp!='S' && resp!='N');
printf("%c", resp); //mostrar respuesta en pantalla
return resp; //retornar la tecla pulsada
}

void leecad(char *cad, int n) //Lee una cadena desde el teclado con número máximo de caracteres 'n' a leer
{
fgets(cad,n,stdin); fflush(stdin); n=strlen(cad)-1;
if (cad[n]=='\n') cad[n]=0;
}

char *conAcentos(char *cad) //Devuelve la cadena cad con los acentos y Ññ corregidos para una correcta impresión
{
int i=strlen(cad);
while (--i>=0)
{ switch (cad[i])
{ case 'á': cad[i]='\xA0'; break;
case 'é': cad[i]='\x82'; break;
case 'í': cad[i]='\xA1'; break;
case 'ó': cad[i]='\xA2'; break;
case 'ú': cad[i]='\xA3'; break;
case 'ñ': cad[i]='\xA4'; break;
case 'Ñ': cad[i]='\xA5'; break;
case 'ü': cad[i]='\x81'; break;
case '¿': cad[i]='\xA8'; break;
}
}
return cad;
}

int incluido(char c, char *cad) // Verifica si el caracter c está incluido en la cadena cad
{
while (*cad!=c && *cad!=0) cad++;
return *cad==c;
}

void marco(int fil1, int col1, int fil2, int col2) //Pinta un marco con linea simple
{ int i;
cursor(fil1,col1); _outtext("\xDA");
for (i=0; i<col2-col1-1; i++) _outtext("\xC4");
_outtext("\xBF");
for (i=fil1+1; i<fil2; i++)
{ cursor(i,col1); _outtext("\xB3"); cursor(i,col2); _outtext("\xB3"); }
cursor(fil2,col1); _outtext("\xC0");
for (i=0; i<col2-col1-1; i++) _outtext("\xC4");
_outtext("\xD9");
}

void marcoDoble(int fil1, int col1, int fil2, int col2) //Pinta un marco con linea doble
{ int i;
cursor(fil1,col1); _outtext("\xC9");
for (i=0; i<col2-col1-1; i++) _outtext("\xCD");
_outtext("\xBB");
for (i=fil1+1; i<fil2; i++)
{ cursor(i,col1); _outtext("\xBA"); cursor(i,col2); _outtext("\xBA"); }
cursor(fil2,col1); _outtext("\xC8");
for (i=0; i<col2-col1-1; i++) _outtext("\xCD");
_outtext("\xBC");
}

void color(char lapiz, char fondo)


{ /* Ajusta el color del lapiz y del fondo con 16 posibles colores de lapiz y 8 colores de fondo
Ejemplo de uso: color('B','N');
Colores de fondo: 'N'=Negro, 'Z'=Azul, 'V'=Verde, 'C'=Cian, 'R'=Rojo, 'G'=Magenta, 'M'=Marron, 'B'=Blanco
Colores de lapiz: Los mismos que los del fondo más estas 8 posibilidades adicionales:
'n'=Gris, 'z'=Azul Claro, 'v'=Verde Claro, 'c'=Cian Claro, 'r'=Rojo Claro, 'g'=Magenta Claro, 'A'=Amarillo,
'b'=Blanco Intenso
*/
int l,f;
char colores[]="NZVCRGMBnzvcrgAb";
for (l=0; l<16; l++)
if (lapiz==colores[l]) break;
for (f=0; f<8; f++)
if (fondo==colores[f]) break;
if (l<16) _settextcolor((short)l);
if (f<8) _setbkcolor((long)f);
}

void caja(int fil1, int col1, int fil2, int col2, char fondo)
{ /* Pinta una caja rellena desde la esquina superior izquierda fil1,col1
hasta la esquina inferior derecha fil2,col2, con el color de fondo especificado
Ejemplo de uso: caja(1,1,10,20,'Z');
*/
int i,j,f;
char colores[]="NZVCRGMB";
for (f=0; f<8; f++)
if (fondo==colores[f]) break;
if (f<8) _setbkcolor((long)f);
for (i=0; i<fil2-fil1+1; i++)
{ cursor(fil1+i,col1); for (j=0; j<col2-col1+1; j++) _outtext(" "); }
}

También podría gustarte