Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Problemone con l'allocazione dinamica
Forum - C/C++ - Problemone con l'allocazione dinamica

Avatar
drewnik99 (Normal User)
Pro


Messaggi: 69
Iscritto: 28/03/2008

Segnala al moderatore
Postato alle 23:06
Domenica, 08/12/2013
Il problema è il seguente: Data una lista ordinata composta da N elementi, il programma restituisce un errore quando tento di eliminare il primo elemento della lista(vedi elimina()).

CODICE:

Codice sorgente - presumibilmente C++

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #define NAME_LENGTH 50
  6. #define DES_LENGTH 50
  7. #define PUTS_LINE_STDERR fputs("________________________________________________________________________________\n", stderr);
  8.  
  9.  
  10. typedef struct my_articolo
  11. {
  12.     signed int code;
  13.     char *name;
  14.     char *des;
  15.     float price;
  16.     signed int q_disp;
  17.     signed int q_min;
  18.     struct my_articolo *n;
  19. } articolo;
  20.  
  21. articolo *start = 0;
  22.  
  23. void apri(void);
  24. void inserisci(void);
  25. void cerca(void);
  26. void modifica(void);
  27. void elimina(void);
  28. void visualizza(void);
  29. void esporta(void);
  30.  
  31. char* r_line(char *str, unsigned int length, FILE *stream);
  32. articolo* if_code(signed int code);
  33. articolo** if_name(articolo **arr, const char *name);
  34. void stampa(articolo **arr);
  35.  
  36.  
  37.  
  38. int main()
  39. {
  40.     void (*cmd[])(void) = {apri, inserisci, cerca, modifica, elimina, visualizza, esporta};
  41.  
  42.     unsigned int c_code = 0;
  43.  
  44.     while(1)
  45.     {
  46.         PUTS_LINE_STDERR;
  47.         fputs("                                 @ Database @\n\n", stderr);
  48.         fputs("1 - Apri database\n\n", stderr);
  49.         fputs("2 - Inserisci articolo nel database\n\n", stderr);
  50.         fputs("3 - Cerca articolo/i nel database\n\n", stderr);
  51.         fputs("4 - Modifica articolo del database\n\n", stderr);
  52.         fputs("5 - Elimina articolo/i del database o svuota l'intero database\n\n", stderr);
  53.         fputs("6 - Visualizza il database\n\n", stderr);
  54.         fputs("7 - Esporta database\n\n", stderr);
  55.         fputs("8 - Esci dal programma\n", stderr);
  56.         PUTS_LINE_STDERR;
  57.         fputs("Inserire il codice corrispondente all'operazione: ", stderr);
  58.  
  59.         fflush(stdin);
  60.         scanf("%u", &c_code);
  61.         c_code--;
  62.  
  63.         if(c_code < 7)
  64.         {
  65.             (*cmd[c_code])();
  66.             fputs("\n------------------------ Premere un tasto per continuare ----------------------\n", stderr);
  67.             fflush(stdin);
  68.             getchar();
  69.             fputs("\n\n", stderr);
  70.         }
  71.         else if(c_code == 7)
  72.         {
  73.             return 0;
  74.         }
  75.         else
  76.         {
  77.             fputs("\n\nIl codice inserito non e' valido.\n\n------------------------ Premere un tasto per continuare ----------------------\n", stderr);
  78.             fflush(stdin);
  79.             getchar();
  80.             fputs("\n\n", stderr);
  81.         }
  82.     }
  83. }
  84.  
  85.  
  86.  
  87. char* r_line(char *str, unsigned int length, FILE *stream)
  88. {
  89.     signed char ch = '\0';
  90.     BYTE i = 0;
  91.  
  92.     if(stream == stdin) fflush(stdin);
  93.  
  94.     while(isspace(ch = fgetc(stream)));
  95.  
  96.     while(((ch != '\n') && (ch != EOF)) && (i < length - 1))
  97.     {
  98.         str[i++] = ch;
  99.         ch = fgetc(stream);
  100.         str = (char*) realloc(str, (i + 1) * sizeof(char));
  101.     }
  102.  
  103.     if(i == length - 1)
  104.     {
  105.         str = (char*) realloc(str, (i + 2) * sizeof(char));
  106.         str[i] = '~';
  107.         str[i + 1] = '\0';
  108.     }
  109.  
  110.     str[i] = '\0';
  111.  
  112.     if(stream == stdin) fflush(stdin);
  113.  
  114.     return str;
  115. }
  116.  
  117.  
  118. void inserisci()
  119. {
  120.     articolo *p = 0, *c = 0, *nn = calloc(1, sizeof(articolo));
  121.     char *n_name = (char*) calloc(1, sizeof(char)), *n_des = (char*) calloc(1, sizeof(char));
  122.  
  123.     if(!nn)
  124.     {
  125.         fputs("\nErrore di memoria. Impossibile aggiungere l'articolo.\n", stderr);
  126.         free(nn);
  127.         return;
  128.     }
  129.  
  130. i_code:
  131.     fputs("\nInserisci il codice del componente (0 - 99999999): ", stderr);
  132.     fflush(stdin);
  133.     scanf("%8i", &nn->code);
  134.  
  135.     if(nn->code < 0 || nn->code > 99999999)
  136.     {
  137.         fputs("\nIl codice inserito non e' valido.\n", stderr);
  138.         goto i_code;
  139.     }
  140.  
  141.     for(c = start, p = 0; c && nn->code > c->code; p = c, c = c->n);
  142.  
  143.     if(c && (nn->code == c->code))
  144.     {
  145.         fputs("\nL'articolo esiste gia'. Impossibile aggiungerlo.\n", stderr);
  146.         free(nn);
  147.         return;
  148.     }
  149.  
  150. i_name:
  151.     fputs("Inserisci il nome dell'articolo: ", stderr);
  152.     r_line(n_name, NAME_LENGTH, stdin);
  153.  
  154.     if(strlen(n_name) <= 0)
  155.     {
  156.         fputs("\nIl nome inserito non e' valido.\n", stderr);
  157.         goto i_name;
  158.     }
  159.  
  160.     nn->name = n_name;
  161.  
  162.  
  163. i_des:
  164.     fputs("Inserisci la descrizione dell'articolo: ", stderr);
  165.     r_line(n_des, DES_LENGTH, stdin);
  166.  
  167.     if(strlen(n_des) <= 0)
  168.     {
  169.         fputs("\nLa descrizione inserita non e' valida.\n", stderr);
  170.         goto i_des;
  171.     }
  172.  
  173.     nn->des = n_des;
  174.  
  175.  
  176. i_price:
  177.     fputs("Inserisci il prezzo dell'articolo(0 - 9999999.99): ", stderr);
  178.     fflush(stdin);
  179.     scanf("%7f", &nn->price);
  180.  
  181.     if(nn->price < 0.0 || nn->price > 9999999.99)
  182.     {
  183.         fputs("\nIl prezzo inserito non e' valido.\n", stderr);
  184.         goto i_price;
  185.     }
  186.  
  187.  
  188. i_disp:
  189.     fputs("Inserisci la disponibilita' dell'articolo(0 - 9999999): ", stderr);
  190.     fflush(stdin);
  191.     scanf("%7i", &nn->q_disp);
  192.  
  193.     if(nn->q_disp < 0 || nn->q_disp > 9999999)
  194.     {
  195.         fputs("\nIl valore inserito non e' valido.\n", stderr);
  196.         goto i_disp;
  197.     }
  198.  
  199.  
  200. i_min:
  201.     fputs("Inserisci la quantita' minima di riordino(0 - 9999998): ", stderr);
  202.     fflush(stdin);
  203.     scanf("%7i", &nn->q_min);
  204.  
  205.     if(nn->q_min < 0 || nn->q_min > 9999998)
  206.     {
  207.         fputs("\nIl valore inserito non e' valido.\n", stderr);
  208.         goto i_min;
  209.     }
  210.  
  211.     nn->n = c;
  212.  
  213.     if(!p)
  214.     {
  215.         start = nn;
  216.     }
  217.     else
  218.     {
  219.         p->n = nn;
  220.     }
  221. }
  222.  
  223.  
  224. void elimina()
  225. {
  226.     articolo *p = 0, *c = 0;
  227.     signed int code = 0, c_code = 0;
  228.  
  229.     if(!start)
  230.     {
  231.         fputs("\nDatabase vuoto.\n", stderr);
  232.         return;
  233.     }
  234.  
  235. menu_e:
  236.     fputs("\n1 - Elimina uno o piu' componenti\n", stderr);
  237.     fputs("\n2 - Elimina tutto il database\n", stderr);
  238.     fputs("\n3 - Torna al menu'\n", stderr);
  239.     fputs("\nInserisci il codice corrispondente alla tua scelta: ", stderr);
  240.  
  241.     fflush(stdin);
  242.     scanf("%u", &c_code);
  243.  
  244.     switch(c_code)
  245.     {
  246.     case 1:
  247. del:
  248.         fputs("\nInserisci il codice del componente: ", stderr);
  249.  
  250.         fflush(stdin);
  251.         scanf("%u", &code);
  252.  
  253.         for(c = start, p = 0; c && (c->code != code); p = c, c = c->n);
  254.  
  255.         if(!c)
  256.         {
  257.             fputs("\nComponente non trovato. Impossibile completare la cancellazione.\n", stderr);
  258.             fputs("\nRiprovare?[s/n]: ", stderr);
  259.             fflush(stdin);
  260.             if(fgetc(stdin) == 's')
  261.             {
  262.                 PUTS_LINE_STDERR;
  263.                 goto del;
  264.             }
  265.             goto ask_e;
  266.         }
  267.         if(!p)
  268.         {
  269.             start = c->n;
  270.         }
  271.         else
  272.         {
  273.             p->n = c->n;
  274.         }
  275.  
  276.         free(c->name);
  277.         free(c->des);
  278.         free(c);
  279.  
  280.         fputs("\nComponente eliminato.\n", stderr);
  281.         break;
  282.  
  283.     case 2:
  284.         for(p = start, c = 0; p; p = c)
  285.         {
  286.             c = p->n;
  287.             free(p->name);
  288.             free(p->des);
  289.             free(p);
  290.         }
  291.  
  292.         start = 0;
  293.  
  294.         fputs("\nDatabase svuotato.\n", stderr);
  295.         return;
  296.  
  297.     case 3:
  298.         return;
  299.  
  300.     default:
  301.         fputs("\nIl codice inserito non e' valido.\n", stderr);
  302.         PUTS_LINE_STDERR
  303.         goto menu_e;
  304.         break;
  305.     }
  306.  
  307. ask_e:
  308.     fputs("\nContinuare con le eliminazioni?[s/n]: ", stderr);
  309.     fflush(stdin);
  310.     if(fgetc(stdin) == 's')
  311.     {
  312.         PUTS_LINE_STDERR;
  313.         goto menu_e;
  314.     }
  315. }



Grazie in anticipo per il vostro aiuto! :rofl:

Ultima modifica effettuata da drewnik99 il 09/12/2013 alle 15:32
PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 23:35
Domenica, 08/12/2013
Mancano alcune costanti

PUTS_LINE_STDERR
NAME_LENGTH
DES_LENGTH

e

r_line


P.S. Tutti quei goto sono orrendi ...


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
drewnik99 (Normal User)
Pro


Messaggi: 69
Iscritto: 28/03/2008

Segnala al moderatore
Postato alle 23:48
Domenica, 08/12/2013
Una soluzione alternativa ai goto?

E per il problema con i free()?

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 7:56
Lunedì, 09/12/2013
I goto non si usano. Al loro posto utilizza i cicli.

Adesso manca il main ...

Ultima modifica effettuata da nessuno il 09/12/2013 alle 8:00


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
drewnik99 (Normal User)
Pro


Messaggi: 69
Iscritto: 28/03/2008

Segnala al moderatore
Postato alle 12:16
Lunedì, 09/12/2013
Potresti dirmi quali sono i vantaggi nell'utilizzare i cicli al posto di goto?
Guardando l'assembly prodotto, isolando una piccola porzione con un menu, non sembrano esserci sostanziali differenze, anche se non sono molto esperto.

Il programma in realtà è molto più ampio, ma il problema si riscontra nella funzione elimina(), per questo ho postato la stessa e inserisci() per mostrare come aggiungo gli elementi alla lista ordinata.
Non riesco ancora a capire perchè il programma non mi permette di eliminare il primo elemento della lista ordinata, ma solo i successivi.

Grazie a tutti per i suggerimenti.

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 5475
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 13:24
Lunedì, 09/12/2013
Per il goto leggi

http://it.wikipedia.org/wiki/Spaghetti_code

Per il resto, senza vedere cosa fai nel main e come chiami le varie funzioni, con quali argomenti, potrebbe essere un problema risalire all'errore. Sicuramente provando il tuo main si fa prima e con certezza.

Tanto per capirci, anche la funzione

r_line

non mi convince e potrebbe essere sbagliata ... vorrei vedere come la usi.

Ultima modifica effettuata da nessuno il 09/12/2013 alle 13:30


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
PM Quote
Avatar
drewnik99 (Normal User)
Pro


Messaggi: 69
Iscritto: 28/03/2008

Segnala al moderatore
Postato alle 15:11
Lunedì, 09/12/2013
Ok, grazie per il link, ho modificato il post iniziale, guarda pure lì. :rofl:

E' possibile eliminare start come variabile globale e passarla come parametro a tutte le funzioni sapendo che vengono richiamate così:

Codice sorgente - presumibilmente C++

  1. void apri(articolo *start);
  2. void inserisci(articolo *start);
  3. void cerca(articolo *start);
  4. void modifica(articolo *start);
  5. void elimina(articolo *start);
  6. void visualizza(articolo *start);
  7. void esporta(articolo *start);
  8.  
  9. int main()
  10. {
  11.     articolo *start = 0;
  12.     unsigned int c_code = 0;
  13.     void (*cmd[7])(articolo*) = {apri, inserisci, cerca, modifica, elimina, visualizza, esporta};
  14.  
  15.     scanf("%u", &c_code);
  16.     c_code--;
  17.  
  18.     (*cmd[c_code])(start);
  19. }


Ultima modifica effettuata da drewnik99 il 09/12/2013 alle 18:59
PM Quote