[C] Rubrica telefonica

Pubblicità

Awenega_

Utente Attivo
Messaggi
198
Reazioni
26
Punteggio
49
Salve, ho un problema con questo esercizio scritto in C.
Si realizzi un programma in linguaggio C in grado di gestire una rubrica di nomi e numeritelefonici. La rubrica deve contenere fino a 100 voci diverse. Ciascuna voce è composta daun nome (max 40 caratteri) e da un numero di telefono (max 20 caratteri).Il programma deve fornire all’utente un menù di scelta, con le seguenti voci:
1) Aggiungi nuova voce in rubrica
2) Ricerca esatta per nome
3) Ricerca approssimata per nome
4) Stampa completa rubrica
0) Esci dal programmaUna volta che l’utente ha scelto l’operazione desiderata (1-4), il programma acquisirà idati necessari dall’utente ed eseguirà il comando.
Nota: nella rubrica non possono esisteredue voci con lo stesso nome.

Il codice che ho scritto è questo:

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


#define MAXN 21
#define MAXL 41
#define MAXV 100


int main () {


  char nome[MAXV][MAXL], numero[MAXV][MAXN], ricerca[MAXL];


  int n, i, g, flag;


  do {


    i = 1;
    flag = 0;


    printf("1) Aggiungi nuova voce in rubrica\n");
    printf("2) Ricerca esatta per nome\n");
    printf("3) Ricerca approssimata per nome\n");
    printf("4) Stampa completa rubrica\n");
    printf("0) Esci dal programma\n");


    printf("Digitare il numero dell'operazione da eseguire\n");
    scanf("%d", &n);


    if(n<0 || n>4)
      printf("L'operazione digitata non e' disponibile\n");


    else {


      switch(n) {


        case 1 :


          if(i>MAXV-1)
            printf("Spazio insufficiente\n");


          else {


            printf("Inserire il nome da memorizzare massimo 40 caratteri\n");
            fgets(nome[i], 40, stdin);


            nome[i][strlen(nome[i])-1] = 0;


            if(strlen(nome[i])<1)
              printf("Nome non valido\n");


            else {


              for(g=1; g<i; g++)
                if(strcmp(nome[g], nome[i])==0)
                  flag = 1;


              if(flag==1)
                printf("Il nome digitato e' gia' presente nella rubrica\n");


              else {


                printf("Inserire il numero telefonico corrispondente massimo 20 caratteri\n");
                fgets(numero[i], 20, stdin);


                numero[i][strlen(numero[i])-1] = 0;


                if(strlen(numero[i])<1)
                  printf("Numero non valido\n");
                else
                  i++;


              }


            }


          }


          flag = 0;


          break;


        case 2 :


          printf("Digitare il nome da cercare in rubrica\n");
          fgets(ricerca, 40, stdin);


          ricerca[strlen(ricerca)-1] = 0;


          for(g=1; g<=i; g++) {


            if(strcmp(nome[g], ricerca)==0) {


              printf("Il numero di %s e' %s\n", ricerca, numero[g]);


              break;


            }


            if(g=1 && strcmp(nome[g], ricerca)!=0)
              printf("Il nome %s non e' presente nella rubrica\n", ricerca);


          }


          break;


        case 3 :


          printf("Digitare la parte di nome da cercare\n");
          fgets(ricerca, 40, stdin);


          ricerca[strlen(ricerca)-1] = 0;


          for(g=1; g<=i; g++)
            if(strstr(nome[g], ricerca)) {


              printf("%s %s\n", nome[g], numero[g]);


              flag = 1;


            }


          if(flag==0)
            printf("Non esiste nessun nome in rubrica con la sequenza di lettere %s\n", ricerca);


          flag = 0;


          break;


        case 4 :


          for(g=1; g<=i; g++)
            printf("%s %s\n", nome[g], numero[g]);


          if(strlen(nome[i-1])==0)
            printf("Non e' memorizzato nessun numero in rubrica\n");


          break;


      }


    }


  } while(n!=0);


  return 0;


}

In pratica il programma è fatto in modo che l'utilizzatore digiti il comando da eseguire.Il programma continua a girare finchè l'utilizzatore non digita 0, ovvero il numero corrispondente al comando di arresto del programma. Il comando 1 fa aggiungere un numero in rubrica e il suo nome corrispondente.Il programma è fatto in modo tale che se il nome non ha lettere(cioè premi invio e basta) no ti lascia inserire il numero corrispondente e termina il comando lasciandotene inserire un altro.
Non so perchè, però, il programma no mi lasci memorizzare il nome e mi dica cgia che ha zero caratteri.

- - - Updated - - -

Taggo un pochino di gente ç_ç @Falco75 , @Ico Bellungi,
@arcidiacof
 
Allora, innanzitutto anzichè usare vettori per immagazzinare i dati, ti conviene creare una semplice struct che contiene il numero di telefono e il char* che sarà il puntatore al nome del contatto.
Punto secondo, gestire i contatti puoi o creare un vettore di puntatori alle struct, che allocherai dinamicamente, oppure puoi semplicemente usare una SCL lineare e scorrerla ricorsivamente, come preferisci.
Per aggiungere un contatto, in qualsiasi caso, ti basterà fare:
1) malloc per allocare una nuova struct
2) Salvi il numero, che è un valore già allocato perché di tipo intero all'interno della struct
3) Usa una gets o quello che vuoi per ricavare la stringa del nome ed assegnala al puntatore char* nella struct

Dimmi se ti ci ritrovi, altrimenti ti butto giù il codice :)

EDIT:
Ho visto l'errore comunque, ma prima di correggerlo è meglio se decidi l'approccio migliore da usare per gestire la rubrica, altrimenti perdi tempo a sistemare una cosa che in partenza non è quella migliore

EDIT2:
A prescindere comunque, non usare mai grandi quantità di dati preallocati, cioè in modo statico, soprattutto se globali, sprechi solo stack. Cerca sempre di allocare tutto dinamicamente.
E per i numeri usa un unsigned int anziché un vettore di char, useresti solo 8 byte per il numero anziché 1 byte per ogni cifra, non ti conviene.
 
Ultima modifica:
Ogni volta una malloc per allocare un nuovo dato? Va bene fare i sovversivi ma qui mi sembra sia giusto un po' esagerata la soluzione
 
Ogni volta una malloc per allocare un nuovo dato? Va bene fare i sovversivi ma qui mi sembra sia giusto un po' esagerata la soluzione

Non vedo il problema, ci vuole manco una riga per allocare una struct in modo dinamico, e sicuramente è 1000 volte più efficiente di allocare tutta quella roba in anticipo :sisi:

Fra l'altro a giudicare dal codice che ha postato, mi sembra che non sia molto pratico di C, quindi usando allocazione dinamica e ricorsione avrebbe solo fatto pratica, che è sempre una cosa positiva :)

EDIT:
Ti sto buttando io giu' il codice visto che non ho nulla da fare :lol:
 
Ultima modifica:
Non vedo il problema, ci vuole manco una riga per allocare una struct in modo dinamico, e sicuramente è 1000 volte più efficiente di allocare tutta quella roba in anticipo :sisi:

Fra l'altro a giudicare dal codice che ha postato, mi sembra che non sia molto pratico di C, quindi usando allocazione dinamica e ricorsione avrebbe solo fatto pratica, che è sempre una cosa positiva :)

EDIT:
Ti sto buttando io giu' il codice visto che non ho nulla da fare :lol:

Ti ringrazio tantissimo dell'aiuto. Esattamente come hai immaginato, è da poco che studio il C... Non sono molto pratico con la funzione malloc, la conosco ma per il momento preferisco allocare tutto in modo statico per evitare casini di memory leak, oltre a questa scelta che so essere poco conveniente, mi sai dire quale sia il problema principale? ç_ç
 
Ultima modifica:
Fatto, alla fine l'ho riscritto da capo :lol:
Ho usato una struttura collegata lineare per gestire la rubrica, così si può allungare senza problemi e se anche volessi rimuovere contatti potresti farlo tranquillamente in futuro.
Ho implementato l'aggiunta di contatti, la stampa della rubrica e la ricerca semplice, se ti serve aggiungi te la ricerca approssimata e i vari controlli (non ho perso tempo a controllare che il nome inserito fosse abbastanza corto, ecc).
Vedi se ti bastano le cifre del numero intero, altrimenti passa all'unsigned long.

Il codice l'ho messo tutto qui, ho aggiunto anche il metodo che uso sempre per pulire lo schermo, così viene più ordinato :)

[C] Rubrica telefonica - Pastebin.com

Se ti servono spiegazioni o chiarimenti chiedi pure :ok:

Sergio :D
 
Fatto, alla fine l'ho riscritto da capo :lol:
Ho usato una struttura collegata lineare per gestire la rubrica, così si può allungare senza problemi e se anche volessi rimuovere contatti potresti farlo tranquillamente in futuro.
Ho implementato l'aggiunta di contatti, la stampa della rubrica e la ricerca semplice, se ti serve aggiungi te la ricerca approssimata e i vari controlli (non ho perso tempo a controllare che il nome inserito fosse abbastanza corto, ecc).
Vedi se ti bastano le cifre del numero intero, altrimenti passa all'unsigned long.

Il codice l'ho messo tutto qui, ho aggiunto anche il metodo che uso sempre per pulire lo schermo, così viene più ordinato :)

[C] Rubrica telefonica - Pastebin.com

Se ti servono spiegazioni o chiarimenti chiedi pure :ok:

Sergio :D

Grazie mille, gentilissimo :)
 
Nel tuo, non si vede una free neanche a pagarla oro. Deformazione personale lavoro in sistemi embedded a 128kb di RAM quindi sono abiutati a vederli.
P.S. utilizzare la windows.h è un punio negli occhi allo standard
 
La windows.h la uso solo per comodità per pulire lo schermo, se devi fare un esercizio su Windows come nel suo caso, non gli serve certo creare un programma che sia per forza multipiattaforma.
E se volesse, basta cancellare quel metodo e finisce lì, la libreria non la uso in nessun punto fondamentale :)

Per quanto riguarda le free, a che gli servirebbero in questo caso?
Deve creare una rubrica senza dover cancellare contatti, non c'è niente di allocato che gli serve rimuovere mentre il programma resta in esecuzione :oogle:
Sono assolutamente d'accordo con te sul fatto che le free vadano usate sempre, ma in questo caso non vedo proprio dove uno le possa mettere :lol:
 
Fatto, alla fine l'ho riscritto da capo :lol:
Ho usato una struttura collegata lineare per gestire la rubrica, così si può allungare senza problemi e se anche volessi rimuovere contatti potresti farlo tranquillamente in futuro.
Ho implementato l'aggiunta di contatti, la stampa della rubrica e la ricerca semplice, se ti serve aggiungi te la ricerca approssimata e i vari controlli (non ho perso tempo a controllare che il nome inserito fosse abbastanza corto, ecc).
Vedi se ti bastano le cifre del numero intero, altrimenti passa all'unsigned long.

Il codice l'ho messo tutto qui, ho aggiunto anche il metodo che uso sempre per pulire lo schermo, così viene più ordinato :)

[C] Rubrica telefonica - Pastebin.com

Se ti servono spiegazioni o chiarimenti chiedi pure :ok:

Sergio :D
Ripensandoci, essendo un esercizio su matrici e vettori di stringhe, apparte l'ottimizzazione del programma che hai spiegato in modo chiarissimo, qual é il problema del mio codice?
 
Fatto, alla fine l'ho riscritto da capo :lol:
Ho usato una struttura collegata lineare per gestire la rubrica, così si può allungare senza problemi e se anche volessi rimuovere contatti potresti farlo tranquillamente in futuro.
Ho implementato l'aggiunta di contatti, la stampa della rubrica e la ricerca semplice, se ti serve aggiungi te la ricerca approssimata e i vari controlli (non ho perso tempo a controllare che il nome inserito fosse abbastanza corto, ecc).
Vedi se ti bastano le cifre del numero intero, altrimenti passa all'unsigned long.

Il codice l'ho messo tutto qui, ho aggiunto anche il metodo che uso sempre per pulire lo schermo, così viene più ordinato :)

[C] Rubrica telefonica - Pastebin.com

Se ti servono spiegazioni o chiarimenti chiedi pure :ok:

Sergio :D

Un dubbio l'avrei io,ho studiato informatica e ora sto cercando di rinfrescare le mie conoscenze per cui spero che non ti darà fastidio spiegare anche a me qualcosa...:)
Nel main secondo me c'è un problema,perchè ponendo la condizione
if ((scelta > 0) && (scelta < 4)) {
clear_screen();
}


se subito dopo ci metti lo switch sulla variabile scelta significa che nel momento in cui ad esempio viene inserito 5 lui comunque entra nello switch e cerca di trovare il caso equivalente per quel numero e si bugga,è così o sbaglio? (non voglio fare il professorino voglio solo cercare di capire se il mio dubbio è lecito :) )
 
Ripensandoci, essendo un esercizio su matrici e vettori di stringhe, apparte l'ottimizzazione del programma che hai spiegato in modo chiarissimo, qual é il problema del mio codice?

Se ti riferisci solo alle matrici, il tuo codice non aveva un problema, era solo scomodo da usare, perché per ogni contatto avresti dovuto accedere a 2 matrici insieme, e meno efficiente, perché avresti inizializzato tutto all'avvio del programma. Le strutture collegate lineari in C sono l'equivalente delle liste che trovi nei linguaggi orientati agli oggetti, e di solito sono preferibili nei casi, come questo, in cui devi gestire un vettore di dati che sia di lunghezza variabile. Questo ripeto, sempre se vuoi evitare di preallocare tutto già in partenza.
Per il resto il mio appunto era su questo, ma sul tuo codice il problema che ti dava era risolvibile, se volessi per forza mantenere l'uso delle matrici potresti farlo :)

Un dubbio l'avrei io,ho studiato informatica e ora sto cercando di rinfrescare le mie conoscenze per cui spero che non ti darà fastidio spiegare anche a me qualcosa...:)
Nel main secondo me c'è un problema,perchè ponendo la condizione
if ((scelta > 0) && (scelta < 4)) {
clear_screen();
}

se subito dopo ci metti lo switch sulla variabile scelta significa che nel momento in cui ad esempio viene inserito 5 lui comunque entra nello switch e cerca di trovare il caso equivalente per quel numero e si bugga,è così o sbaglio? (non voglio fare il professorino voglio solo cercare di capire se il mio dubbio è lecito :) )

No, non ci sono problemi su quello, uno switch è del tutto equivalente ad una serie di if / else, è solo più pratico da scrivere e modificare, ma se vai a leggere il codice Assembly generato dalla compilazione dovrebbe essere uguale. Se entri nello switch con un valore che non corrisponde a nessun caso, semplicemente non entri in nessun ramo e lo salti :ok:
In altri linguaggi, ad esempio il C#, puoi inserire un'etichetta default che si attiva in tutti i casi non intercettati nel resto del codice all'interno dello switch.
Poi, macché professorino,fare domande è la cosa più giusta di tutte, ti pare? :D

Sergio :)
 
No, non ci sono problemi su quello, uno switch è del tutto equivalente ad una serie di if / else, è solo più pratico da scrivere e modificare, ma se vai a leggere il codice Assembly generato dalla compilazione dovrebbe essere uguale. Se entri nello switch con un valore che non corrisponde a nessun caso, semplicemente non entri in nessun ramo e lo salti :ok:
In altri linguaggi, ad esempio il C#, puoi inserire un'etichetta default che si attiva in tutti i casi non intercettati nel resto del codice all'interno dello switch.
Poi, macché professorino,fare domande è la cosa più giusta di tutte, ti pare? :D

Sergio :)

Giusto non ci avevo pensato grazie per il chiarimento.Oltre a questo quando si assume in input una stringa non sarebbe il caso anche di usare il comando fflush()?Se la memoria non mi inganna dovrebbe pulire la cache della tastiera che se non pulita nel momento in cui in input si prende una stringa potrebbe dar problemi,giusto o ricordo male?
 
Pubblicità
Pubblicità
Indietro
Top