Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. 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: 6380
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 ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
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: 6380
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 ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
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: 6380
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 ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
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