El contexto es el siguiente: A partir de un archivo de antecedentes que guarda un identificador de un alumno, que a su vez guarda un identificador de un centro educativo, lo que estoy haciendo es un ranking de centros educativos en los que tienen más delitos cometidos con sus alumnos.
Para ello me propuse crear un archivo temporal, que está ordenado decrecientemente en torno al conteo de los centros que tienen más delitos de sus alumnos. Así a medida que se revisa el archivo de antecedentes, el archivo de conteo crece y se edita contantemente hasta obtener un ranking ordenado, del cual solo al final tendré que mostrar el resultado por pantalla.
La inserción y edición funcionan bien, pero mis problemas van cuando la función que me permite mostrar por pantalla el archivo de conteo (RevisarConteo), la quiero pasar al final (suena lógico porque no voy a estar mostrando constantemente por pantalla como se hace el ranking, solo lo voy a mostrar una vez), en ese caso al ejecutar (gcc) me sale un segfault.
Código C:
Ver original#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stAntecedente {
char rut_alumno[12];
int id_documento;
char sentencia[30];
int id_delito;
char fecha[12];
char rut_polichile[12];
};
struct stAlumno {
char rut_alumno[12];
char nombre[30];
int edad;
int id_institucion;
};
struct stCentroEduc {
int id_institucion;
char nombre[30];
};
struct stRegistroConteo {
int cuenta;
char nombre_institucion[30];
};
void RevisarConteo()
{
/* Revisa el ranking archivado */
struct stRegistroConteo reg_conteo;
FILE *file_conteo;
file_conteo
= fopen("conteo.dat", "r+b");
while (fread(®_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteo
)) {
printf("%4d %-10s\n", reg_conteo.
cuenta, reg_conteo.
nombre_institucion); }
}
void InsertarNuevoConteo (struct stRegistroConteo new_conteo)
{
/* El archivo conteo emula un ranking de las instituciones cuyos delitos de sus alumnos más figuran en los antecedentes
en otras palabras, el archivo está ordenado por la clave de cuenta en orden decreciente */
struct stRegistroConteo conteo_temp;
int insertado = 0;
FILE *file_conteo, *file_conteotemp;
file_conteo
= fopen("conteo.dat", "r+b"); if(!file_conteo)
file_conteo
= fopen("conteo.dat", "w+b"); file_conteotemp
= fopen("conteotemp.dat", "r+b"); if(!file_conteotemp)
file_conteotemp
= fopen("conteotemp.dat", "w+b");
while (fread(&conteo_temp
, sizeof(struct stRegistroConteo
), 1, file_conteo
)) {
if ((new_conteo.cuenta > conteo_temp.cuenta) && insertado==0)
{
fwrite(&new_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteotemp
); fwrite(&conteo_temp
, sizeof(struct stRegistroConteo
), 1, file_conteotemp
); insertado=1;
}
else
{
fwrite(&conteo_temp
, sizeof(struct stRegistroConteo
), 1, file_conteotemp
); }
}
if (insertado==0)
fwrite(&new_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteotemp
);
rename ("conteotemp.dat", "conteo.dat"); }
void ConteoGeneral (char nombre_institucion[30])
{
/* Esta función procederá en general a hacer el escrutinio de cada institución de cada alumno
en el archivo de antecedentes */
int encontrado = 0;
int conteo;
struct stRegistroConteo regi_conteo;
FILE *file_conteo, *file_conteotemp;
file_conteo
= fopen("conteo.dat", "r+b"); if(!file_conteo)
file_conteo
= fopen("conteo.dat", "w+b");
/* Así por cada institución buscamos en el archivo de conteo: */
while (fread(®i_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteo
)) { if (!strcmp(regi_conteo.
nombre_institucion, nombre_institucion
)) encontrado = 1;
}
/* Si no está la institución, la insertamos inmediatamente como nueva... */
if (encontrado==0)
{
strcpy(regi_conteo.
nombre_institucion, nombre_institucion
); regi_conteo.cuenta = 1;
InsertarNuevoConteo(regi_conteo);
}
/* ...pero si está, se debe borrar la institución del archivo original y reinsertarse con su conteo sumado en 1 */
else
{
file_conteo
= fopen("conteo.dat", "r+b"); if(!file_conteo)
file_conteo
= fopen("conteo.dat", "w+b"); file_conteotemp
= fopen("conteotemp.dat", "r+b"); if(!file_conteotemp)
file_conteotemp
= fopen("conteotemp.dat", "w+b");
while (fread(®i_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteo
)) {
if (strcmp(nombre_institucion
, regi_conteo.
nombre_institucion)) fwrite(®i_conteo
, sizeof(struct stRegistroConteo
), 1, file_conteotemp
); else
conteo = regi_conteo.cuenta +1;
}
rename ("conteotemp.dat", "conteo.dat");
strcpy(regi_conteo.
nombre_institucion, nombre_institucion
); regi_conteo.cuenta = conteo;
InsertarNuevoConteo(regi_conteo);
}
}
void BuscarCentro (int temp_idinstitucion)
{
/* Por cada alumno se busca el centro educacional al que pertenece */
struct stCentroEduc regi_centro;
FILE *file_cen;
file_cen
= fopen("centros.dat", "r+b"); if(!file_cen)
file_cen
= fopen("centros.dat", "w+b");
while (fread(®i_centro
, sizeof(struct stCentroEduc
), 1, file_cen
)) {
if (temp_idinstitucion==regi_centro.id_institucion)
{
ConteoGeneral(regi_centro.nombre);
}
}
}
void BuscarAlumno (char temp_rutalumno[12])
{
/* Por cada registro en el archivo de antecedentes busca un alumno */
struct stAlumno regi_alumno;
FILE *file_alu;
file_alu
= fopen("alumnos.dat", "r+b"); if(!file_alu)
file_alu
= fopen("alumnos.dat", "w+b");
while (fread(®i_alumno
, sizeof(struct stAlumno
), 1, file_alu
)) {
if (!strcmp(temp_rutalumno
, regi_alumno.
rut_alumno))
{
BuscarCentro(regi_alumno.id_institucion);
}
}
}
int main()
{
/* Función principal: Revisa el archivo de antecedentes */
struct stAntecedente regi_antecedente;
FILE *file_ant;
file_ant
= fopen("antecedentes.dat", "r+b"); if(!file_ant)
file_ant
= fopen("antecedentes.dat", "w+b"); printf("------------------------\n"); printf("------------------------\n"); while (fread(®i_antecedente
, sizeof(struct stAntecedente
), 1, file_ant
)) BuscarAlumno (regi_antecedente.rut_alumno);
RevisarConteo();
}
Sin embargo, cuando la función la paso a la función que me irá a buscar por cada alumno a su centro educativo, esta funciona, aunque con un loop por la búsqueda en el archivo de antecedentes.
¿Alguna idea de qué estaré cometiendo mal?
Saludos!