Sigue siendo un poco lío ese código... Las funciones tienen que tener un valor de retorno aunque este sea void, la función main() está vacía, es difícil seguir con precisión la ejecución si se va pasando de función en función, algunas funciones hacen demasiadas cosas...
Te pongo una estructura alternativa para que la rellenes:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// Declara constantes para los numeros que vayas a usar luego. Si siguen algun patron que poner de nombre para recordarlos mejor, usalo.
// Si las longitudes que utilizas estan fundamentadas en algo no dire nada pero si son aleatorias te recomiendo que utilices una para todo. O las minimas necesarias, por ejemplo: LONG_NOMBRE y LONG_OTRAS_CADENAS o lo que mas te convenza
#define LONG_NOMBRE 20
#define LONG_OTRAS_CADENAS 15
#define MAX_CONTACTOS 30
// Crea un tipo de dato Contacto que consta de un struct. Los campos es mejor poner uno por linea.
// Si no quieres usar typedef cambialo por struct Contacto {...} pero tendras que usar "struct Contacto" cada vez que quieras hacer referencia a "Contacto"
typedef struct {
int numeroRegistrado; // Este campo no podras relacionarlo con el numero de contactos porque al borrar uno se produciran saltos y se repetiran valores.
//int activo; // Por lo que veo lo usas para determinar si el numero esta borrado o no. Para este codigo es prescindible, ya lo veras.
int telefono; // Dudo que realmente necesites un long para un telefono asi que usare int durante todo el codigo
char nombre[LONG_NOMBRE];
char apellidoPaterno[LONG_NOMBRE]; // Que no te de miedo poner nombres un poco largos. Cuanto mejor se entienda, mejor
char apellidoMaterno[LONG_NOMBRE];
//...
} Contacto; // No declares el array global
int main(){
Contacto contactos[MAX_CONTACTOS]; // Declara el array local
int contactosRegistrados = 0;
int telefonoBuscado;
int indiceBuscado;
int opcion;
do {
opcion = mostrarMenu(); // Muestra el menu y devuelve la opcion. En mostrarMenu() puedes controlar que la opcion este en el rango
switch(opcion){
case 1:
if(contactosRegistrados < MAX_CONTACTOS){
contactos[contactosRegistrados] = crearContacto(); // Crea un contacto en el array contactos en la posicion contactosRegistrados
++contactosRegistrados;
} else printf("Limite de contactos alcanzado\n"); break;
case 2: // Cuando actualizas es como si creases un contacto nuevo en la posicion del existente
printf("Introduce el numero de telefono del contacto a modificar: "); scanf("%d", &telefonoBuscado
); indiceBuscado = buscarPorTelefono(contactos, contactosRegistrados, telefonoBuscado); // Que devuelva el indice del contacto con ese numero o -1 si no lo encuentra
if(indiceBuscado != -1){
contactos[indiceBuscado] = crearContacto();
} else printf("No existe ningun contacto con ese numero\n"); break;
case 3: // Para borrar de un array lo que se hace es mover todos los elementos a la derecha del eliminado una posicion hacia la izquierda para no dejar huecos
printf("Introduce el numero de telefono del contacto a eliminar: "); scanf("%d", &telefonoBuscado
); indiceBuscado = buscarPorTelefono(contactos, contactosRegistrados, telefonoBuscado); // Que devuelva el indice del contacto con ese numero o -1 si no lo encuentra
if(indiceBuscado != -1){
eliminarContacto(contactos, contactosRegistrados, indiceBuscado); // Que empiece en indiceBuscado y hasta el final mueva cada contactos a su izquierda
--contactosRegistrados;
} else printf("No existe ningun contacto con ese numero\n"); break;
}
mostrarContactos(contactos, contactosRegistrados);
} while(opcion != 4); // La opcion 4 solo sale. No es necesario hacer un case para ella.
// Para hacer una pausa olvidate de getch() y de system("pause"). La mejor opcion SIEMPRE es getchar() que pertenece a <stdio.h> asi que olvidate de <conio.h>
return 0;
}
Como ves, la función main() tiene que dar una idea general del funcionamiento del programa. Que al mirar el main() puedas saber lo que hace el programa aunque no sepas cómo (esto corresponde a las funciones adicionales).
Crea funciones estructuradas, no que se llamen unas a otras haciendo bucles o que tengan varios return (hay casos excepcionales pero son pocos).
Ahora te queda a ti implementar las funciones que he ido llamando por ahí. Créalas de forma que cumplan las restricciones que te pongo y todo funcionará correctamente. Observa también los parámetros que tienen que tener y sus valores de retorno. Y limítate a que cada función realice su labor, no quieras mezclar. Cuanto más precisa sea una función más independiente será y más la podrás reutilizar (fíjate en buscarPorTelefono() o crearContacto() como las hemos podido usar varias veces).
Casi lo olvido: para solucionar el tema del numeroRegistro de cada contacto, puedes crear dentro de la función crearContacto() una variable static. Las variables static mantienen su existencia y su valor durante las diferentes llamadas a la función. Así cada vez que llames a la función puedes incrementar en 1 esa variable y en la siguiente llamada, se mantendrá ese valor para volver a incrementarle 1.
Ya tienes bastante trabajo. Y te aseguro si te sirve de inspiración que vas a aprender/reforzar bastantes cosas de hacer este programa. Dos consejos más para que por favor apliques y te quede ya un programa de 10, te lo aseguro:
- Leer cadenas de texto: Para esto la función recomendada es fgets(). Por ejemplo, para guardar el nombre (que te hará falta):
Contacto contacto;
printf("Introduce el nombre: "); fgets(contacto.
nombre, LONG_NOMBRE
, stdin
);
Una vez guardado el nombre es importante hacer dos cosas más: eliminar el salto de línea que se habrá almacenado al pulsar ENTER y limpiar el buffer para el siguiente dato que pidamos. Para hacer ambas cosas utiliza el siguiente código justo después del fgets():
if(contacto.
nombre[strlen(contacto.
nombre)-1] == '\n') // Si antes del final de cadena hay un salto de linea... contacto.
nombre[strlen(contacto.
nombre)-1] = '\0'; //... lo sustituimos por el final de cadena para eliminarloelse // sino, el salto de linea se ha quedado en el buffer ademas de que puede haber otros caracteres antes...
while(getchar() != '\n'); // ...entonces con esto limpiamos el buffer en caso de que quede algo
Como puedes ver en las funciones scanf() de más arriba también he utilizado la misma sentencia para limpiar el buffer pero en ese caso sin la comprobación del if pues el scanf() siempre deja el ENTER en el buffer.
Esta es una manera más correcta de limpiar el buffer que con fflush(stdin). Utilízalo.
Cualquier duda, problema o lo que sea que tengas, no dudes en preguntar. El objetivo es que entiendas lo que se hace y por qué.
Suerte.