En C, la expresión fseek(unFlujo, n, SEEK_SET) posiciona el cursor

Anuncio
UTN – FRBA – Algoritmos y Estructura de Datos – Examen Final – 17/07/2015
Elecciones 2015
Temas evaluados: Resolución de problemas, abstracción, modularización, archivos y flujos.
Contexto
Usted es parte de un equipo que brinda apoyo informático a la Dirección Nacional Electoral y debe informar sobre los resultados de las
Primarias Abiertas Simultaneas Obligatorias (PASO). El Centro de Cómputos que usted lidera recibe vía internet la información de las
mesas escrutadas de todo el país. Su equipo debe procesar la información e informar los resultados parciales acumulados.
Problema
Dado un archivo con los datos de una mesa, se deben actualizar los resultados generales e informar el avance del proceso.
El nombre del archivo contiene el distrito y el números de mesa. El nombre es una cadena de 10 dígitos, los primeros 4 representan el
código de distrito, los siguientes 5 el número de mesa, y el décimo es un número verificador.
El archivo de mesa contiene la cantidad de votos de cada fórmula presidencial, agrupadas por partido. Los partidos están ordenados
alfabéticamente, al igual que las fórmulas. Cada registro tiene la forma (partido, fórmula, votos). Los primeros tres registros son
especiales, tienen partido y fórmula nulos, el primero tiene los votos en blanco, el segundo los impugnados, y la cantidad de personas
que no se acercaron a votar en el tercero.
El archivo de resultados tiene la misma forma y cantidad de registros, pero en vez de representar cantidades de una mesa, representa
el acumulado del resultado general, originalmente en cero.
Recursos disponibles

Las variables externas a toda función (“globales”) losResultadosGenerales, laCantidadDeMesasEscrutadasHastaAhora, y
laCantidadVotosEscrutadosHastaAhora, la primera es un flujo (archivo abierto) para lectura y escritura, las últimas son
enteros.

La constante externa a toda función (“global”) laCantidadDeMesasTotal.

La función GetMesa que dado un string con el nombre de archivo de mesa retorna el número de mesa.

La función EsMesaProcesada que dado un número de mesa retorna verdadero si la mesa ya fue procesada.
Recuerde que

Puede usar funciones de biblioteca para resolver búsquedas.

La expresión sizeof(Tipo) tiene como valor la cantidad de bytes que ocupa variables de Tipo.

En C, la expresión fseek(unFlujo, n, SEEK_SET) posiciona el cursor de unFlujo a n bytes del inicio.
En C++, la expresión unFlujo.seekg(n) posiciona el cursor de lectura, y unFlujo.seekp(n), el de escritura.
Se pide
1. Codificar las declaraciones necesarias para el registro que se usa en ambos archivos.
2.
Diagramar o codificar la función ProcesarMesa que dado el nombre de un archivo de mesa, procese ese archivo, actualice los
resultados generales e informe el avance. La función debe verificar que la mesa no haya sido procesada previamente. Para la
actualización, recuerde leer, posicionarse, y escribir.
3.
Diagramar o codificar la función InformarAvance dada la cantidad de votos de una mesa, actualiza la cantidad de mesas
escrutadas, y envía a la salida estándar el porcentaje de mesas escrutadas y el porcentaje votos obtenidos por cada formula a ese
momento.
UTN – FRBA – Algoritmos y Estructura de Datos – Examen Final – 31/07/2015
Recursos disponibles

Las variables externas a toda función (“globales”)
o
losResultadosGenerales,  archivo abierto
o
laCantidadDeMesasEscrutadasHastaAhora,  int
o
laCantidadVotosEscrutadosHastaAhora,  int

La constante externa a toda función (“global”) laCantidadDeMesasTotal.

La función GetMesa que dado un string con el nombre de archivo de mesa retorna el número de mesa.

La función EsMesaProcesada que dado un número de mesa retorna verdadero si la mesa ya fue procesada.
Recuerde que

Puede usar funciones de biblioteca para resolver búsquedas.

La expresión sizeof(Tipo) tiene como valor la cantidad de bytes que ocupa variables de Tipo.

En C, la expresión fseek(unFlujo, n, SEEK_SET) posiciona el cursor de unFlujo a n bytes del inicio.
En C++, la expresión unFlujo.seekg(n) posiciona el cursor de lectura, y unFlujo.seekp(n), el de escritura.
Se pide
1. Codificar las declaraciones necesarias para el registro que se usa en ambos archivos.
En C
En C++
Implementando cadenas con vector de char
Utilizando array de caracteres para cadena de tamaño fijo
struct VotosDeFormula {
char elPartido[50 + 1];
char laFormula[50 + 1];
unsigned losVotos;
};
struct VotosDeFormula{
array<char,50> elPartido, laFormula;
unsigned losVotos;
};
UTN – FRBA – Algoritmos y Estructura de Datos – Examen Final – 31/07/2015
2.
Diagramar o codificar la función ProcesarMesa que dado el nombre de un archivo de mesa, procese ese archivo, actualice los
resultados generales e informe el avance. La función debe verificar que la mesa no haya sido procesada previamente. Para la
actualización, recuerde leer, posicionarse, y escribir.
En C
void ProcesarMesa(char* nombreMesa) {
VotosDeFormula formula, formulaTotal;
if (esMesaProcesada(getMesa(nombreMesa))) return;
FILE* archMesa = fopen(nombreMesa, "rb+");
int cantidadDeVotosTotalesMesa = 0;
fseek(losResultadosGenerales, 0, SEEK_SET);
fread(&formula, sizeof(formula), 1, archMesa);
while (!feof(archMesa)) {
fread(&formulaTotal, sizeof(formulaTotal), 1, losResultadosGenerales);
formulaTotal.votos+= formula.votos;
fseek(losResultadosGenerales, ftell(losResultadosGenerales – sizeof(formulaTotal), SEEK_SET);
write(&formulaTotal, sizeof(formulaTotal), 1, losResultadosGenerales);
cantidadDeVotosTotalesMesa+= candidato.votos;
fread(&formula, sizeof(formula), 1, archMesa);
}
informarAvance(cantidadDeVotosTotalesMesa);
fclose(archMesa);
return;
}
En C con plantillas
void procesarMesa(char* nombreMesa) {
if (esMesaProcesada(getMesa(nombreMesa))) return;
FILE* archMesa = fopen(nombreMesa, "rb+");
int cantidadDeVotosTotalesMesa = 0;
seek<VotosDeFormula>(losResultadosGenerales, 0);
VotosDeFormula formula = read<VotosDeFormula>(archMesa);
while (!feof(archMesa)) {
VotosDeFormula formulaTotal = read<VotosDeFormula>(losResultadosGenerales);
formulaTotal.votos+= formula.votos;
seek<VotosDeFormula>(losResultadosGenerales, filePos< VotosDeFormula >
(losResultadosGenerales) - 1);
write< VotosDeFormula >(losResultadosGenerales, candidatoTotal);
cantidadDeVotosTotalesMesa+= candidato.votos;
candidato = read<VotosDeFormula>(archMesa);
}
informarAvance(cantidadDeVotosTotalesMesa);
fclose(archMesa);
return;
}
En C ++
void ProcesarMesa(string unNombreDeArchivoDeMesa)
extern stream losResultadosGenerales; // Declaración extern es innecesaria, pero clarifica
unsigned elNumeroDeMesa = GetMesa(unNombreDeArchivoDeMesa);
if(EsMesaYaProcesada(elNumeroDeMesa)) return;
stream laMesa=AbrirArchivo(unNombreDeArchivoDeMesa); // me conecto a la mesa
losResultadosGenerales.seekg(0);
losResultadosGenerales.seekp(0); // incializo los cursores de losResultados
VotosDeFormula unRegistroEnMesa, unRegistroEnResultados;
unisgned losVotosDeLaMesa = 0;
while(Read(laMesa, unRegistroEnMesa)){
Read(losResultadosGenerales, unRegistroEnResultados);
// Leo y avanzo
unRegistroEnResultados.losVostos += unRegistroEnResultados; // Acumulo
Write(losResultadosGenerales, unRegistroEnResultados);
// Escribo y avanzo
losVotosDeLaMesa += unRegistroEnMesa.losVotos;
}
InformarAvance(votosDeLaMesa);
}
template<typename T> std::ostream& Write(std::ostream& out, const T& block){
return out.write(reinterpret_cast<const char*>(&block), sizeof block );
}
template<typename T> std::istream& Read(std::istream& in, T& block){
return in.read( reinterpret_cast<char*>(&block), sizeof block );
}
UTN – FRBA – Algoritmos y Estructura de Datos – Examen Final – 31/07/2015
3.
Diagramar o codificar la función InformarAvance dada la cantidad de votos de una mesa, actualiza la cantidad de mesas
escrutadas, y envía a la salida estándar el porcentaje de mesas escrutadas y el porcentaje votos obtenidos por cada formula a ese
momento.
En C
// variables Globales
FILE * losResultadosGenerales;
unsigned laCantidadDeMesasEscrutadasHastaAhora;
unsigned laCantidadVotosEscrutadosHastaAhora;
const unsigned laCantidadDeMesasTotal = 2;
void informarAvance(int cantidadDeVotosTotalesMesa) {
VotosDeFormula blanco, impugnado, noVoto, formulaTotal;
laCantidadDeMesasEscrutadasHastaAhora++;
laCantidadVotosEscrutadosHastaAhora += cantidadDeVotosTotalesMesa;
cout << "Cantidad de mesas escrutadas: " << laCantidadDeMesasEscrutadasHastaAhora * 100.0 /
laCantidadDeMesasTotal << "\%" << endl;
fseek(losResultadosGenerales, 0, SEEK_SEET);
fread(&blanco, sizeof(blanco),1, losResultadosGenerales);
cout << "Votos en blanco : " <<
blanco.votos * 100.0 / laCantidadVotosEscrutadosHastaAhora << "\%" << endl;
fread(&impugnado, sizeof(impugnado), 1losResultadosGenerales);
cout << "Votos impugnados : " <<
impugnado.votos * 100.0 / laCantidadVotosEscrutadosHastaAhora << "\%" << endl;
fread(noVoto, sizeof(noVoto), 1,losResultadosGenerales);
cout << "No votaron : " <<
noVoto.votos * 100.0 / laCantidadVotosEscrutadosHastaAhora << "\%" << endl;
fread(&formulaTotal, sizeof(formulaTotal), 1, losResultadosGenerales);
while (!feof(losResultadosGenerales)) {
cout << formulaTotal.partido << " - " << formulaTotal.formula << " : " <<
formulaTotal.votos * 100.0 / laCantidadVotosEscrutadosHastaAhora << "\%" << endl;
fread(&formulaTotal, sizeof(formulaTotal), 1, losResultadosGenerales);
}
}
En C++
void InformarAvance(unsigned unosVotosDeMesa){
// La declaración extern no es necesaria, pero clarifica
extern unsigned laCantidadDeMesasEscrutadasHastaAhora;
extern unsigned laCantidadDeVotosEscrutadosHastaAhora;
extern const unsigned laCantidadDeMesasTotal;
++laCantidadDeMesasEscrutadasHastaAhora; // cuento mesas
laCantidadDeVotosEscrutadosHastaAhora += unosVotosDeMesa; //acumulo votos
cout
<< "Mesas escrutadas: "
<< laCantidadDeMesasEscrutadasHastaAhora / laCantidadDeMesasTotal * 100;
<< endl;
losResultadosGenerales.seekg(0);
while(Read(losResultadosGenerales, unRegistroEnResultados))
cout
<< unRegistroEnResultados.elPartido << '\t'
<< unRegistroEnResultados.laFormula << '\t'
<< unRegistroEnResultados.losVotos / laCantidadDeVotosEscrutadosHastaAhora * 100;
<< endl;
}
Descargar