/*Una empresa desea construir una base de datos para registrar datos de
postulantes a diversos puestos a cubrir.
Para ello solicitó que se escriba un programa para llevar registro de
los datos de dichos postulantes.
Se suministra un programa que realiza lo solicitado y que funciona
correctamente, pero el programador olvidó incluir entre dichos datos
el número de DNI y el domicilio del postulante.
Se pide agregar al siguiente programa dichos datos adecuando las funciones
que sea necesario, para que siga funcionando correctamente.
Se recomienda probar bien el programa antes de modificarlo para
familiarizarse con su funcionamiento.
* /
/* Archivos de cabecera */
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Definiciones de constantes */
#define LNOM 32
#define LNAC 12
#define LTEL 16
#define LDNI 11
#define ALTA 1
#define BAJA 2
#define MODIF 3
#define LISTAR 4
#define SALIR 5
/* Definiciones de tipos de datos */
typedef struct f
{
int d, m, a;
}fecha;
typedef struct persona Nodo, * pNodo;
struct persona
{
char nom[LNOM];
char te[LTEL];
fecha nacim;
pNodo pSig;
char dni[LDNI];
char domicilio[LNOM];
};
/* Prototipos de funciones */
void altas(pNodo*);
void insertarEnOrden(pNodo*, pNodo);
void bajas(pNodo*);
void eliminarNodo(pNodo*, pNodo);
void modificar(pNodo);
void listar(pNodo);
pNodo buscar(pNodo, char buscado[]);
char* buscarSubcadena(char cad[], char sub[]);
void actualizarRegistro(pNodo);
int menu(void);
void ingresarCadena(char[], int, char[]); /* Esta función permite ingresar una
cadena de texto controlando su longitud y eliminando el '\n' */
/* Podría reemplazarse por gets() */
void guardarArchText(pNodo);
void leerArchTxt(pNodo*);
void liberarMemoria(pNodo*);
int main(void)
{
int opc;
pNodo inicio; /* Puntero para la lista enlazada */
inicio = NULL; /* Lista inicialmente vacía */
leerArchTxt(&inicio);
opc = menu();
while (opc != SALIR)
{
switch (opc)
{
case ALTA:
altas(&inicio);
break;
case BAJA:
bajas(&inicio);
break;
case MODIF:
modificar(inicio);
break;
case LISTAR:
listar(inicio);
break;
}
opc = menu();
}
guardarArchText(inicio);
liberarMemoria(&inicio);
return 0;
}
int menu(void)
{
int opc, vale; /* La variable 'vale' se utiliza para evitar un error al
ingresar una letra en lugar de un dígito */
printf("Menu\n");
printf("1 - Alta\n");
printf("2 - Bajas\n");
printf("3 - Modificar\n");
printf("4 - Listar\n");
printf("5 - Salir\n");
do
{
printf("Opcion: ");
vale = scanf("%d", &opc);
while (fgetc(stdin) != '\n') /* Elimina el '\n' de la cola del teclado
*/
;
} while (vale != 1 || opc<ALTA || opc>SALIR);
return opc;
}
void altas(pNodo* pLista)
{
char aux[LNOM];
pNodo nuevo;
ingresarCadena(aux, LNOM, "Nombre (enter en blanco para terminar): ");
while (aux[0] != '\0') /* Mientras se ingrese un nombre */
{
if ((nuevo = (pNodo)malloc(sizeof(Nodo))) == NULL) /* Memoria para el
nuevo nodo */
{
printf("Error: no hay suficiente memoria\n");
return;
}
strcpy(nuevo->nom, aux);
ingresarCadena(nuevo->te, LTEL, "TE: ");
printf("Ingresar fecha (dd/mm/aaaa): ");
scanf("%d/%d/%d", &nuevo->nacim.d, &nuevo->nacim.m, &nuevo->nacim.a);
fgetc(stdin);
ingresarCadena(nuevo->dni, LDNI, "DNI: ");
ingresarCadena(nuevo->domicilio, LNOM, "Domicilio: "); // se agrega
insertarEnOrden(pLista, nuevo); /* Agrega el nuevo nodo a la lista */
ingresarCadena(aux, LNOM, "Nombre(enter para terminar) : ");
}
}
void insertarEnOrden(pNodo* pIni, pNodo nuevo)
{
pNodo actual, ant;
actual = *pIni;
if (actual == NULL || strcmp(nuevo->nom, actual->nom) < 0) /*Si la lista está
vacía o el nuevo va al inicio */
{
nuevo->pSig = *pIni;
*pIni = nuevo;
}
else
{
ant = actual;
actual = actual->pSig;
while (actual != NULL && strcmp(nuevo->nom, actual->nom) > 0)
{
ant = actual;
actual = actual->pSig;
}
ant->pSig = nuevo;
nuevo->pSig = actual;
}
}
/* Recibe la cadena, su longitud y un mensaje para imprimir en pantalla */
void ingresarCadena(char cadena[], int tamano, char mensaje[])
{
char* p;
printf("%s", mensaje);
fgets(cadena, tamano, stdin);
if ((p = strchr(cadena, '\n')) != NULL)
*p = '\0';
else
while (fgetc(stdin) != '\n')
;
}
void listar(pNodo pLista)
{
printf("\nListado:\n");
printf("%-*s %-*s %-*s %-*s %-*s\n", LNOM, "Nombre", LTEL, "Telefono", LNAC,
"Nacimiento", LDNI, "DNI", LNOM, "Domicilio");
printf("%-*s %-*s %-*s %-*s %-*s \n", LNOM, "------", LTEL, "---------",
LNAC, "-------", LDNI, "---", LNOM, "---------");
while (pLista != NULL)
{
printf("%-*s %-*s %02d/%02d/%4d %-*s %-*s\n", LNOM, pLista->nom, LTEL,
pLista->te, pLista->nacim.d, pLista->nacim.m, pLista->nacim.a, LDNI, pLista->dni,
LNOM, pLista->domicilio);
pLista = pLista->pSig;
}
printf("\n");
}
void guardarArchText(pNodo pInicio)
{
FILE* pf;
if ((pf = fopen("AgendaList.txt", "wt")) != NULL)
{
while (pInicio != NULL)
{
fprintf(pf, "%s\n", pInicio->nom);
fprintf(pf, "%s\n", pInicio->te);
fprintf(pf, "%d/%d/%d\n", pInicio->nacim.d, pInicio->nacim.m,
pInicio->nacim.a);
fprintf(pf, "%s\n", pInicio->dni);
fprintf(pf, "%s\n", pInicio->domicilio);
pInicio = pInicio->pSig;
}
fclose(pf);
}
else
printf("Error: no se grabó el archivo\n");
}
void leerArchTxt(pNodo* pIni)
{
FILE* pf;
pNodo nuevo;
char aux[LNOM];
char* p;
if ((pf = fopen("AgendaList.txt", "rt")) != NULL)
{
fgets(aux, LNOM, pf);
while (!feof(pf))
{
if ((p = strchr(aux, '\n')) != NULL)
p = '\0'; // Elimina el '\n' de la cadena leída * /
nuevo = (pNodo)malloc(sizeof(Nodo));
if (nuevo == NULL)
{
printf("ERROR: insuficiente memoria\n");
return;
}
strcpy(nuevo->nom, aux);
fgets(nuevo->te, LTEL, pf);
if ((p = strchr(nuevo->te, '\n')) != NULL)
*p = '\0';
fscanf(pf, "%02d/%02d/%4d", &(nuevo->nacim.d), &(nuevo->nacim.m),
&(nuevo->nacim.a));
fgetc(pf);
fgets(nuevo->dni, LDNI, pf);
if ((p = strchr(nuevo->dni, '\n')) != NULL)
*p = '\0';
//fgetc(pf);
fgets(nuevo->domicilio, LNOM, pf);
if ((p = strchr(nuevo->domicilio, '\n')) != NULL)
*p = '\0';
//fgetc(pf);
insertarEnOrden(pIni, nuevo); /* Agrega el nuevo nodo a la lista
*/
fgets(aux, LNOM, pf);
}
fclose(pf);
}
else
printf("No se encuentra el archivo\n");
}
pNodo buscar(pNodo pLista, char buscado[])
{
pNodo busq = NULL;
int c, encontrado = 0;
while (pLista != NULL && !encontrado)
{
if (buscarSubcadena(pLista->nom, buscado) != NULL)
{
printf("%-*s %-*s %02d/%02d/%4d %-*s %-*s\n", LNOM, pLista->nom,
LTEL, pLista->te, pLista->nacim.d, pLista->nacim.m, pLista->nacim.a, LDNI, pLista-
>dni, LNOM, pLista->domicilio);
printf("Es el nombre buscado? (s/n): \n");
c = fgetc(stdin);
if (toupper(c) == 'S')
{
encontrado = 1;
busq = pLista;
}
while (fgetc(stdin) != '\n')
;
}
pLista = pLista->pSig;
}
return busq;
}
char* buscarSubcadena(char cad[], char sub[]) /* Convierte a minúsculas antes de
buscar */
{
char s1[80], s2[80];
int i = 0;
while (cad[i] != '\0')
{
s1[i] = tolower(cad[i]);
i++;
}
s1[i] = '\0';
i = 0;
while (sub[i] != '\0')
{
s2[i] = tolower(sub[i]);
i++;
}
s2[i] = '\0';
return strstr(s1, s2);
}
void bajas(pNodo* pLista)
{
char buscado[LNOM];
pNodo pBusq;
if (*pLista)
{
ingresarCadena(buscado, LNOM, "BAJAS\n-----\nIngresar nombre a buscar
(enter para salir): ");
while (buscado[0] != '\0')
{
pBusq = buscar(*pLista, buscado);
if (pBusq)
{
eliminarNodo(pLista, pBusq);
}
else
printf("No se encuentra el nombre del registro a dar de
baja\n");
ingresarCadena(buscado, LNOM, "\nBAJAS\n--------------\nIngresar
nombre a buscar (enter para salir): ");
}
}
else
printf("No hay datos cargados\n");
void modificar(pNodo pLista)
{
char buscado[LNOM];
pNodo pBusq;
if (pLista)
{
ingresarCadena(buscado, LNOM, "MODIFICACIONES\n--------------\nIngresar
nombre a buscar (enter para salir): ");
while (buscado[0] != '\0')
{
pBusq = buscar(pLista, buscado);
if (pBusq)
{
actualizarRegistro(pBusq);
}
else
printf("No se encuentra el nombre del registro a modificar\
n");
ingresarCadena(buscado, LNOM, "\nMODIFICACIONES\n--------------\
nIngresar nombre a buscar (enter para salir): ");
}
}
else
printf("No hay datos cargados\n");
}
void eliminarNodo(pNodo* Inicio, pNodo p)
{
pNodo actual, anterior;
anterior = NULL;
actual = *Inicio;
if (actual == p) /* Es el primero */
{
*Inicio = actual->pSig;
free(actual);
}
else
{
while (actual != p)
{
anterior = actual;
actual = actual->pSig;
}
anterior->pSig = actual->pSig;
free(actual);
}
}
void actualizarRegistro(pNodo pAct)
{
char aux[LNOM];
int r;
printf("MODIFICACIONES\n");
printf("NOMBRE: %s\n", pAct->nom);
ingresarCadena(aux, LNOM, "Ingresar el nuevo nombre o enter para dejar el
actual\n");
if (aux[0] != '\0')
strcpy(pAct->nom, aux);
printf("TELEFONO: %s\n", pAct->te);
ingresarCadena(aux, LNOM, "Ingresar el nuevo tel\202fono o enter para dejar
el actual\n");
if (aux[0])
strcpy(pAct->te, aux);
printf("%02d/%02d/%4d: ", pAct->nacim.d, pAct->nacim.m, pAct->nacim.a);
ingresarCadena(aux, LNOM, "Ingresar la nueva fecha o enter para dejar la
actual\n");
if (aux[0])
r = sscanf(aux, "%d/%d/%d", &pAct->nacim.d, &pAct->nacim.m, &pAct-
>nacim.a);
ingresarCadena(aux, LDNI, "Ingresar el nuevo dni enter para dejar el actual\
n");
if (aux[0])
strcpy(pAct->dni, aux);
ingresarCadena(aux, LNOM, "Ingresar el nuevo domicilio o enter para dejar el
actual\n");
if (aux[0])
strcpy(pAct->domicilio, aux);
}
void liberarMemoria(pNodo* pInicio)
{
pNodo actual, anterior;
anterior = NULL;
actual = *pInicio;
while (actual)
{
anterior = actual;
actual = actual->pSig;
free(anterior);
}
*pInicio = NULL;
}