Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Temas - Rhessus

#1
¡Hola a todos!
Hace tiempo quería pasarme por acá, pero no encontraba la excusa :P

Tuve que hacer un buscador para el caso de recibir un arreglo de objetos de esta clase:

class Menu {
 id: int
 name: string
 url: string | null
 children: Menu[]
}


Como pueden notar, es multinivel. Y vale aclarar que sólo los objetos sin hijos (hojas, si los vemos como árboles) tendrán un valor distinto de null en el atributo url, el cual permite hacer la redirección.

El buscador muestra únicamente:
(1) Aquel objeto cuyo name cumpla con los valores ingresados
(2) Los hijos de (1), si los tiene
(3) El padre de (1) y sus ascendentes (abuelo, bisabuelo, etc.), hasta el primer nivel.

Mi solución fue muy engorrosa, por lo cual me gustaría saber si hay una forma simple (mas no sencilla) de hacerlo. Cuando tenga más tiempo repaso el código y comento qué hice.

¡Muchas gracias!
#2
Mis agradecimientos de manera especial a AlbertoBSD, por su incondicional ayuda a cada una de mis dudas, y a mi profesora (llamémosla "L", no me gusta dejar información personal de otros en Internet), por su infinita paciencia y ayuda incansable.

Nota: el código es corregible (o sea, no es perfecto... pero prefiero dejarlo así, tal y como lo entregué; con el añadido de una sola aclaración). Para comprender el mismo, es necesario conocimiento básico en C (punteros, arrays, estructuas y memoria dinámica).

Código (bash) [Seleccionar]
/***************************************************************************************************************************/

                  /***  LABORATORIO DE PROGRAMACIÓN II- TRABAJO PRÁCTICO FINAL: AGENDA DE CONTACTOS  ***/                  

/***************************************************************************************************************************/

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

#define N 300  //cantidad de caracteres para el espacio en memoria para las cadenas
#define M 30   //cantidad de caracteres para las cadenas

/***************************************************************************************************************************/

typedef struct direccion{

char calle[N];
char numero[N];

} _direccion;

/***************************************************************************************************************************/

typedef struct contact {

char name[N];
char number[N];
char mail[N];
_direccion address;
struct contact *next;

} Contact;

/***************************************************************************************************************************/

Contact *head = NULL;
Contact *tail = NULL;

/***************************************************************************************************************************/

void imprimirSeparador() { printf("=================================\n"); }

/***************************************************************************************************************************/

void imprimirOpciones() {
   
   imprimirSeparador();
   printf("Agenda\n");
   printf("======\n");
   printf("1. Agregar contacto\n");
   printf("2. Mostrar contactos\n");
   printf("3. Mostrar contactos por letra\n");
   printf("4. Buscar contactos por nombre\n");
   printf("5. Buscar contactos por teléfono\n");
   printf("6. Eliminar contacto por nombre\n");
   printf("7. Eliminar todos los contactos\n");
   printf("8. Salir\n");
   imprimirSeparador();    
   
}

/***************************************************************************************************************************/

//se encarga de leer nombre, teléfono, mail y dirección del contacto que se desea agregar,
//llama a nuevoContactoLista(...) para agregarlo a la lista de ser posible y
//finalmente comunica al usuario el resultado de la operación
void nuevoContacto(){

Contact *new;
new = (Contact *)malloc(sizeof(Contact));

imprimirSeparador();

printf("Contacto nuevo\n");
printf("==============\n");

printf("Nombre: ");
scanf("%s", new->name);

while(strlen(new->name) > M){ //si la cadena es demasiado larga
imprimirSeparador();
printf("El nombre es demasiado largo. Intenta nuevamente con uno más corto.\n");
printf("Nombre: ");
scanf("%s", new->name);
}

printf("Teléfono: ");
scanf("%s", new->number);

while(strlen(new->number) > M){ //si la cadena es demasiado larga
imprimirSeparador();
printf("El número de teléfono es demasiado largo. Intenta nuevamente con uno más corto.\n");
printf("Teléfono: ");
scanf("%s", new->number);
}


printf("Mail: ");
scanf("%s", new->mail);

while(strlen(new->mail) > M){ //si la cadena es demasiado larga
imprimirSeparador();
printf("El mail es demasiado largo. Intenta nuevamente con uno más corto.\n");
printf("Mail: ");
scanf("%s", new->mail);
}

printf("Dirección: ");
scanf("%s%s", new->address.calle, new->address.numero);

while(strlen(new->address.calle) > M || strlen(new->address.numero) > M){ //si la cadena es demasiado larga
imprimirSeparador();
printf("La dirección es demasiado larga. Intenta nuevamente con una más corta.\n");
printf("Dirección: ");
scanf("%s%s", new->address.calle, new->address.numero);
}

imprimirSeparador();

nuevoContactoLista(new->name, new->number, new->mail, new->address.calle, new->address.numero);

free(new);
}

/***************************************************************************************************************************/

//recibe como argumento nombre, teléfono, mail y dirección del contacto que se desea agregar,
//si no existe ningún otro contacto con el mismo nombre lo agrega a la lista
void nuevoContactoLista(char name[], char number[], char mail[], _direccion addressCalle[], _direccion addressNumero[]){

Contact *contactoNuevo, *aux;
contactoNuevo = (Contact *)malloc(sizeof(Contact));

/**********************************************************************/

aux = head;
while(aux != NULL) {
if((strcmp(aux->name, name)) == 0){
printf("El nombre de contacto ingresado ya existe.\n");
return;
}
else{
aux = aux->next;
}
}
if(aux == NULL){
strcpy(contactoNuevo->name, name);
}

/**********************************************************************/

aux = head;
while(aux != NULL) {
if((strcmp(aux->number, number)) == 0){
printf("El número de teléfono ingresado ya existe.\n");
return;
}
else{
aux = aux->next;
}
}
if(aux == NULL){
strcpy(contactoNuevo->number, number);
}

/**********************************************************************/

strcpy(contactoNuevo->mail, mail);

/**********************************************************************/

strcpy(contactoNuevo->address.calle, addressCalle);

/**********************************************************************/

strcpy(contactoNuevo->address.numero, addressNumero);

/**********************************************************************/

contactoNuevo->next = NULL;

/**********************************************************************/

if(head == NULL){
head = contactoNuevo;
}
else{
       tail->next = contactoNuevo;
}

   tail = contactoNuevo;
   printf("La información del contacto ha sido guardada exitosamente.\n");
   
}

/***************************************************************************************************************************/

void imprimirContactos(){

Contact *auxiliar;
int TAM;

imprimirSeparador();

/**********************************************************************/

//TAM = cantidad de contactos

auxiliar = head;

TAM = 0;
while(auxiliar != NULL) {
auxiliar = auxiliar->next;
TAM++;
}

/**********************************************************************/
//Ordenamiento de burbuja: ordena alfabéticamente los contactos
if(head != NULL){
Contact *first = NULL, *second = NULL, *auxi = NULL;

first = head;
while(first != tail){
second = first->next;
while(second != NULL){
if(strcmp(first->name, second->name) > 0){
strcpy(auxi->name, first->name);
strcpy(auxi->number, first->number);
strcpy(auxi->mail, first->mail);
strcpy(auxi->address.calle, first->address.calle);
strcpy(auxi->address.numero, first->address.numero);

strcpy(first->name, second->name);
strcpy(first->number, second->number);
strcpy(first->mail, second->mail);
strcpy(first->address.calle, second->address.calle);
strcpy(first->address.numero, second->address.numero);

strcpy(second->name, auxi->name);
strcpy(second->number, auxi->number);
strcpy(second->mail, auxi->mail);
strcpy(second->address.calle, auxi->address.calle);
strcpy(second->address.numero, auxi->address.numero);
}

second = second->next;
}

first = first->next;
}
}

/**********************************************************************/

auxiliar = head;

printf("Contactos\n");

while(auxiliar != NULL) {
printf("=========\n");
printf("Nombre:    %s\nTeléfono:  %s\nMail:      %s\nDirección: %s %s\n", auxiliar->name, auxiliar->number, auxiliar->mail, auxiliar->address.calle, auxiliar->address.numero);
auxiliar = auxiliar->next;
}

if(TAM == 0){
printf("=========\n");
printf("La agenda está vacía.\n");
}

}

/***************************************************************************************************************************/

//lee la letra con que se quiere que empiecen los nombres de los contactos que se desean imprimir,
//luego le pasa el caracter a la función encargada de imprimirlos
void imprimirContactosLetra(){

char c[1];

imprimirSeparador();

printf("Ingrese la primera letra de los contactos que desea ver: ");
scanf("%s", c);

imprimirContactosLetraLista(c);

}

/***************************************************************************************************************************/

//recibe un caracter e imprime todos los contactos cuyo nombre empieza con ese caracter
void imprimirContactosLetraLista(char c[]){

Contact *aux;
int i;

imprimirSeparador();

printf("Contactos que empiezan con la letra '%s'\n", c);

aux = head;
i = 0;
while(aux != NULL){
if(strncmp(aux->name, c, 1) == 0){
printf("=========\n");
printf("Nombre:    %s\nTeléfono:  %s\nMail:      %s\nDirección: %s %s\n", aux->name, aux->number, aux->mail, aux->address.calle, aux->address.numero);
aux = aux->next;
i++;
}
else{
aux = aux->next;
}
}
if(i == 0){
printf("=========\n");
printf("No hay resultados.\n");
}

}

/***************************************************************************************************************************/

//lee el nombre (o el inicio del mismo) que desea usarse para la búsqueda y se lo pasa a la función encargada de buscar
void buscarContactosNombre(){

char nam[N];

imprimirSeparador();

printf("Ingrese el nombre, o el inicio del mismo, que desea utilizar para la búsqueda de contactos: ");
scanf("%s", nam);

buscarContactosNombreLista(nam);

}

/***************************************************************************************************************************/

//recibe una cadena de caracteres y devuelve los contactos cuyo nombre comienza con dicha cadena
//aclaración: NO debe diferenciar mayúsculas de minúsculas
void buscarContactosNombreLista(char nam[]){

Contact *aux;
int i;

imprimirSeparador();

printf("Contactos relacionados con '%s'\n", nam);

aux = head;

i = 0;
while(aux != NULL){
if(strncasecmp(aux->name, nam, strlen(nam)) == 0){
printf("=========\n");
printf("Nombre:    %s\nTeléfono:  %s\nMail:      %s\nDirección: %s %s\n", aux->name, aux->number, aux->mail, aux->address.calle, aux->address.numero);
aux = aux->next;
i++;
}
else{
aux = aux->next;
}
}

if(i == 0){
printf("=========\n");
printf("No hay resultados.\n");
}

}

/***************************************************************************************************************************/

//lee el teléfono (o el inicio del mismo) que desea usarse para la búsqueda y se lo pasa a la función encargada de buscar
void buscarContactosTelefono(){

char num[N];

imprimirSeparador();

printf("Ingrese el teléfono, o el inicio del mismo, que desea utilizar para la búsqueda de contactos: ");
scanf("%s", num);

buscarContactosTelefonoLista(num);

}

/***************************************************************************************************************************/

//recibe un teléfono (o parte de él) y devuelve los contactos cuyo teléfono empieza con ese número
void buscarContactosTelefonoLista(char num[]){

Contact *aux;
int i;

imprimirSeparador();

printf("Contactos cuyo teléfono está relacionado con '%s'\n", num);

aux = head;
i = 0;
while(aux != NULL){
if(strncmp(aux->number, num, strlen(num)) == 0){
printf("=========\n");
printf("Nombre:    %s\nTeléfono:  %s\nMail:      %s\nDirección: %s %s\n", aux->name, aux->number, aux->mail, aux->address.calle, aux->address.numero);
aux = aux->next;
i++;
}
else{
aux = aux->next;
}
}

if(i == 0){
printf("=========\n");
printf("No hay resultados.\n");
}

}

/***************************************************************************************************************************/

//lee el nombre del contacto que se desea eliminar, solicita la confirmación del usuario,
//llama a eliminarContactoNombreLista(...) la cual borra el contacto si es que existe y
//finalmente comunica al usuario el resultado de la operación
void eliminarContactoNombre(){

Contact *aux = head;
int i = 0;
char nom[N];
int opc;

imprimirSeparador();

printf("Ingrese el nombre del contacto que desea eliminar: ");
scanf("%s", nom);

imprimirSeparador();

while(aux != NULL){
if(strcmp(aux->name, nom) == 0){
i++;
printf("¿Está seguro de querer eliminar a '%s' de la agenda?\n", nom);
printf("1. Sí\n");
printf("2. No\n");

imprimirSeparador();

scanf("%d", &opc);

switch(opc) {

case 1:
eliminarContactoNombreLista(nom);
break;
case 2:
return;
break;
default:
break;
}
if(opc == 1){
imprimirSeparador();
printf("El contacto '%s' ha sido borrado de la agenda.\n", nom);
}
break;
}
else{
aux = aux->next;
}
}

if(i == 0){
printf("No existe ningún contacto con el nombre '%s'.\n", nom);
}

}

/***************************************************************************************************************************/

//recibe un nombre, si existe algún contacto en la lista con ese nombre lo borra
void eliminarContactoNombreLista(char nom[]){

Contact *aux_borrar;
Contact *anterior = NULL;

aux_borrar = head;

while(strcmp(aux_borrar->name, nom) != 0){ //mientras el nombre no coincida con el nombre del contacto
anterior = aux_borrar; //se pasará al siguiente contacto
aux_borrar = aux_borrar->next;
}

//salir del while significa que se encontró el contacto cuyo nombre coincide con el ingresado

if(aux_borrar->next != NULL){ //si el contacto ha ser eliminado NO es el ÚLTIMO
if(aux_borrar != head){ // si el contacto no es el primero
anterior->next = aux_borrar->next; //su anterior seguirá a su sucesor
free(aux_borrar); //y el contacto será eliminado
}
else{ //si el contacto ES el PRIMERO
head = aux_borrar->next; //el segundo se convertirá en el primero
free(aux_borrar); //y el contacto será eliminado
}
}
else{ //aux_borrar->next = NULL //si el contacto ha ser eliminado ES el ÚLTIMO
if(aux_borrar != head){ //y si no es el primero (hay más contactos)
anterior->next = NULL; //su anterior seguirá a NULL
free(aux_borrar); //el contacto será eliminado
tail = anterior; //y el anterior se convertirá en el último
}
else{ //si el contacto es el único (ES el PRIMERO y el ÚLTIMO)
free(aux_borrar); //será eliminado
head = NULL;
tail = NULL;
}
}

}

/***************************************************************************************************************************/

//solicita la confirmación del usuario antes de borrar todos los contactos,
//en caso de obtenerla llama a eliminarTodosContactosLista(...) y
//finalmente muestra un mensaje apropiado
void eliminarTodosContactos(){

imprimirSeparador();

printf("¿Está seguro de querer eliminar todos los contactos de la agenda?\n");
printf("1. Sí\n");
printf("2. No\n");

imprimirSeparador();

submenuTodosContactos();

}          

/***************************************************************************************************************************/

//sub-menú de la función eliminarTodosContactos()
void submenuTodosContactos(){

Contact *auxil;
int op;

int i;

auxil = head;

i = 0;
while(auxil != NULL) {
auxil = auxil->next;
i++;
}

scanf("%d", &op);

switch(op) {
       
           case 1:
               eliminarTodosContactosLista();
               break;
           case 2:
               return;
           default:
               break;
       }
       
       imprimirSeparador();
       
       if(i != 0){
printf("Todos los contactos de la agenda han sido borrados.\n");
}
       else {
printf("No existen contactos en la agenda.\n");
}
}

/***************************************************************************************************************************/

//se encarga de borrar todos los nodos de la lista
void eliminarTodosContactosLista(){

   Contact *con;

   if(head != NULL) {
while(1) {
       con = head;
       head = head->next;
       free(con);
   }
   
tail = NULL;
}

}

/***************************************************************************************************************************/

//liberar memoria al salir
void liberarMemoria(){

imprimirSeparador();

printf("Programa cerrado.\n");

imprimirSeparador();

eliminarTodosContactosLista();

}

/**************************************************  FUNCIÓN MAIN()  *******************************************************/

int main() {

   int opcion;

   while(1) {
       
       imprimirOpciones();
       
       scanf("%d", &opcion);
       //while(getchar() != '\n'); acá debería limpiar el buffer para que no caiga en bucle infinito si se iingresa una letra, pero por algún motivo no me funcionó
correctamente cuando lo utilicé

       switch(opcion) {
       
           case 1:
               nuevoContacto();
               break;
           case 2:
               imprimirContactos();
               break;
           case 3:
               imprimirContactosLetra();
               break;
           case 4:
               buscarContactosNombre();
               break;
           case 5:
               buscarContactosTelefono();
               break;
           case 6:
               eliminarContactoNombre();
               break;
           case 7:
               eliminarTodosContactos();
               break;
           case 8:
               liberarMemoria();
               return 0;
           default:
               break;
       }
       
       
   }

}

/***************************************************************************************************************************

    by: Nahuel

***************************************************************************************************************************/
#3
Hola a todos.
A punto de terminar la bendita agenda de contactos, me encuentro con el problema que espero sea el último de esta magnitud: mi programa devuelve un error (violación de segmento) después de eliminar el último nodo.
Les comparto el código pertinente:

Código (bash) [Seleccionar]


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

#define N 30 //cantidad de caracteres para las cadenas

typedef struct contact {

char name[N];
char number[N];
char mail[N];
char address[N];
struct contact *next;

} Contact;

/***************************************************************************************************************************/

Contact *head = NULL;
Contact *tail = NULL;

/***************************************************************************************************************************/

void eliminarContactoNombre(){

        Contact *aux = head;
int i = 0;
char nom[N];
int opcion;

imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

printf("Ingrese el nombre del contacto que desea eliminar: ");
scanf("%s", nom);

printf("\n");
imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

while(aux != NULL){
if(strcmp(aux->name, nom) == 0){ //si el nombre del contacto coincide con el nombre ingresado
i++; //el contador suma uno
printf("¿Está seguro de querer eliminar a '%s' de la agenda?\n", nom);
printf("1. Sí\n");
printf("2. No\n");

imprimirSeparador(); //imprime una linea y un enter para ordenar el texto

scanf("%d", &opcion);

switch(opcion) {

case 1:
eliminarContactoNombreLista(nom); //funcion que borra el contacto y ordena la lista para que el anterior apunte al siguiente del nodo eliminado
break;
case 2:
main();
break;
default:
break;
}

if(opcion == 1){
imprimirSeparador(); //imprime una linea y un enter para ordenar el texto
printf("El contacto '%s' ha sido borrado de la agenda\n", nom);
}
break;
}

else{      //en caso de que el nombre del contacto no coincida con el ingresado
aux = aux->next;   //pasa al siguiente contacto
}
}

if(i == 0){ //si no se encontro´ ningun contacto con el nombre ingresado, el contador es igual a 0
printf("No existe ningún contacto con el nombre '%s'\n", nom);
}

}

/***************************************************************************************************************************/

void eliminarContactoNombreLista(char nom[]){

Contact *aux_borrar;
Contact *anterior = NULL;

aux_borrar = head;

while(aux_borrar != NULL && strcmp(aux_borrar->name, nom) != 0){ //
anterior = aux_borrar;
aux_borrar = aux_borrar->next;
}
if(anterior == NULL){
head = head->next;
free(aux_borrar);
}
else{
anterior->next = aux_borrar->next;
free(aux_borrar);
}
}


Espero puedan ayudarme. Muchas gracias.
Saludos. Nahuel.
#4
Hola a todos.
Continuando con la agenda en C, ahora estoy buscando la forma de ordenar alfabéticamente los contactos (utilizando únicamente las librerías stdio.h, stdlib.h y string.h). Investigué sobre el tema, y reconozco que aprendí algoritmos básicos de ordenamiento que desconocía: ordenamiento burbuja, de inserción, etc. Al parecer, el que resulta más conveniente para listas enlazadas es el de ordenamiento por mezcla. Sin embargo, vuelvo a chocarme contra la pared: por más que intento, no encuentro la forma de "convertirlo" al caso (todos los ejemplos que encuentro son con elementos de una lista, y no con listas enlazadas; en otros casos, son códigos de otro lenguaje).
¿Alguien podría guiarme?
Muchas gracias por su tiempo. Saludos.
#5
Hola a todos.
Estoy haciendo una agenda en C, pero hay un error que no puedo llegar a vislumbrar.


Código (bash) [Seleccionar]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct contact {
char name[20];
char number[20];
char mail[20];
char address[20];
struct contact *next;
} Contact;

Contact *head = NULL;
Contact *tail = NULL;

void imprimirSeparador() { printf("=================================\n"); }

void imprimirOpciones() {
   
   imprimirSeparador();
   printf("Agenda\n");
   printf("======\n");
   printf("1. Agregar contacto\n");
   printf("2. Mostrar contactos\n");
   imprimirSeparador();    
}

void nuevoContacto(){
Contact *new;
new = (Contact *)malloc(sizeof(Contact));

printf("Nombre: ");
scanf("%s", new->name);

printf("Número: ");
scanf("%s", new->number);

printf("Mail: ");
scanf("%s", new->mail);

printf("Dirección: ");
scanf("%s", new->address);
       
   nuevoContactoLista(new->name, new->number, new->mail, new->address);
}

void nuevoContactoLista(char name[], char number[], char mail[], char address[]){

Contact *contactoNuevo, *aux;
contactoNuevo = (Contact *)malloc(sizeof(Contact));

aux = head;
if(aux != NULL){
while(aux != NULL) {
if((strcmp(aux->name,name))==0){
printf("El nombre de contacto ingresado ya existe.\n");
printf("1. Intentar con otro nombre.\n");
printf("2. Volver al menú.\n");
submenu1();
}
else{
aux = aux->siguiente;
}
}
}
else{
strcpy(contactoNuevo->name, name);
}

       aux = head;
if(aux != NULL){
while(aux != NULL) {
if((strcmp(aux->number,number))==0){
printf("El número de teléfono ingresado ya existe.\n");
printf("1. Intentar con otro número.\n");
printf("2. Volver al menú.\n");
submenu1();
}
else{
aux = aux->siguiente;
}
}
}
else{
strcpy(contactoNuevo->number, number);
}

       strcpy(contactoNuevo->mail, mail);

       strcpy(contactoNuevo->address, address);

       contactoNuevo->next = NULL;

/***************************************/

if(head==NULL){
head = contactoNuevo;
printf("La información del contacto ha sido guardada exitosamente.\n");
}

else{
aux = head;
while(aux->next != NULL) {
aux = aux->next;
}
aux->next = contactoNuevo;
printf("La información del contacto ha sido guardada exitosamente.\n");
}
}

void submenu1(){
int opcion;
       
       scanf("%d", &opcion);
       
       switch(opcion) {
       
           case 1:
               nuevoContacto();
               break;
           case 2:
               int main();
               break;
           default:
               break;
       }
}

void imprimirContactos(){
Contact *auxiliar;
auxiliar = head;

printf("Contactos:\n");
if(auxiliar != NULL){
while(auxiliar != NULL) {
printf("%s\t%s\t%s\t%s\n", auxiliar->name, auxiliar->number, auxiliar->mail, auxiliar->address);
auxiliar = auxiliar->siguiente;
}
}
else{
printf("Agenda vacía.\n");
}
}

int main() {

   int opcion;

   while(1) {
       
       imprimirOpciones();
       
       scanf("%d", &opcion);
       
       switch(opcion) {
       
           case 1:
               nuevoContacto();
               break;
           case 2:
               imprimirContactos();
               break;
           default:
               break;
       }
   }
}


Hay dos cosas particulares en el ejercicio: no pueden haber dos contactos que tengan el mismo nombre o número de teléfono, y es necesario que la información almacenada en nuevoContacto() pase a nuevoContactoLista().

Mi problema: no entiendo por qué no identifica la repetición cuando ingreso dos nombres de contacto iguales, además de no realizar ninguna acción al seleccionar la segunda opción.

Muchas gracias por su tiempo y esfuerzo.