Uso de Ficheros y LSE en C

Iniciado por matiri90, 8 Agosto 2016, 15:57 PM

0 Miembros y 2 Visitantes están viendo este tema.

matiri90

Hola gente. Hace poco que estoy en esto de C.. Leyendo, trate de juntar todo ese conocimiento e hice una agenda.. Creo que se pude mejorar, pero me gustaria saber si las practicas utilizadas estan bien encaminadas.. Desde ya, muchas gracias.. Cualquier consejo, sera tomado como tal..



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define ANCHO_PANTALLA 80 //Maximo de caracteres en la pantalla
#define Max 26 //Arreglo Indice Apellido


typedef struct TipoFecha{
int dia;
int mes;
int año;
}TFecha;

typedef struct TipoAmigo{
char apellido[18];
char nombre[18];
char email[21];
char celular[13];
TFecha fecNac;
bool flag;
}Amigo;

typedef struct ElementoLista{
  Amigo  dato;
  struct ElementoLista *sig;
}Persona;

typedef struct ListaIdentificar {
    Persona *inicio;
}Lista;

typedef struct {
char letra;
int pos;
int cantidad;
}Indice;

const char *arrMes[12]={"ENERO","FEBRERO","MARZO","ABRIL","MAYO","JUNIO","JULIO","AGOSTO","SEPTIEMBRE","OCTUBRE","NOVIEMBRE","DICIEMBRE"};
//const char arrMes[12]={'enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'};


//MENU PRINCIPAL
int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista);
//devuelve la opcion elegido
int mostrarMenu();

//Guarda contacto en el archivo
void guardarContacto(Amigo persona, char *nombreArchivo);



//----Guarda los datos en el archivo


int actualizarArchivo(char *nombreArchivo,Lista *lista);
//Pasa los datos de la lista al archivo
int listaArchivo(Lista *lista, char *nombreArchivo);
//Pasa los datos del archivo a la lista
void archivoLista(char *NombreArchivo, Lista *lista);
//Une 2 listas y las ordena
int unirListas(Lista *lista,Lista *aux);
//Borra los datos y libera la memoria
int destruir(Lista *lista);
//Suprime un dato de la lista
int suprimirInicio (Lista *lista); //de acuerdo al campo flag=='*'
//devuelve el tamaño del archivo
int tamanioArchivo(char *nombreArchivo);
//Muestra los datos guardados en el archivo
void mostrarAgenda(char *nombreArchivo);

int borrarContactoArchivo(char *nombreArchivo, int pos);

Amigo pedirAmigoBuscar();

void mostrarBuscadoArchivo(char *nombreArchivo,Amigo buscoAmigo);



/*
-------FUNCIONES MANEJO DE LISTA DINAMICA (Area de Intercambio)
*/
//Inserta un dato al inicio de la lista en la memoria dinamica
int insertarInicio (Lista *lista,Amigo p);
//devuelve los datos de un amigo que llena el usuario
Amigo pedirAmigo();
//Pide la fecha y la devuelve
TFecha ingresarFecha(Amigo aux);
//Duvuelve el maximo de dias que se pueden ingresar, dado un mes y un año
int topeDias(int mes,int año);
//agrega un amigo a la lista
int agregarAmigo(Lista *lista,char *nombreArchivo);
//revisa la lista para ver si encuentra datos
int estaAmigoLista(Lista *l,Amigo p);
//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p);
//actualiza el archivo. Agrega datos de la lista y ordena el archivo
//ordena la lista por apellido y nombre
void ordenar(Lista *lista);

int borrarContactoLista(Lista *lista, int pos);

void mostrarBuscadoLista(Lista *lista,Amigo buscoAmigo);


//Funciones de Muestra
//Muestra un titulo con los datos de amigo (tipo Tabla)
void tipoTabla();
//Muestra un titulo con los datos de indice (tipo Tabla)
void tipoTablaIndice();
//Muestra los datos de la Lista
void mostrarDatos(Lista *lista);
//Muestra los datos de un amigo
void mostrarAmigo(Amigo p);
//Muestra un titulo en el medio
void mostrarTituloMenu(char *titulo);
//Muestra un mensaje de error
void mostrarMensajeCentro(char *msj);
//Muestra los datos del archivo indice
void mostrarArchivoIndice(char* nombreArchivoIndice);
//Muestra los datos de un elem del archivo indice
void mostrarLetra(Indice indice);


//Muestra los apellidos que comiencen con una letra "x"
//dados una posicion y la cantidad a mostrar, se mueve en el archivo principal y muestra los datos
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant);
/*Listar amigos cuyo apellido comienza con una determinada letra.*/
void MostrarApellidoInicial(char *nombreArchivo,char *nombreArchivoIndice,char c);
//Inicializa el arreglo indice
void inicializar(Indice indice[]);
//Pasa del arreglo al arch
void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]);
//Guarda un dato en el archivo INDICE
void guardarIndice(char *nombreArchivoIndice,Indice ind);
//Se forma el archivo indice
void formarIndice(char *nombreArchivo,char *nombreArchivoIndice);
/*
Listar amigos que cumplen años un determinado mes: el mes será ingresado por
el usuario. Mostrar los registros en formato tabla.
*/
//falta
void MostrarCumpleMes(Lista *lista,int mes);


int main(){
//boolean toReturn=true;
char nombreArchivo[12]= "agenda.bin";
char nombreArchivoIndice[12]= "indice.bin";
Lista *lista;
if ((lista = (Lista *) calloc (1,sizeof(Lista))) == NULL){
    return false;
}
menu (nombreArchivo,nombreArchivoIndice,lista);
return true;
}



int mostrarMenu(){
int opc;
char cadena[10];
do{
mostrarTituloMenu("MENU GENERAL");
printf("\n1) Agregar Amigo al Area de transacciones.");
printf("\n2) Mostrar Area de transacciones.");
printf("\n3) Actualizar Archivo agenda.");
printf("\n4) Mostrar Archivo agenda.");
printf("\n5) Mostrar contactos con la inicial ""x"" en el apellido.");
printf("\n6) Mostrar contactos que cumplan años determinado mes.");
printf("\n7) Buscar contacto.");
printf("\n8) Borrar contacto.");
printf("\n9) Eliminar Archivos.");
printf("\n10) Salir.");
printf("\n\nElige una opcion: ");
fgets(cadena,10,stdin);
        sscanf(cadena,"%i",&opc);
        //scanf("%d",&opc);
}while (opc<1 || opc>10);
return opc;
}

void mostrarTituloMenu(char *titulo){
system("cls");
    printf("%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(titulo)/2, titulo);
}

void mostrarMensajeCentro(char *msj){
    printf("\n\n\n\n\n%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(msj)/2, msj);
}

void mostrarMensajeAviso(char *msj){
    printf("\n\n%*s\n\n", ANCHO_PANTALLA/2 + strlen(msj)/2, msj);
}

void presUnaTecla(){
mostrarMensajeCentro("Presione ENTER para continuar.");
while(getchar() != '\n');
    setbuf(stdin, NULL);
}


int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista){
int pos,opc,mes;
char car;
Amigo amigoBuscar;
    do{
opc=mostrarMenu();
    switch (opc){
    case 1:
    if(!agregarAmigo(lista,nombreArchivo)){
mostrarMensajeCentro("Hubo un error. Elemento duplicado");
}else{
printf("\n\nSe ha hecho correctamente");
    ordenar(lista);
}
break;
case 2:
mostrarTituloMenu("AMIGOS EN AREA DE TRANSACCIONES");
if(lista->inicio!=NULL){
tipoTabla();
mostrarDatos(lista);
printf("\n\n\n\n");
}else
mostrarMensajeCentro("Lista Vacia.");
break;
case 3:
if (actualizarArchivo(nombreArchivo,lista)!=false){
formarIndice(nombreArchivo,nombreArchivoIndice);
(destruir(lista)) ? mostrarMensajeAviso("Se actualizo el archivo y se borro la lista.") : mostrarMensajeAviso("Hubo un problema");
}
break;
case 4:
if(tamanioArchivo(nombreArchivo)!=0){
mostrarTituloMenu("AMIGOS EN ARCHIVO");
mostrarAgenda(nombreArchivo);
printf("\n\n\n\n");
}else{
mostrarMensajeCentro("Archivo Vacio.");
}
break;
case 5:
mostrarTituloMenu("AMIGOS POR INICIAL");
printf("\nIngrese una letra:");
do{
fflush(stdin);
scanf("%c",&car);
}while(car<65 || (car>90 && car<97)|| car>122);
if (car>97 || car<122) car=car-32; //Si no es mayuscula, la transforma en mayuscula
printf("\n\n\n");
mostrarApellidoInicial(nombreArchivo,nombreArchivoIndice,car);
break;
case 6:
    //pedirMes
mes=pedirNombreMes();
mostrarTituloMenu("CUMPLEN AÑOS EN EL MES");
            printf("\nDE %s:\n\n",arrMes[mes-1]);
            printf("\n\nAmigos del archivo:\n\n\n");
tipoTabla();
MostrarCumpleMesArchivo(nombreArchivo,mes);
printf("\n\nAmigos del archivo:\n\n\n");
MostrarCumpleMesLista(lista,mes);
break;
case 7:
amigoBuscar=pedirAmigoBuscar();
printf("\nAmigos del archivo:\n\n\n");
tipoTabla();
mostrarBuscadoArchivo(nombreArchivo,amigoBuscar);
printf("\n\n\nAmigos de la lista:\n\n\n");
(lista->inicio!=NULL) ? mostrarBuscadoLista(lista,amigoBuscar) : mostrarMensajeAviso("Lista Vacia.");
break;
case 8:
    mostrarTituloMenu("BORRAR AMIGO");
if((tamanioArchivo(nombreArchivo)==0)&&(lista->inicio==NULL)){
                mostrarMensajeCentro("No hay elementos.");
}else if((tamanioArchivo(nombreArchivo)!=0)&&(lista->inicio==NULL)){
    printf("\nAmigos en el archivo: \n");
                mostrarAgenda(nombreArchivo);
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarMensajeAviso("Lista Vacia");
                printf("Ingrese el numero de contacto: ");
                scanf("%d",&pos);
                if(borrarContactoArchivo(nombreArchivo,pos)) printf("\nSe ha borrado el usuario con exito");
}else if((tamanioArchivo(nombreArchivo)==0)&&(lista->inicio!=NULL)){
    tipoTabla();
    printf("\nAmigos en el archivo: \n");
    mostrarMensajeAviso("Archivo Vacio");
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarDatos(lista);
                printf("Ingrese el numero de contacto: ");
                scanf("%d",&pos);
                borrarContactoLista(lista,pos);
}else{
    //CONTROLAR LOS MAXIMOS Y MINIMOS
    printf("\nAmigos en el archivo: \n");
                mostrarAgenda(nombreArchivo);
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarDatos(lista);
                int eleccion;
                printf("\n\n\n\n\nDe que lugar quiere eliminar el amigo?");
                printf("\nIngrese \t1.)Agenda. \t2)Transaccion. \t3)Salir\n");
                scanf("%d",&eleccion);
                if (eleccion==1){
                    printf("Ingrese el numero de contacto: ");
                    scanf("%d",&pos);
                    if(borrarContactoArchivo(nombreArchivo,pos)) printf("\nSe ha borrado el usuario con exito");
                }else if(eleccion==2){
                    printf("Ingrese el numero de contacto: ");
                    scanf("%d",&pos);
                    borrarContactoLista(lista,pos);
                }
}
break;
case 9:
remove(nombreArchivo);
remove(nombreArchivoIndice);
mostrarMensajeCentro("Los archivos se borraron efectivamente.");
break;
case 10:
printf ("\nAdios");
break;
}
//
presUnaTecla();
} while (opc!=10);
return 0;
}



int agregarAmigo(Lista *lista,char *nombreArchivo){
Amigo amigo=pedirAmigo();
bool toReturn=true;
if ((estaAmigoLista(lista,amigo)||(estaAmigoArchivo(nombreArchivo,amigo))))
        toReturn=false;
else{
insertarInicio(lista,amigo);
}
return toReturn;
}

void limpiar (char *cadena)
{
  char *p;
  p = strchr (cadena, '\n');
  if (p)
    *p = '\0';
}

Amigo pedirAmigo(){
Amigo aux;
system("cls");
mostrarTituloMenu("MENU DE CARGA DE DATOS");
do{
printf("\nIngrese el apellido de su amigo.\n");
        fgets(aux.apellido,17, stdin);
        limpiar(aux.apellido);
}while (strlen(aux.apellido)>17);
do{
printf("\nIngrese el nombre de su amigo.\n");
        fgets(aux.nombre,17, stdin);
        limpiar(aux.nombre);
}while (strlen(aux.nombre)>17);
do{
printf("\nIngrese el email de su amigo.\n");
        fgets(aux.email,17, stdin);
        limpiar(aux.email);
}while (strlen(aux.email)>17);
do{
printf("\nIngrese el celular de su amigo.\n");
        fgets(aux.celular,15, stdin);
        limpiar(aux.celular);
}while (strlen(aux.celular)>15);
printf("\nFecha de nacimiento de su amigo:\n");
aux.fecNac=ingresarFecha(aux);
aux.flag=true;
//mostrarAmigo(aux);
return aux;
}

int esBisiesto(int a){||
return (a%4==0 && a%100!=0) || (a%400==0);
}

TFecha ingresarFecha(Amigo aux){
int limDias;
char cadena[10];
do{
printf("\nIngrese el año de nacimiento: [1900..2016]\n");
fgets(cadena,10, stdin);
sscanf(cadena,"%i",&aux.fecNac.año);
}while ((aux.fecNac.año>2016)||(aux.fecNac.año<1900));
do{
printf("\nIngrese el mes de nacimiento:\n");
fgets(cadena,10, stdin);
sscanf(cadena,"%i",&aux.fecNac.mes);
}while ((aux.fecNac.mes>12)||(aux.fecNac.mes<1));
limDias=(topeDias(aux.fecNac.mes,aux.fecNac.año));
do{
printf("\nIngrese el dia de nacimiento:[1..%d]\n",limDias);
fgets(cadena,10, stdin);
sscanf(cadena,"%i",&aux.fecNac.dia);
}while ((aux.fecNac.dia>limDias)||(aux.fecNac.dia<1));
return aux.fecNac;
}

int topeDias(int mes,int año){
if((mes==1)||(mes==3)||(mes==5)||(mes==7)||(mes==8)||(mes==10)||(mes==12)){
return 31;
}else if((mes==4)||(mes==6)||(mes==9)||(mes==11)){
return 30;
}else if((mes==2)&&esBisiesto(año)){
return 29;
}else{
return 28;
}
}


int estaAmigoLista(Lista *lista,Amigo p){
  bool existe = false;
  Persona *aux;
  for(aux=lista->inicio; aux && !existe; aux=aux->sig){
    existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
    existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
    existe &= (strcmpi(aux->dato.email,p.email)==0);
    existe &= (strcmpi(aux->dato.celular,p.celular)==0);
    existe &= (aux->dato.fecNac.año==p.fecNac.año);
    existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
    existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
  }
  return existe;
}

//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p){
FILE *file=fopen(nombreArchivo,"rb");
bool existe =false;
Amigo amigo;
while(!existe && fread(&amigo, sizeof(Amigo), 1, file)){
    existe = (strcmpi(amigo.apellido,p.apellido)==0);
    existe &= (strcmpi(amigo.nombre,p.nombre)==0);
    existe &= (strcmpi(amigo.email,p.email)==0);
    existe &= (strcmpi(amigo.celular,p.celular)==0);
    existe &= (amigo.fecNac.año==p.fecNac.año);
    existe &= (amigo.fecNac.mes==p.fecNac.mes);
    existe &= (amigo.fecNac.dia==p.fecNac.dia);
}
fclose(file);
return existe;
}





int insertarInicio(Lista *lista, Amigo amigo){
  int toReturn = false; // error
  Persona *aux = (Persona *) malloc (sizeof (Persona));
  if (aux != NULL){
    aux->dato=amigo;
    aux->sig=lista->inicio;
    lista->inicio=aux;
    toReturn = true; // error
  }
  return toReturn;
}

void tipoTabla(){
printf("%-4s %-15s %-15s %-15s %-12s %-10s\n\n","NUM","APELLIDO","NOMBRE","EMAIL","CELULAR","DD/MM/AAAA");
}


void mostrarAmigo(Amigo p){
printf("%-2s %-15s %-15s %-15s %-12s %i/%i/%i\n","",p.apellido,p.nombre,p.email,p.celular,p.fecNac.dia,p.fecNac.mes,p.fecNac.año);
}


void mostrarDatos(Lista *lista){
Persona *aux=lista->inicio;
int i=1;
while (aux){
printf(" %i ",i);
mostrarAmigo(aux->dato);
aux=aux->sig;
i++;
}
}


int tamanioLista(Lista *lista){
Persona *aux=lista->inicio;
int cant=0;
while (aux){
mostrarAmigo(aux->dato);
aux=aux->sig;
cant++;
}
return cant;
}

void ordenar(Lista *lista){
Amigo cam;
Persona *aux,*aux2,*min;
min=lista->inicio;
while(min){
aux=min;
aux2=min->sig;
while(aux2!=NULL){
if((strcmpi(aux->dato.apellido,aux2->dato.apellido))>0){ //se comparan apellidos
aux=aux2; //se compara el nombre
}else if(((strcmpi(aux->dato.apellido,aux2->dato.apellido))==0)&&((strcmpi(aux->dato.nombre,aux2->dato.nombre))>0)){
aux=aux2;
}
aux2=aux2->sig;
}
cam=min->dato;
min->dato=aux->dato;
aux->dato=cam;
min=min->sig;
}

}


int destruir (Lista *lista){
    bool toReturn=false;
    while (lista->inicio){
        suprimirInicio (lista);
    }
    if(lista->inicio==NULL) toReturn=true;
    return toReturn;
}



/* eliminación al inicio de la lista */
int suprimirInicio (Lista *lista){
// ¿Por qué -1? si no hace nada lo lógico sería retornar 0, equivalente natural de false
bool   toReturn = false;
if (lista->inicio){
Persona *sig = lista->inicio->sig;
free(lista->inicio);
lista->inicio = sig;
toReturn = true; // ¿Por qué 0? siguiendo el planteamiento análogo debería ser 1
}
return toReturn;
}


int listaArchivo(Lista *lista, char *nombreArchivo){
    bool toReturn=false;
if(lista->inicio){
Persona *aux=lista->inicio;
while (aux){
if(aux->dato.flag){
guardarContacto(aux->dato,nombreArchivo);
aux=aux->sig;
}
}
toReturn=true;
}
return toReturn;
}


int unirListas(Lista *lista,Lista *aux){
    bool toReturn=false;
if(aux){
Persona *recorrer=aux->inicio;
while(recorrer){
insertarInicio(lista,recorrer->dato);
recorrer=recorrer->sig;
}
ordenar(lista);
toReturn=true;
}
return toReturn;
}

int tamanioArchivo(char *nombreArchivo){
FILE *file=fopen(nombreArchivo,"ab");
fseek(file, 0, SEEK_END);
int tamanio=ftell(file)/sizeof(Amigo);
fclose(file);
return tamanio;
}


int actualizarArchivo(char *nombreArchivo,Lista *lista){
bool toReturn=true;
if(tamanioArchivo(nombreArchivo)!=0){
Lista *aux;
if ((aux = (Lista *) calloc (1,sizeof(Lista))) == NULL){
mostrarMensajeCentro("Error de Memoria.");
    toReturn=false;
}
archivoLista(nombreArchivo,aux);
if(remove(nombreArchivo)!=-1){
unirListas(lista,aux); //une, ordena
listaArchivo(lista,nombreArchivo);
destruir(aux);
}
}else if(tamanioArchivo(nombreArchivo)==0){
if (listaArchivo(lista,nombreArchivo)==-1){
mostrarMensajeCentro("No hay elementos para guardar.");
toReturn=false;
}
}
return toReturn;
}

//CORREGIR ESTO

void archivoLista(char *nombreArchivo, Lista *aux){
FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }else{
        Amigo amigo;
        rewind(file);
        while(fread(&amigo, sizeof(Amigo), 1, file)){
            if(amigo.flag){
insertarInicio(aux,amigo);
        }
}
        fclose(file);
    }
}


void guardarContacto(Amigo persona, char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&persona, sizeof(Amigo), 1, file);
        fclose(file);
    }
}


void mostrarAgenda(char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    int i=1;
    tipoTabla();
        Amigo persona;
        while (fread(&persona, sizeof(Amigo), 1, file)){
            if(persona.flag){
            printf(" %i ",i);
mostrarAmigo(persona);
i++;
}
        }
        fclose(file);
    }
}


void inicializar(Indice indice[]){
int i;
for (i=0;i<Max;i++){
indice[i].letra=(17+i)+48;
indice[i].pos=-1;
indice[i].cantidad=0;
}
}


int tamanioArchivoIndice(char *nombreArchivoIndice){
FILE *file=fopen(nombreArchivoIndice,"ab");
fseek(file, 0, SEEK_END);
int tamanio=ftell(file)/sizeof(Indice);
fclose(file);
return tamanio;
}


void formarIndice(char *nombreArchivo,char *nombreArchivoIndice){
Indice indice[Max];
inicializar(indice);
Amigo persona;
char inic;
int j=0,encontrado,i=0;
FILE *file=fopen(nombreArchivo,"rb");
while(fread(&persona, sizeof(Amigo), 1, file)){
inic=persona.apellido[0];
if (inic>97 || inic<122) inic=inic-32; //Si no es mayuscula, la transforma en mayuscula
encontrado=0;
while(i<Max && encontrado!=1){
if((indice[i].letra==inic)&&(indice[i].pos==-1)){
indice[i].pos=j;
indice[i].cantidad=indice[i].cantidad+1;
encontrado=1;
}else if((indice[i].letra==inic)&&(indice[i].pos!=-1)){
indice[i].cantidad++;
encontrado=1;
}else{
i++;
}
}
j++;
}
fclose(file);
remove(nombreArchivoIndice);
arregloArchivoIndice(nombreArchivoIndice,indice);
}

void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]){
int i;
for (i=0;i<Max;i++){
guardarIndice(nombreArchivoIndice,indice[i]);
}
}

void guardarIndice(char *nombreArchivoIndice,Indice ind){
    FILE* file= fopen(nombreArchivoIndice, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&ind, sizeof(Indice), 1, file);
        fclose(file);
    }
}


void tipoTablaIndice(){
printf("%-10s %-15s %-15s\n\n","LETRA","POSICION","CANTIDAD");
}

//Muestra uno
void mostrarLetra(Indice ind){
if(ind.cantidad!=0) printf("%-10c %-15d %-15d\n\n",ind.letra,ind.pos,ind.cantidad);
}

//Muestra el arreglo indice (No se usa, solo era para probar)
void mostrarArregloIndice(Indice indice[]){
int i;
tipoTablaIndice();
for (i=0;i<Max;i++){
mostrarLetra(indice[i]);
}
}

//Muestra el archivo indice (No se usa, solo era para probar)
void mostrarArchivoIndice(char* nombreArchivoIndice){
    FILE* file= fopen(nombreArchivoIndice, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        Indice indice;
        while (fread(&indice, sizeof(Indice), 1, file)){
mostrarLetra(indice);
    }
        fclose(file);
    }
}

//Dada una pos y una cantidad, muestra contactos desde una posicion avanzando tanto como cant haya
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant){
FILE *file=fopen(nombreArchivo,"rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    int i,elem;
    if (cant!=0){
    elem=pos;
    tipoTabla();
    for (i=pos;i<pos+cant;i++){
    Amigo amigo;
    fseek (file, (elem)*sizeof(Amigo), SEEK_SET);
        fread(&amigo, sizeof(Amigo), 1, file);
mostrarAmigo(amigo);
elem++;
}
}else{
mostrarMensajeCentro("No hay amigos con esa inicial.");
}
        fclose(file);
        printf("\n\n");
}
}

//Muestra los contactos dependiendo de la letra inicial
void mostrarApellidoInicial(char *nombreArchivo,char *nombreArchivoIndice,char c){
c=c-65;
FILE *file=fopen(nombreArchivo,"rb");
if (tamanioArchivo(nombreArchivo)==0){
mostrarMensajeCentro("Archivo Vacio");
fclose(file);
}else{
FILE *fileInd=fopen(nombreArchivoIndice,"rb");
if (fileInd==NULL){
mostrarMensajeCentro("Error al intentar acceder al archivo");
    }else{
Indice ind;
fseek(fileInd,(c)*sizeof(Indice),SEEK_SET);
fread(&ind,sizeof(Indice),1,fileInd);
fclose(fileInd);
mostrarArchivoApellido(nombreArchivo,ind.pos,ind.cantidad);
}
}
}

int borrarContactoArchivo(char *nombreArchivo, int pos){
    bool toReturn=true;
    if((tamanioArchivo(nombreArchivo)<pos)||(pos<1)){
        printf("La posicion indicada es invalida");
        toReturn=false;
    }else{
        FILE *file=fopen(nombreArchivo,"r+b");
        Amigo amigo;
        fseek (file, (pos-1)*sizeof(Amigo), SEEK_SET);
        fread(&amigo, sizeof(Amigo), 1, file);
        mostrarAmigo(amigo);
        presUnaTecla();
        amigo.flag=false;
        fseek (file, -1*sizeof(Amigo), SEEK_CUR);
        fwrite(&amigo,sizeof(Amigo),1,file);
        fclose(file);
    }
    return toReturn;
}

int borrarContactoLista(Lista *lista, int pos){
    Persona *aux=lista->inicio, *elemEliminar;
    bool toReturn=false;
    int i;
    if(pos!=1){
        for(i=1;i<pos-1;i++){
            aux=aux->sig;
        }
        elemEliminar=aux->sig;
        aux->sig=elemEliminar->sig;
        free(elemEliminar);
        toReturn=true;
    }else{
        suprimirInicio(lista);
        toReturn=true;
    }
    return toReturn;
}

void mostrarBuscadoArchivo(char *nombreArchivo,Amigo buscoAmigo){
FILE *file=fopen(nombreArchivo,"rb");
Amigo amigo;
int i=1;
while(fread(&amigo, sizeof(Amigo), 1, file)){
        if (estaApellidONombre(amigo,buscoAmigo)){
            printf(" %i ",i);
            mostrarAmigo(amigo);
            i++;
        }
}
fclose(file);
    if(i==1)mostrarMensajeAviso("No se encontraron amigos con ese nombre y/o apellido");
}

void mostrarBuscadoLista(Lista *lista,Amigo buscoAmigo){
    Persona *aux=lista->inicio;
    int i=1;
while(aux){
        if(estaApellidONombre(aux->dato,buscoAmigo)){
                printf(" %i ",i);
                mostrarAmigo(aux->dato);
                i++;
        }
        aux=aux->sig;
}
if(i==1) mostrarMensajeAviso("No se encontraron amigos con ese nombre y/o apellido");
}

int estaApellidONombre(Amigo amigo, Amigo buscoAmigo){
    bool existe =false;
    existe = (strcmpi(amigo.apellido,buscoAmigo.apellido)==0);
    existe |= (strcmpi(amigo.nombre,buscoAmigo.nombre)==0);
    return existe;
}

Amigo pedirAmigoBuscar(){
    Amigo amigoBuscar;
    do{
printf("\nIngrese el apellido de su amigo.\n");
        fgets(amigoBuscar.apellido,17, stdin);
        limpiar(amigoBuscar.apellido);
}while (strlen(amigoBuscar.apellido)>17);
do{
printf("\nIngrese el nombre de su amigo.\n");
        fgets(amigoBuscar.nombre,17, stdin);
        limpiar(amigoBuscar.nombre);
}while (strlen(amigoBuscar.nombre)>17);
return amigoBuscar;
}


int pedirNombreMes(){
    char mes[12];
    do{
        printf("\nIngrese el nombre: \n");
        fgets(mes,12, stdin);
        limpiar(mes);
    } while ((strlen(mes)>12) || (esMes(mes))==0);
}

int esMes(char *mes){
    int toReturn=-1;
    int i=0;
    while((i<12) && (toReturn==-1)){
        if(strcmpi(arrMes[i],mes)==0){
            toReturn=i+1;
        }
        i++;
    }
    return toReturn;
}

void MostrarCumpleMesLista(Lista *lista,int mes){
    Persona *aux=lista->inicio;
    int i=1;
    while(aux){
        if(aux->dato.fecNac.mes==mes){
            printf(" %i ",i);
            mostrarAmigo(aux->dato);
            i++;
        }
        aux=aux->sig;
    }
}

void MostrarCumpleMesArchivo(char *nombreArchivo,int mes){
    FILE *file=fopen(nombreArchivo,"rb");
    if(file==NULL){
        mostrarMensajeAviso("Hubo un error al abrir el archivo");
    }else{
        Amigo amigo;
        int i=1;
        while(fread(&amigo,sizeof(Amigo),1,file)){
            if(amigo.fecNac.mes==mes){
                printf(" %i ",i);
                mostrarAmigo(amigo);
                i++;
            }
        }
    }
    fclose(file);
}
[code=c]

[/code]

AlbertoBSD

Solo algunis detalles pero a cualquier le pueden pasar.

El uso de

fflush(stdin);

Esta indefinido recomiendo no usarlo en lo Absoluto.

en los gets si le especificas que son 17 o X cantidad de caracteres  solo guarda el \n si la cadena ingresada es menor a X-2 de longitud

En caso de que la cadena ingresada tebga mayor longiud automaticamente la corta y agrega \0 en la posicion numero 16 de la cadena por lo cual en dado caso no existiria un \n

Otra cosa es las variables enteras que usas como variables booleanas, si funciona claro pero si ya vas a usar true y false pues tambien declara  de una vez las variables bool.

En general todo lo demas muy bien.

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

matiri90

El uso de

[code=c]fflush(stdin);


Esta indefinido recomiendo no usarlo en lo Absoluto.[/code]

Gracias por responder AlbertoBSD.. Si, se me paso por alto, use el fgets() y algunos me quedaron colgados.. Gracias por leer el codigo..

en los gets si le especificas que son 17 o X cantidad de caracteres  solo guarda el \n si la cadena ingresada es menor a X-2 de longitud

A esto lo soluciono usando fgets?.



En caso de que la cadena ingresada tebga mayor longiud automaticamente la corta y agrega \0 en la posicion numero 16 de la cadena por lo cual en dado caso no existiria un \n

Otra cosa es las variables enteras que usas como variables booleanas, si funciona claro pero si ya vas a usar true y false pues tambien declara  de una vez las variables bool

Con esto decis que deberia devolver un bool??


Gracias nuevamente por los consejos!



AlbertoBSD

#3
Lo que te comentaba era por que veo una funcion.

void limpiar (char *cadena)
{
 char *p;
 p = strchr (cadena, '\n');
 if (p)
   *p = '\0';
}


Y por ejemplo si testeas este codigo de prueba:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
char *busqueda = NULL;
char *buffer = calloc(1000,sizeof(char));
printf("Ingrese una cadena de prueba de mas de 10 caracteres: ");
fgets(buffer,10,stdin);
busqueda = strstr(buffer,"\n");
printf("Primer \\n encontrado en la posicion %lu",busqueda-buffer);
return 0;
}|


De va a dar que el enter esta en una posición muyyyyyyy alta, prueba con inputs de 7,8,9,10 el detalle es que pruebe no ser un problema.... o puedes terminar sobreescribiendo alguna parte importante del código o algún apuntador en la memoria, lo cual posteriormente si es un grave problema de seguridad.

Pero como te digo son pequeños detalles y a cualquier le pasan, lo que debes de hacer es buscar por el primero \0 o \n lo que se presente primero y si y solo si, esta dentro de los primero X-1 espacios asignados en el fgets

Y sobre el flush(stdin), busca otra solucion.

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

matiri90


case 5:
mostrarTituloMenu("AMIGOS POR INICIAL");
printf("\nIngrese una letra:");
do{
                fgets(car,3, stdin);
                limpiar(car);
}while((car<65 || (car>90 && car<97)|| car>122)&&(strlen(car)>1));
if (car>97 || car<122) car=car-32; //Si no es mayuscula, la transforma en mayuscula

printf("\ncar %c\n%d\n",car,strlen(car));
presUnaTecla();
mostrarApellidoInicial(nombreArchivo,nombreArchivoIndice,car);
break;


En el case 5 de la funcion menu() Tengo un problema.. No se como hacer para leer un solo elemento y que me tome solo ese elemento..
En este caso si pongo mas de un caracter me da cualquier cosa y si pongo 1 me da error tambien..

Algun consejo?. La funcion limpiar sirve?.


#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {
char *busqueda = NULL;
char *buffer = calloc(1000,sizeof(char));
printf("Ingrese una cadena de prueba de mas de 10 caracteres: ");
fgets(buffer,10,stdin);
busqueda = strstr(buffer,"\n");
printf("Primer \\n encontrado en la posicion %lu",busqueda-buffer);
return 0;
}



Entonces en la fgets(buffer,10,stdin);
Deberia cambiarlo por:


fgets(buffer,3,stdin);


tenia todos scanf y gets con el fflush.. Y lei en este foro que era una mala practica y recomendaban el uso de fgets....
Segui leyendo y dio resultado, pero como que en esos casos de leer un char y eso, no le encuentro la vuelta.. :/

Desde ya, gracias y disculpa las molestias.. Quizas deberia leer mas..

AlbertoBSD

En caso de :

fgets(car,3, stdin);

la variable car deberia de ser:

char car[3];
char aux;



Y la validacion podria ser:

aux = car[0];
}while((aux <65 || (aux >90 && aux <97)|| aux >122));
   if (aux >97 || aux <122) aux =aux - 32;     //Si no es mayuscula, la transforma en mayuscula


Repito son pequeños detalles, es posible que el fflush funcione en algunos compiladores pero no hay garantia que en todos.

La opción es implementar algo como lo que puse.

Y pues lo que dices de leer, tal vez practicar mas, como te digo el codigo esta bien para un trabajo cualquiera, pero si en algun momento implementas algun programa "Grande" es posible que puedas tener bugs si la entrada que ingresa el usuario esta "malformada" en fin  son pequeños detalles.

Y si la funcion limpiar sirve solo que deberia de limitarse solo si encuentra un \n en los primeros X caracteres, si el \n se encuentra despues de esa cantidad, es posible que pertenezca a otra variable y no seria recomendable sobreescribirlo ya que perteneceria a otra variable.

Aqui hay algunos articulos que te interesen:

https://foro.elhacker.net/programacion_cc/c_duda_con_la_funcion_scanf-t446111.0.html;msg2052213
https://foro.elhacker.net/programacion_cc/evitar_leer_el_salto_de_linea_cuando_leemos_cadenas_en_c-t449285.0.html
https://foro.elhacker.net/programacion_cc/zanjar_de_una_vez_fflushstdin-t265125.0.html;msg1294511



Saludos!

Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

matiri90

#6
AlbertoBSD

La solucion que mandaste anda espectacular.. ;)

Le agregue un par de cosas a la funcion limpiar..

void limpiar (char *cadena){
   char *p;
   p = strchr (cadena, '\n');
   if (p){
       *p = '\0';
   }else{
       pausarPrograma();
   }
}


y la pausarPrograma()


void pausarPrograma(){
while(getchar() != '\n');
   setbuf(stdin, NULL);
}


probando llegue a esa solucion..

Lo que si, tengo problemas con esta funcion..

TFecha ingresarFecha(Amigo aux){
int limDias,busqueda,buffer;
char cadena[10];
do{
printf("\nIngrese el año de nacimiento: [1900..2016]\n");
fgets(cadena,6, stdin);
sscanf(cadena,"%d",&aux.fecNac.año);
}while ((aux.fecNac.año>2016)||(aux.fecNac.año<1900));
limpiar(cadena);
do{
printf("\nIngrese el mes de nacimiento:\n");
fgets(cadena,4,stdin);
sscanf(cadena,"%d",&aux.fecNac.mes);
}while (((aux.fecNac.mes>12)||(aux.fecNac.mes<1)));
limDias=(topeDias(aux.fecNac.mes,aux.fecNac.año));
do{
printf("\nIngrese el dia de nacimiento:[1..%d]\n",limDias);
fgets(cadena,4, stdin);
sscanf(cadena,"%d",&aux.fecNac.dia);
}while ((aux.fecNac.dia>limDias)||(aux.fecNac.dia<1));
return aux.fecNac;
}


Cuando agregas 1 amigo, anda bien.. Pero, al agregar 1 mas.. O sea..
Agrego un amigo, funciona bien..
Agrego otro amigo, y no se porque!?, en el mes, le pone 2..
Le pone 2, si vos apretas ENTER y no pones nada.. Se entiende?
Pero en el año y en el dia, no pasa nada..

Insisto, no le encuentro la vuelta, pero acarrea un 2.. Y solo sucede en el mes..
No se en que parte le estoy errando :/

AlbertoBSD

Hay que ver como esta llamando a

TFecha ingresarFecha(Amigo aux);

El detalle que tengo mucho que no programo sin apuntadores y el acceso a los elementos de tus estrucuras me confunde un poquito....

Donde validas que el mes tiene 2 en ese momento?

Despues del sscanf coloca un printf imprimiendo el valor capturado si ahi se imprime bien entonces el problema esta en otro lado

Saludos!
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

matiri90

Insertar Cita
Hay que ver como esta llamando a


TFecha ingresarFecha(Amigo aux);

El detalle que tengo mucho que no programo sin apuntadores y el acceso a los elementos de tus estrucuras me confunde un poquito....

Esa seria una buena practica??. Como para mejorar, pregunto..



Donde validas que el mes tiene 2 en ese momento?

Despues del sscanf coloca un printf imprimiendo el valor capturado si ahi se imprime bien entonces el problema esta en otro lado


Vos sabes que habia hecho ese printf a modo de bandera..
Pero cuando preguntaste, como la invocaba me diste una idea de donde podria estar el error..

aux.fecNac=ingresarFecha();

antes, era..

aux.fecNac=ingresarFecha(aux);

Y cambie la funcion ingresarFecha..

TFecha ingresarFecha(){
int limDias,busqueda,buffer;
TFecha fecha;
char cadena[10];
do{
printf("\nIngrese el año de nacimiento: [1900..2016]\n");
fgets(cadena,6, stdin);
sscanf(cadena,"%d",&fecha.año);
}while ((fecha.año>2016)||(fecha.año<1900));
limpiar(cadena);
do{
printf("\nIngrese el mes de nacimiento:\n");
fgets(cadena,4,stdin);
sscanf(cadena,"%d",&fecha.mes);
printf("%d",fecha.mes);
}while ((fecha.mes>12)||(fecha.mes<1));
limDias=(topeDias(fecha.mes,fecha.año));
do{
printf("\nIngrese el dia de nacimiento:[1..%d]\n",limDias);
fgets(cadena,4, stdin);
sscanf(cadena,"%d",&fecha.dia);
}while ((fecha.dia>limDias)||(fecha.dia<1));
return fecha;
}



Ahora funciona bien.. Probe ese error y no lo hizo mas..
Lo voy a probar bien y si funciona bien, lo subo..

Gracias AlbertoBSD..

matiri90

Dejo el codigo terminado a mi entender.. O quizas, me faltaria dividorlo en cabeceras..
Algun consejo para esto?. Gracias..


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define ANCHO_PANTALLA 80 //Maximo de caracteres en la pantalla
#define Max 26 //Arreglo Indice Apellido


typedef struct TipoFecha{
int dia;
int mes;
int año;
}TFecha;

typedef struct TipoAmigo{
char apellido[18];
char nombre[18];
char email[21];
char celular[13];
TFecha fecNac;
bool flag;
}Amigo;

typedef struct ElementoLista{
  Amigo  dato;
  struct ElementoLista *sig;
}Persona;

typedef struct ListaIdentificar {
    Persona *inicio;
}Lista;

typedef struct {
char letra;
int pos;
int cantidad;
}Indice;

const char *arrMes[12]={"ENERO","FEBRERO","MARZO","ABRIL","MAYO","JUNIO","JULIO","AGOSTO","SEPTIEMBRE","OCTUBRE","NOVIEMBRE","DICIEMBRE"};
//const char arrMes[12]={'enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre'};


//MENU PRINCIPAL
int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista);
//devuelve la opcion elegido
int mostrarMenu();

//Guarda contacto en el archivo
void guardarContacto(Amigo persona, char *nombreArchivo);

void pausarPrograma();

void limpiar (char *cadena);

//----Guarda los datos en el archivo


int actualizarArchivo(char *nombreArchivo,Lista *lista);
//Pasa los datos de la lista al archivo
int listaArchivo(Lista *lista, char *nombreArchivo);
//Pasa los datos del archivo a la lista
void archivoLista(char *NombreArchivo, Lista *lista);
//Une 2 listas y las ordena
int unirListas(Lista *lista,Lista *aux);
//Borra los datos y libera la memoria
int destruir(Lista *lista);
//Suprime un dato de la lista
int suprimirInicio (Lista *lista); //de acuerdo al campo flag=='*'
//devuelve el tamaño del archivo
int tamanioArchivo(char *nombreArchivo);
//Muestra los datos guardados en el archivo
void mostrarAgenda(char *nombreArchivo);

int borrarContactoArchivo(char *nombreArchivo, int pos);

Amigo pedirAmigoBuscar();

void mostrarBuscadoArchivo(char *nombreArchivo,Amigo buscoAmigo);



/*
-------FUNCIONES MANEJO DE LISTA DINAMICA (Area de Intercambio)
*/
//Inserta un dato al inicio de la lista en la memoria dinamica
int insertarInicio (Lista *lista,Amigo p);
//devuelve los datos de un amigo que llena el usuario
Amigo pedirAmigo();
//Pide la fecha y la devuelve
TFecha ingresarFecha();
//Duvuelve el maximo de dias que se pueden ingresar, dado un mes y un año
int topeDias(int mes,int año);
//agrega un amigo a la lista
int agregarAmigo(Lista *lista,char *nombreArchivo);
//revisa la lista para ver si encuentra datos
int estaAmigoLista(Lista *l,Amigo p);
//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p);
//actualiza el archivo. Agrega datos de la lista y ordena el archivo
//ordena la lista por apellido y nombre
void ordenar(Lista *lista);
//borra un contacto de la lista
int borrarContactoLista(Lista *lista, int pos);
//Muestra un amigo de acuerdo a unos datos dados
void mostrarBuscadoLista(Lista *lista,Amigo buscoAmigo);
//Muestra los apellido que comiencen con una dada letra
void mostrarApellidoInicialLista(Lista *lista, char car);


//Funciones de Muestra
//Muestra un titulo con los datos de amigo (tipo Tabla)
void tipoTabla();
//Muestra un titulo con los datos de indice (tipo Tabla)
void tipoTablaIndice();
//Muestra los datos de la Lista
void mostrarDatos(Lista *lista);
//Muestra los datos de un amigo
void mostrarAmigo(Amigo p);
//Muestra un titulo en el medio
void mostrarTituloMenu(char *titulo);
//Muestra un mensaje de error
void mostrarMensajeCentro(char *msj);
//Muestra los datos del archivo indice
void mostrarArchivoIndice(char* nombreArchivoIndice);
//Muestra los datos de un elem del archivo indice
void mostrarLetra(Indice indice);


//Muestra los apellidos que comiencen con una letra "x"
//dados una posicion y la cantidad a mostrar, se mueve en el archivo principal y muestra los datos
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant);
/*Listar amigos cuyo apellido comienza con una determinada letra.*/
void mostrarApellidoInicialArchivo(char *nombreArchivo,char *nombreArchivoIndice,char c);
//Inicializa el arreglo indice
void inicializar(Indice indice[]);
//Pasa del arreglo al arch
void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]);
//Guarda un dato en el archivo INDICE
void guardarIndice(char *nombreArchivoIndice,Indice ind);
//Se forma el archivo indice
void formarIndice(char *nombreArchivo,char *nombreArchivoIndice);
/*
Listar amigos que cumplen años un determinado mes: el mes será ingresado por
el usuario. Mostrar los registros en formato tabla.
*/

void mostrarCumpleMesLista(Lista *lista,int mes);

void mostrarCumpleMesArchivo(char *nombreArchivo,int mes);

int main(){
//boolean toReturn=true;
char nombreArchivo[12]= "agenda.bin";
char nombreArchivoIndice[12]= "indice.bin";
Lista *lista;
if ((lista = (Lista *) calloc (1,sizeof(Lista))) == NULL){
    return false;
}
menu (nombreArchivo,nombreArchivoIndice,lista);
return true;
}



int mostrarMenu(){
int opc;
char cadena[10];
do{
mostrarTituloMenu("MENU GENERAL");
printf("\n1) Agregar Amigo al Area de transacciones.");
printf("\n2) Mostrar Area de transacciones.");
printf("\n3) Actualizar Archivo agenda.");
printf("\n4) Mostrar Archivo agenda.");
printf("\n5) Mostrar contactos con la inicial ""x"" en el apellido.");
printf("\n6) Mostrar contactos que cumplan años determinado mes.");
printf("\n7) Buscar contacto.");
printf("\n8) Borrar contacto.");
printf("\n9) Eliminar Archivos.");
printf("\n10) Salir.");
printf("\n\nElige una opcion: ");
fgets(cadena,10,stdin);
        sscanf(cadena,"%i",&opc);
        //scanf("%d",&opc);
}while (opc<1 || opc>10);
return opc;
}

void mostrarTituloMenu(char *titulo){
system("cls");
    printf("%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(titulo)/2, titulo);
}

void mostrarMensajeCentro(char *msj){
    printf("\n\n\n\n\n%*s\n\n\n", ANCHO_PANTALLA/2 + strlen(msj)/2, msj);
}

void mostrarMensajeAviso(char *msj){
    printf("\n\n%*s\n\n", ANCHO_PANTALLA/2 + strlen(msj)/2, msj);
}

void presUnaTecla(){
mostrarMensajeCentro("Presione ENTER para continuar.");
while(getchar() != '\n');
    setbuf(stdin, NULL);
}


int menu(char *nombreArchivo,char *nombreArchivoIndice, Lista *lista){
int pos,opc,mes;
char car[3],aux;
tipoTablaIndice();
mostrarArchivoIndice(nombreArchivoIndice);
pausarPrograma();
Amigo amigoBuscar;
    do{
opc=mostrarMenu();
    switch (opc){
    case 1:
    if(!agregarAmigo(lista,nombreArchivo)){
mostrarMensajeCentro("Hubo un error. Elemento duplicado");
}else{
printf("\n\nSe ha hecho correctamente");
    ordenar(lista);
}
break;
case 2:
mostrarTituloMenu("AMIGOS EN AREA DE TRANSACCIONES");
if(lista->inicio!=NULL){
tipoTabla();
mostrarDatos(lista);
printf("\n\n\n\n");
}else
mostrarMensajeCentro("Lista Vacia.");
break;
case 3:
if (actualizarArchivo(nombreArchivo,lista)!=false){
formarIndice(nombreArchivo,nombreArchivoIndice);
(destruir(lista)) ? mostrarMensajeAviso("Se actualizo el archivo y se borro la lista.") : mostrarMensajeAviso("Hubo un problema");
}
break;
case 4:
if(tamanioArchivo(nombreArchivo)!=0){
mostrarTituloMenu("AMIGOS EN ARCHIVO");
mostrarAgenda(nombreArchivo);
printf("\n\n\n\n");
}else{
mostrarMensajeCentro("Archivo Vacio.");
}
break;
case 5:
mostrarTituloMenu("AMIGOS POR INICIAL");
do{
                printf("\nIngrese una letra:");
                fgets(car,3,stdin);
                limpiar(car);
                aux = car[0];
            }while((aux <65 || (aux >90 && aux <97)|| aux >122));
            if (aux >96 || aux <123) aux =aux - 32; //Si no es mayuscula, la transforma en mayuscula
            printf("%c",aux);
mostrarApellidoInicialArchivo(nombreArchivo,nombreArchivoIndice,aux);
mostrarApellidoInicialLista(lista,aux);
break;
case 6:
mes=pedirNombreMes();
mostrarTituloMenu("CUMPLEN AÑOS EN EL MES");
            printf("\nDE %s:\n\n",arrMes[mes-1]);
            printf("\n\nAmigos del archivo:\n\n\n");
tipoTabla();
mostrarCumpleMesArchivo(nombreArchivo,mes);
printf("\n\nAmigos del archivo:\n\n\n");
mostrarCumpleMesLista(lista,mes);
break;
case 7:
amigoBuscar=pedirAmigoBuscar();
printf("\nAmigos del archivo:\n\n\n");
tipoTabla();
mostrarBuscadoArchivo(nombreArchivo,amigoBuscar);
printf("\n\n\nAmigos de la lista:\n\n\n");
(lista->inicio!=NULL) ? mostrarBuscadoLista(lista,amigoBuscar) : mostrarMensajeAviso("Lista Vacia.");
break;
case 8:
    mostrarTituloMenu("BORRAR AMIGO");
if((tamanioArchivo(nombreArchivo)==0)&&(lista->inicio==NULL)){
                mostrarMensajeCentro("No hay elementos.");
}else if((tamanioArchivo(nombreArchivo)!=0)&&(lista->inicio==NULL)){
    printf("\nAmigos en el archivo: \n");
                mostrarAgenda(nombreArchivo);
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarMensajeAviso("Lista Vacia");
                printf("Ingrese el numero de contacto: ");
                scanf("%d",&pos);
                if(borrarContactoArchivo(nombreArchivo,pos)) printf("\nSe ha borrado el usuario con exito");
}else if((tamanioArchivo(nombreArchivo)==0)&&(lista->inicio!=NULL)){
    tipoTabla();
    printf("\nAmigos en el archivo: \n");
    mostrarMensajeAviso("Archivo Vacio");
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarDatos(lista);
                printf("Ingrese el numero de contacto: ");
                scanf("%d",&pos);
                borrarContactoLista(lista,pos);
}else{
    //CONTROLAR LOS MAXIMOS Y MINIMOS
    printf("\nAmigos en el archivo: \n");
                mostrarAgenda(nombreArchivo);
                printf("\nAmigos en la lista de Transaccion: \n");
                mostrarDatos(lista);
                int eleccion;
                printf("\n\n\n\n\nDe que lugar quiere eliminar el amigo?");
                printf("\nIngrese \t1.)Agenda. \t2)Transaccion. \t3)Salir\n");
                scanf("%d",&eleccion);
                if (eleccion==1){
                    printf("Ingrese el numero de contacto: ");
                    scanf("%d",&pos);
                    if(borrarContactoArchivo(nombreArchivo,pos)) printf("\nSe ha borrado el usuario con exito");
                }else if(eleccion==2){
                    printf("Ingrese el numero de contacto: ");
                    scanf("%d",&pos);
                    borrarContactoLista(lista,pos);
                }
}
break;
case 9:
remove(nombreArchivo);
remove(nombreArchivoIndice);
mostrarMensajeCentro("Los archivos se borraron efectivamente.");
break;
case 10:
printf ("\nAdios");
break;
}
//
presUnaTecla();
} while (opc!=10);
return 0;
}



int agregarAmigo(Lista *lista,char *nombreArchivo){
Amigo amigo=pedirAmigo();
bool toReturn=true;
if ((estaAmigoLista(lista,amigo)||(estaAmigoArchivo(nombreArchivo,amigo))))
        toReturn=false;
else{
insertarInicio(lista,amigo);
}
return toReturn;
}

void limpiar (char *cadena){
    char *p;
    p = strchr (cadena, '\n');
    if (p){
        *p = '\0';
    }else{
        pausarPrograma();
    }
}

void limpiar2 (char *cadena, int largo)
{
  char *p;
  if(strlen(cadena)>=largo){
      p = strchr (cadena, '\n');
      printf("\nEs p=%s\n",p);
    if (p)
        printf("\nAca entro\n");
        *p = '\0';
  }

}


Amigo pedirAmigo(){
Amigo aux;
system("cls");
mostrarTituloMenu("MENU DE CARGA DE DATOS");
do{
printf("\nIngrese el apellido de su amigo.\n");
        fgets(aux.apellido,20, stdin);
        limpiar(aux.apellido);
}while (strlen(aux.apellido)>17);
do{
printf("\nIngrese el nombre de su amigo.\n");
        fgets(aux.nombre,20, stdin);
        limpiar(aux.nombre);
}while (strlen(aux.nombre)>17);
do{
printf("\nIngrese el email de su amigo.\n");
        fgets(aux.email,20, stdin);
        limpiar(aux.email);
}while (strlen(aux.email)>17);
do{
printf("\nIngrese el celular de su amigo.\n");
        fgets(aux.celular,18, stdin);
        limpiar(aux.celular);
}while (strlen(aux.celular)>15);
printf("\nFecha de nacimiento de su amigo:\n");
aux.fecNac=ingresarFecha();
aux.flag=true;
//mostrarAmigo(aux);
return aux;
}

int esBisiesto(int a){
return (a%4==0 && a%100!=0) || (a%400==0);
}

TFecha ingresarFecha(){
int limDias,busqueda,buffer;
TFecha fecha;
char cadena[10];
do{
printf("\nIngrese el año de nacimiento: [1900..2016]\n");
fgets(cadena,6, stdin);
sscanf(cadena,"%d",&fecha.año);
}while ((fecha.año>2016)||(fecha.año<1900));
limpiar(cadena);
do{
printf("\nIngrese el mes de nacimiento:\n");
fgets(cadena,4,stdin);
sscanf(cadena,"%d",&fecha.mes);
}while ((fecha.mes>12)||(fecha.mes<1));
limDias=(topeDias(fecha.mes,fecha.año));
do{
printf("\nIngrese el dia de nacimiento:[1..%d]\n",limDias);
fgets(cadena,4, stdin);
sscanf(cadena,"%d",&fecha.dia);
}while ((fecha.dia>limDias)||(fecha.dia<1));
return fecha;
}

int topeDias(int mes,int año){
if((mes==1)||(mes==3)||(mes==5)||(mes==7)||(mes==8)||(mes==10)||(mes==12)){
return 31;
}else if((mes==4)||(mes==6)||(mes==9)||(mes==11)){
return 30;
}else if((mes==2)&&esBisiesto(año)){
return 29;
}else{
return 28;
}
}


int estaAmigoLista(Lista *lista,Amigo p){
  bool existe = false;
  Persona *aux;
  for(aux=lista->inicio; aux && !existe; aux=aux->sig){
    existe = (strcmpi(aux->dato.apellido,p.apellido)==0);
    existe &= (strcmpi(aux->dato.nombre,p.nombre)==0);
    existe &= (strcmpi(aux->dato.email,p.email)==0);
    existe &= (strcmpi(aux->dato.celular,p.celular)==0);
    existe &= (aux->dato.fecNac.año==p.fecNac.año);
    existe &= (aux->dato.fecNac.mes==p.fecNac.mes);
    existe &= (aux->dato.fecNac.dia==p.fecNac.dia);
  }
  return existe;
}

//revisa el archivo para ver si encuentra datos
int estaAmigoArchivo(char *nombreArchivo,Amigo p){
FILE *file=fopen(nombreArchivo,"rb");
bool existe =false;
Amigo amigo;
while(!existe && fread(&amigo, sizeof(Amigo), 1, file)){
    existe = (strcmpi(amigo.apellido,p.apellido)==0);
    existe &= (strcmpi(amigo.nombre,p.nombre)==0);
    existe &= (strcmpi(amigo.email,p.email)==0);
    existe &= (strcmpi(amigo.celular,p.celular)==0);
    existe &= (amigo.fecNac.año==p.fecNac.año);
    existe &= (amigo.fecNac.mes==p.fecNac.mes);
    existe &= (amigo.fecNac.dia==p.fecNac.dia);
}
fclose(file);
return existe;
}





int insertarInicio(Lista *lista, Amigo amigo){
  int toReturn = false; // error
  Persona *aux = (Persona *) malloc (sizeof (Persona));
  if (aux != NULL){
    aux->dato=amigo;
    aux->sig=lista->inicio;
    lista->inicio=aux;
    toReturn = true; // error
  }
  return toReturn;
}

void tipoTabla(){
printf("%-4s %-15s %-15s %-15s %-12s %-10s\n\n","NUM","APELLIDO","NOMBRE","EMAIL","CELULAR","DD/MM/AAAA");
}


void mostrarAmigo(Amigo p){
printf("%-2s %-15s %-15s %-15s %-12s %i/%i/%i\n","",p.apellido,p.nombre,p.email,p.celular,p.fecNac.dia,p.fecNac.mes,p.fecNac.año);
}


void mostrarDatos(Lista *lista){
Persona *aux=lista->inicio;
int i=1;
while (aux){
printf(" %i ",i);
mostrarAmigo(aux->dato);
aux=aux->sig;
i++;
}
}


int tamanioLista(Lista *lista){
Persona *aux=lista->inicio;
int cant=0;
while (aux){
mostrarAmigo(aux->dato);
aux=aux->sig;
cant++;
}
return cant;
}

void ordenar(Lista *lista){
Amigo cam;
Persona *aux,*aux2,*min;
min=lista->inicio;
while(min){
aux=min;
aux2=min->sig;
while(aux2!=NULL){
if((strcmpi(aux->dato.apellido,aux2->dato.apellido))>0){ //se comparan apellidos
aux=aux2; //se compara el nombre
}else if(((strcmpi(aux->dato.apellido,aux2->dato.apellido))==0)&&((strcmpi(aux->dato.nombre,aux2->dato.nombre))>0)){
aux=aux2;
}
aux2=aux2->sig;
}
cam=min->dato;
min->dato=aux->dato;
aux->dato=cam;
min=min->sig;
}

}


int destruir (Lista *lista){
    bool toReturn=false;
    while (lista->inicio){
        suprimirInicio (lista);
    }
    if(lista->inicio==NULL) toReturn=true;
    return toReturn;
}



/* eliminación al inicio de la lista */
int suprimirInicio (Lista *lista){
// ¿Por qué -1? si no hace nada lo lógico sería retornar 0, equivalente natural de false
bool   toReturn = false;
if (lista->inicio){
Persona *sig = lista->inicio->sig;
free(lista->inicio);
lista->inicio = sig;
toReturn = true; // ¿Por qué 0? siguiendo el planteamiento análogo debería ser 1
}
return toReturn;
}


int listaArchivo(Lista *lista, char *nombreArchivo){
    bool toReturn=false;
if(lista->inicio){
Persona *aux=lista->inicio;
while (aux){
if(aux->dato.flag){
guardarContacto(aux->dato,nombreArchivo);
aux=aux->sig;
}
}
toReturn=true;
}
return toReturn;
}


int unirListas(Lista *lista,Lista *aux){
    bool toReturn=false;
if(aux){
Persona *recorrer=aux->inicio;
while(recorrer){
insertarInicio(lista,recorrer->dato);
recorrer=recorrer->sig;
}
ordenar(lista);
toReturn=true;
}
return toReturn;
}

int tamanioArchivo(char *nombreArchivo){
FILE *file=fopen(nombreArchivo,"ab");
fseek(file, 0, SEEK_END);
int tamanio=ftell(file)/sizeof(Amigo);
fclose(file);
return tamanio;
}


int actualizarArchivo(char *nombreArchivo,Lista *lista){
bool toReturn=true;
if(tamanioArchivo(nombreArchivo)!=0){
Lista *aux;
if ((aux = (Lista *) calloc (1,sizeof(Lista))) == NULL){
mostrarMensajeCentro("Error de Memoria.");
    toReturn=false;
}
archivoLista(nombreArchivo,aux);
if(remove(nombreArchivo)!=-1){
unirListas(lista,aux); //une, ordena
listaArchivo(lista,nombreArchivo);
destruir(aux);
}
}else if(tamanioArchivo(nombreArchivo)==0){
if (listaArchivo(lista,nombreArchivo)==-1){
mostrarMensajeCentro("No hay elementos para guardar.");
toReturn=false;
}
}
return toReturn;
}

//CORREGIR ESTO

void archivoLista(char *nombreArchivo, Lista *aux){
FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }else{
        Amigo amigo;
        rewind(file);
        while(fread(&amigo, sizeof(Amigo), 1, file)){
            if(amigo.flag){
insertarInicio(aux,amigo);
        }
}
        fclose(file);
    }
}


void guardarContacto(Amigo persona, char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&persona, sizeof(Amigo), 1, file);
        fclose(file);
    }
}


void mostrarAgenda(char* nombreArchivo){
    FILE* file= fopen(nombreArchivo, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    int i=1;
    tipoTabla();
        Amigo persona;
        while (fread(&persona, sizeof(Amigo), 1, file)){
            if(persona.flag){
            printf(" %i ",i);
mostrarAmigo(persona);
i++;
}
        }
        fclose(file);
    }
}


void inicializarIndice(Indice indice[]){
int i;
for (i=0;i<Max;i++){
indice[i].letra=(17+i)+48;
indice[i].pos=-1;
indice[i].cantidad=0;
}
}


int tamanioArchivoIndice(char *nombreArchivoIndice){
FILE *file=fopen(nombreArchivoIndice,"ab");
fseek(file, 0, SEEK_END);
int tamanio=ftell(file)/sizeof(Indice);
fclose(file);
return tamanio;
}


void formarIndice(char *nombreArchivo,char *nombreArchivoIndice){
Indice indice[Max];
inicializarIndice(indice);
Amigo persona;
char inic;
int j=0,encontrado,i=0;
FILE *file=fopen(nombreArchivo,"rb");
while(fread(&persona, sizeof(Amigo), 1, file)){
inic=persona.apellido[0];
if (inic>97 || inic<122) inic=inic-32; //Si no es mayuscula, la transforma en mayuscula
encontrado=0;
while(i<Max && encontrado!=1){
if((indice[i].letra==inic)&&(indice[i].pos==-1)){
indice[i].pos=j;
indice[i].cantidad=indice[i].cantidad+1;
encontrado=1;
}else if((indice[i].letra==inic)&&(indice[i].pos!=-1)){
indice[i].cantidad++;
encontrado=1;
}else{
i++;
}
}
j++;
}
fclose(file);
remove(nombreArchivoIndice);
arregloArchivoIndice(nombreArchivoIndice,indice);
}

void arregloArchivoIndice(char *nombreArchivoIndice,Indice indice[]){
int i;
for (i=0;i<Max;i++){
guardarIndice(nombreArchivoIndice,indice[i]);
}
}

void guardarIndice(char *nombreArchivoIndice,Indice ind){
    FILE* file= fopen(nombreArchivoIndice, "ab");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        fwrite(&ind, sizeof(Indice), 1, file);
        fclose(file);
    }
}


void tipoTablaIndice(){
printf("%-10s %-15s %-15s\n\n","LETRA","POSICION","CANTIDAD");
}

//Muestra uno
void mostrarLetra(Indice ind){
    if(ind.cantidad!=0) printf("%-10c %-15d %-15d\n\n",ind.letra,ind.pos,ind.cantidad);
}

//Muestra el arreglo indice (No se usa, solo era para probar)
void mostrarArregloIndice(Indice indice[]){
int i;
tipoTablaIndice();
for (i=0;i<Max;i++){
mostrarLetra(indice[i]);
}
}

//Muestra el archivo indice (No se usa, solo era para probar)
void mostrarArchivoIndice(char* nombreArchivoIndice){
    FILE* file= fopen(nombreArchivoIndice, "rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
        Indice indice;
        while (fread(&indice, sizeof(Indice), 1, file)){
mostrarLetra(indice);
    }
        fclose(file);
    }
}


//Muestra los contactos dependiendo de la letra inicial
void mostrarApellidoInicialArchivo(char *nombreArchivo,char *nombreArchivoIndice,char c){
c=c-65; //Transforma el caracter en entero
FILE *file=fopen(nombreArchivo,"rb");
if (tamanioArchivo(nombreArchivo)==0){
mostrarMensajeCentro("Archivo Vacio");
fclose(file);
}else{
FILE *fileInd=fopen(nombreArchivoIndice,"rb");
if (fileInd==NULL){
mostrarMensajeCentro("Error al intentar acceder al archivo");
    }else{
Indice ind;
fseek(fileInd,(c)*sizeof(Indice),SEEK_SET);
fread(&ind,sizeof(Indice),1,fileInd);
fclose(fileInd);
mostrarArchivoApellido(nombreArchivo,ind.pos,ind.cantidad);
}
}
}


//Dada una pos y una cantidad, muestra contactos desde una posicion avanzando tanto como cant haya
void mostrarArchivoApellido(char *nombreArchivo,int pos,int cant){
FILE *file=fopen(nombreArchivo,"rb");
    if (file==NULL){
        mostrarMensajeCentro("Error al intentar acceder al archivo\n");
    }
    else{
    int i,elem,numero=1;
    if (cant!=0){
    elem=pos;
    tipoTabla();
    for (i=pos;i<pos+cant;i++){
    Amigo amigo;
    printf(" %d ",numero);
    fseek (file, (elem)*sizeof(Amigo), SEEK_SET);
        fread(&amigo, sizeof(Amigo), 1, file);
mostrarAmigo(amigo);
elem++;
numero++;
}
}else{
mostrarMensajeCentro("No hay amigos con esa inicial.");
}
        fclose(file);
        printf("\n\n");
}
}


void mostrarApellidoInicialLista(Lista *lista, char car){
    Persona *aux=lista->inicio;
    Amigo amigo;
    char inic;
    int i=1;
if(aux){
while (aux){
if(aux->dato.flag){
                amigo=aux->dato;
    inic=amigo.apellido[0];
    if(inic>96 && inic<123) inic=inic-32;
    if(inic==car){
                    printf(" %i ",i);
                    mostrarAmigo(amigo);
                    i++;
    }
                aux=aux->sig;
}
}
    }
}



int borrarContactoArchivo(char *nombreArchivo, int pos){
    bool toReturn=true;
    if((tamanioArchivo(nombreArchivo)<pos)||(pos<1)){
        printf("La posicion indicada es invalida");
        toReturn=false;
    }else{
        FILE *file=fopen(nombreArchivo,"r+b");
        Amigo amigo;
        fseek (file, (pos-1)*sizeof(Amigo), SEEK_SET);
        fread(&amigo, sizeof(Amigo), 1, file);
        mostrarAmigo(amigo);
        presUnaTecla();
        amigo.flag=false;
        fseek (file, -1*sizeof(Amigo), SEEK_CUR);
        fwrite(&amigo,sizeof(Amigo),1,file);
        fclose(file);
    }
    return toReturn;
}

int borrarContactoLista(Lista *lista, int pos){
    Persona *aux=lista->inicio, *elemEliminar;
    bool toReturn=false;
    int i;
    if(pos!=1){
        for(i=1;i<pos-1;i++){
            aux=aux->sig;
        }
        elemEliminar=aux->sig;
        aux->sig=elemEliminar->sig;
        free(elemEliminar);
        toReturn=true;
    }else{
        suprimirInicio(lista);
        toReturn=true;
    }
    return toReturn;
}

void mostrarBuscadoArchivo(char *nombreArchivo,Amigo buscoAmigo){
FILE *file=fopen(nombreArchivo,"rb");
Amigo amigo;
int i=1;
while(fread(&amigo, sizeof(Amigo), 1, file)){
        if (estaApellidONombre(amigo,buscoAmigo)){
            printf(" %i ",i);
            mostrarAmigo(amigo);
            i++;
        }
}
fclose(file);
    if(i==1)mostrarMensajeAviso("No se encontraron amigos con ese nombre y/o apellido");
}

void mostrarBuscadoLista(Lista *lista,Amigo buscoAmigo){
    Persona *aux=lista->inicio;
    int i=1;
while(aux){
        if(estaApellidONombre(aux->dato,buscoAmigo)){
                printf(" %i ",i);
                mostrarAmigo(aux->dato);
                i++;
        }
        aux=aux->sig;
}
if(i==1) mostrarMensajeAviso("No se encontraron amigos con ese nombre y/o apellido");
}

int estaApellidONombre(Amigo amigo, Amigo buscoAmigo){
    bool existe =false;
    existe = (strcmpi(amigo.apellido,buscoAmigo.apellido)==0);
    existe |= (strcmpi(amigo.nombre,buscoAmigo.nombre)==0);
    return existe;
}

Amigo pedirAmigoBuscar(){
    Amigo amigoBuscar;
    do{
printf("\nIngrese el apellido de su amigo.\n");
        fgets(amigoBuscar.apellido,20, stdin);
        limpiar(amigoBuscar.apellido);
}while (strlen(amigoBuscar.apellido)>17);
do{
printf("\nIngrese el nombre de su amigo.\n");
        fgets(amigoBuscar.nombre,20, stdin);
        limpiar(amigoBuscar.nombre);
}while (strlen(amigoBuscar.nombre)>17);
return amigoBuscar;
}


int pedirNombreMes(){
    char mes[12];
    do{
        printf("\nIngrese el nombre: \n");
        fgets(mes,15, stdin);
        limpiar(mes);
    } while ((strlen(mes)>12) || (esMes(mes))==0);
}

int esMes(char *mes){
    int toReturn=-1;
    int i=0;
    while((i<12) && (toReturn==-1)){
        if(strcmpi(arrMes[i],mes)==0){
            toReturn=i+1;
        }
        i++;
    }
    return toReturn;
}

void mostrarCumpleMesLista(Lista *lista,int mes){
    Persona *aux=lista->inicio;
    int i=1;
    while(aux){
        if(aux->dato.fecNac.mes==mes){
            printf(" %i ",i);
            mostrarAmigo(aux->dato);
            i++;
        }
        aux=aux->sig;
    }
}

void mostrarCumpleMesArchivo(char *nombreArchivo,int mes){
    FILE *file=fopen(nombreArchivo,"rb");
    if(file==NULL){
        mostrarMensajeAviso("Hubo un error al abrir el archivo");
    }else{
        Amigo amigo;
        int i=1;
        while(fread(&amigo,sizeof(Amigo),1,file)){
            if(amigo.fecNac.mes==mes){
                printf(" %i ",i);
                mostrarAmigo(amigo);
                i++;
            }
        }
    }
    fclose(file);
}

void pausarPrograma(){
while(getchar() != '\n');
    setbuf(stdin, NULL);
}