Visualizzazione dei risultati da 1 a 9 su 9

Discussione: Char x char... S x s

Hybrid View

  1. #1
    Riguardo alla realloc(), vi sono effettivamente tre cose fondamentali che devi sapere subito:

    1) Non va usata e devi dimenticarti anche della sua esistenza.

    2) Non va usata e devi dimenticarti anche della sua esistenza.

    3) Non va usata e devi dimenticarti anche della sua esistenza.


    Escludendo le funzioni hard I/O bound (es. lettura/scrittura su supporti di massa, I/O su filestream di sistema che corrispondono a socket TCP/IP, linee e bus seriali, etc), la realloc() è la funzione in assoluto potenzialmente più inefficiente e disastrosa dal punto di vista prestazionale dell'intera libreria standard. Nessun principiante dovrebbe sognarsi di usarla, men che meno con una densità elevata di chiamate in un singolo programma. E anche i professionisti devono ricorrervi con estrema parsimonia.

    Dunque, segui l'ottimo consiglio del nostro oregon, accetta la stringa di partenza in un unico buffer di ampie dimensioni, allocato staticamente, e poi divertiti a reinventare una strtok() fatta in casa per separare le varie parole, allocando dinamicamente lo spazio per ciascuna di esse.
    Ultima modifica di M.A.W. 1968; 30-11-2014 a 01:46
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  2. #2
    Quote Originariamente inviata da M.A.W. 1968 Visualizza il messaggio
    Riguardo alla realloc(), vi sono effettivamente tre cose fondamentali che devi sapere subito:

    1) Non va usata e devi dimenticarti anche della sua esistenza.

    2) Non va usata e devi dimenticarti anche della sua esistenza.

    3) Non va usata e devi dimenticarti anche della sua esistenza.


    Escludendo le funzioni hard I/O bound (es. lettura/scrittura su supporti di massa, I/O su filestream di sistema che corrispondono a socket TCP/IP, linee e bus seriali, etc), la realloc() è la funzione in assoluto potenzialmente più inefficiente e disastrosa dal punto di vista prestazionale dell'intera libreria standard. Nessun principiante dovrebbe sognarsi di usarla, men che meno con una densità elevata di chiamate in un singolo programma. E anche i professionisti devono ricorrervi con estrema parsimonia.

    Dunque, segui l'ottimo consiglio del nostro oregon, accetta la stringa di partenza in un unico buffer di ampie dimensioni, allocato staticamente, e poi divertiti a reinventare una strtok() fatta in casa per separare le varie parole, allocando dinamicamente lo spazio per ciascuna di esse.
    Si, sapevo che la realloc è da cestinare, ma non me ne frega niente della qualità del programma adesso. Lo faccio per un discorso di comprensione dell'utilizzo, con cicli su cilci, puntatori etc. Quando quello che dovrò programmare avrà un senso mi ricorderò delle tre regole fondamentali da te esposte, sperando di ricordarle tutte perché sono davvero molto articolate.

  3. #3
    Quote Originariamente inviata da caramelleamare Visualizza il messaggio
    Quando quello che dovrò programmare avrà un senso mi ricorderò delle tre regole fondamentali da te esposte, sperando di ricordarle tutte perché sono davvero molto articolate.
    Come già ebbe a dire un giovane e burlone fisico statistico su un altro forum, quelle regole puoi sempre fartele tatuare su un avambraccio, così da risparmiare sinapsi, usandole invece per memorizzare i contenuti di questi testi, dei quali tali regole sono un minimale frammento.

    Riguardo ai puntatori, potrebbe anche interessarti studiare questo sempreverde esempio, che illustra una silloge di tecniche di buona programmazione ed engineering coerente, MISRA/C compatibile, pur mantenendo uno stile ampiamente accettabile didatticamente.
    codice:
    /*
    ** alloc_example.c
    **
    ** Esempi di allocazione con passaggio di puntatori a vari livelli
    ** di indirezione.
    **
    */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <assert.h>
    
    #define DIM (6)
    
    /********************************************************************/
    
    #ifdef ALLOC_FAIL_01
      #pragma message("Compilazione di TEST con ALLOC_FAIL_01 abilitato.")
    #endif
    
    #ifdef ALLOC_FAIL_02
      #pragma message("Compilazione di TEST con ALLOC_FAIL_02 abilitato.")
    #endif
    
    #ifdef ALLOC_FAIL_03
      #pragma message("Compilazione di TEST con ALLOC_FAIL_03 abilitato.")
      #ifdef TEST_AT
        #undef TEST_AT
      #endif
      #define TEST_AT (r-3)
    #endif
    
    #ifdef ALLOC_FAIL_04
      #pragma message("Compilazione di TEST con ALLOC_FAIL_04 abilitato.")
    #endif
    
    #ifdef ALLOC_FAIL_05
      #pragma message("Compilazione di TEST con ALLOC_FAIL_05 abilitato.")
      #ifdef TEST_AT
        #undef TEST_AT
      #endif
      #define TEST_AT (2)
    #endif
    
    #ifdef ALLOC_FAIL_06
      #pragma message("Compilazione di TEST con ALLOC_FAIL_06 abilitato.")
    #endif
    
    #ifdef ALLOC_FAIL_07
      #pragma message("Compilazione di TEST con ALLOC_FAIL_07 abilitato.")
    #endif
    
    #ifdef ALLOC_FAIL_08
      #pragma message("Compilazione di TEST con ALLOC_FAIL_08 abilitato.")
      #ifdef TEST_AT
        #undef TEST_AT
      #endif
      #define TEST_AT (r-1)
    #endif
    
    #ifdef ALLOC_FAIL_09
      #pragma message("Compilazione di TEST con ALLOC_FAIL_09 abilitato.")
      #ifdef TEST_AT
        #undef TEST_AT
      #endif
      #define TEST_AT (c-3)
    #endif
    
    /********************************************************************/
    
    typedef enum {FALSE, TRUE} boole_t;
    
    typedef struct
    {
        char    *myString;
        size_t  myStrLen;
        int     iVal;
    } myStruct_t;
    
    boole_t alloc_vector(int **v, const size_t s);
    boole_t alloc_string(char **st, size_t *s);
    boole_t alloc_string_vect(char ***m, const size_t r, size_t *c);
    boole_t alloc_string_matrix(char ****m, const size_t r, const size_t c, size_t *le);
    boole_t alloc_struct_vect(myStruct_t **ms, const size_t s, size_t *le);
    boole_t alloc_struct_matrix(myStruct_t ***ms, const size_t r, const size_t c, size_t *le);
    
    /********************************************************************/
    /********************************************************************/
    
    int main(void)
    {
        boole_t status = FALSE;
        size_t i;
        char ***ma = NULL;
        char **m = NULL;
        char *s = NULL;
    
        myStruct_t *ms = NULL;
        int *v = NULL;
        size_t vDim = 0;
    
        puts("Esempi di allocazione indiretta con passaggio di\n"
             "puntatori a vari livelli di indirezione.\n");
    
        puts("1) Allocazione stringa singola.");
        status = alloc_string(&s, &vDim);
        if(status)
        {
            printf("   Dimensione....: %d\n"
                   "   Contenuto.....: [%s]\n", vDim, s);
            free(s);
        }
        else
        {
            puts(">>> Errore di allocazione!");
        }
    
        puts("\n2) Allocazione vettore di stringhe.");
        status = alloc_string_vect(&m, DIM, &vDim);
        if(status)
        {
            printf("   Dimensione....: %d\n"
                   "   Contenuti.....:\n", vDim);
    
            for(i = 0; i < DIM; ++i)
            {
                printf("     m[%d]: \"%s\"\n", i, m[i]);
                free(m[i]);
            }
            free(m);
        }
        else
        {
            puts(">>> Errore di allocazione!");
        }
    
        puts("\n3) Allocazione vettore di strutture.");
        status = alloc_struct_vect(&ms, DIM, &vDim);
        if (status)
        {
            puts("   Contenuti.....:");
            for(i = 0; i < DIM; ++i)
            {
                printf("     ms[%d].myString.....: \"%s\"\n"
                       "     ms[%d].myStrLen.....: %d\n"
                       "     ms[%d].iVal.........: %d\n",
                       i, ms[i].myString,
                       i, ms[i].myStrLen,
                       i, ms[i].iVal);
    
                free(ms[i].myString);
            }
            free(ms);
        }
        else
        {
            puts(">>> Errore di allocazione!");
        }
    
        puts("\n4) Allocazione vettore di interi.");
        status = alloc_vector(&v, DIM);
        if (status)
        {
            puts("   Contenuti.....:");
            for(i = 0; i < DIM; ++i)
            {
                printf("     v[%d] = %d\n", i, v[i]);
            }
            free(v);
        }
        else
        {
            puts(">>> Errore di allocazione!");
        }
    
        puts("\n5) Allocazione matrice di stringhe.");
        status = alloc_string_matrix(&ma, DIM, DIM, &vDim);
        if (status)
        {
            puts("   Contenuti.....:");
            for(i = 0; i < DIM; ++i)
            {
                size_t j;
                for (j = 0; j < DIM; ++j)
                {
                    printf("     ma[%d][%d] = \"%s\"\n", i, j, ma[i][j]);
                    free(ma[i][j]);
                }
                puts("");
                free(ma[i]);
            }
            free(ma);
        }
        else
        {
            puts(">>> Errore di allocazione!");
        }
    
        return status ? EXIT_SUCCESS : EXIT_FAILURE;
    }
    
    /********************************************************************/
    /********************************************************************/
    boole_t alloc_string(char **st, size_t *s)
    {
        const char *string = "Stringa di prova.";
    
        assert(NULL != s);
    
        *s = strlen(string) + 1;
    
    #ifdef ALLOC_FAIL_01
        *st = NULL;
        fprintf(stderr, "- simulazione errore di allocazione stringa.\n");
    #else
        *st = (char *)malloc((*s) * sizeof(char));
    #endif
    
        if (NULL != *st)
        {
            strcpy(*st, string);
        }
    
        return (boole_t)(NULL != *st);
    }
    
    /********************************************************************/
    boole_t alloc_string_vect(char ***m, const size_t r, size_t *c)
    {
        const char *string = "Stringa_";
        boole_t retval = FALSE;
    
        assert(NULL != c);
        assert(r > 1);
    
        *c = strlen(string) + 3;
    
    #ifdef ALLOC_FAIL_02
        *m = NULL;
        fprintf(stderr, "- simulazione errore di allocazione vettore.\n");
    #else
        *m = (char **)malloc(r * sizeof(char *));
    #endif
    
        if (NULL != *m)
        {
            size_t i;
            retval = TRUE;
    
            for(i = 0; i < r; ++i)
            {
                char *p;
                p = (char *)malloc(*c * sizeof(char));
    
    #ifdef ALLOC_FAIL_03
                if (TEST_AT == i)
                {
                    free(p);
                    p = NULL;
                    fprintf(stderr, "- simulazione errore di allocazione elemento %d\n", i);
                }
    #endif
                if (NULL != p)
                {
                    sprintf(p, "%s%02d", string, i +1);
                    (*m)[i] = p;
                }
                else
                {
                    do
                    {
                        --i;
                        free((*m)[i]);
                        fprintf(stderr, "- deallocazione elemento %d\n", i);
                    } while(i);
                    free(*m);
    
                    retval = FALSE;
                    break;
                }
            }
        }
    
        return retval;
    }
    
    /********************************************************************/
    boole_t alloc_struct_vect(myStruct_t **ms, const size_t r, size_t *le)
    {
        const char *string = "Stringa-in-struct_";
        boole_t retval = FALSE;
    
        assert(NULL != le);
        assert(r > 1);
    
        *le = strlen(string) +3;
    
    #ifdef ALLOC_FAIL_04
        *ms = NULL;
        fprintf(stderr, "- simulazione errore di allocazione vettore.\n");
    #else
        *ms = (myStruct_t *)malloc(r * sizeof(myStruct_t));
    #endif
    
        if (NULL != *ms)
        {
            size_t i;
            retval = TRUE;
    
            for(i = 0; i < r; ++i)
            {
                char *p;
    
                p = (char *)malloc((*le) * sizeof(char));
    
    #ifdef ALLOC_FAIL_05
                if (TEST_AT == i)
                {
                    free(p);
                    p = NULL;
                    fprintf(stderr, "- simulazione errore di allocazione elemento %d\n", i);
                }
    #endif
    
                if(NULL != p)
                {
                    sprintf(p, "%s%02d", string, i);
                    ((*ms)[i]).myString = p;
                    ((*ms)[i]).myStrLen = strlen(p);
                    ((*ms)[i]).iVal = i;
                }
                else
                {
                    while (i--)
                    {
                        free((*ms)[i].myString);
                        fprintf(stderr, "- deallocazione elemento %d\n", i);
                    }
                    free(*ms);
                    retval = FALSE;
                    break;
                }
            }
        }
    
        return retval;
    }
    
    /********************************************************************/
    boole_t alloc_vector(int **v, const size_t s)
    {
        boole_t retval = FALSE;
        size_t i;
    
        assert(s > 1);
    
    #ifdef ALLOC_FAIL_06
        *v = NULL;
        fprintf(stderr, "- simulazione errore di allocazione vettore.\n");
    #else
        *v = (int *)malloc(s * sizeof(int));
    #endif
    
        if (NULL != *v)
        {
            for(i = 0; i < s; ++i)
            {
                (*v)[i] = i;
            }
    
            retval = TRUE;
        }
    
        return retval;
    }
    
    /********************************************************************/
    boole_t alloc_string_matrix(char ****m, const size_t r,
                                const size_t c, size_t *le)
    
    {
        const char *string = "Testo_";
        boole_t retval = FALSE;
    
        assert(NULL != le);
        assert(r > 1);
        assert(c > 1);
    
        *le = strlen(string) + 6;
    
    #ifdef ALLOC_FAIL_07
        *m = NULL;
        fprintf(stderr, "- simulazione errore di allocazione matrice.\n");
    #else
        *m = (char ***)malloc(r * sizeof(char **));
    #endif
    
        if (NULL != *m)
        {
            size_t i, j;
            retval = TRUE;
    
            for(i = 0; i < r; ++i)
            {
                char **p;
                p = (char **)malloc(c * sizeof(char *));
    
    #ifdef ALLOC_FAIL_08
                if (TEST_AT == i)
                {
                    free(p);
                    p = NULL;
                    fprintf(stderr, "- simulazione errore di allocazione riga %d\n", i);
                }
    #endif
                if (NULL != p)
                {
                    (*m)[i] = p;
    
                    for (j = 0; j < c; ++j)
                    {
                        char *q;
                        q = (char *)malloc((*le) * sizeof(char));
    
    #ifdef ALLOC_FAIL_09
                        if ((TEST_AT == j) && (TEST_AT == i))
                        {
                            free(q);
                            q = NULL;
                            fprintf(stderr, "- simulazione errore di allocazione"
                                    " elemento %d, riga %d\n", j, i);
                        }
    #endif
    
                        if (NULL != q)
                        {
                            sprintf(q, "%s%02d_%02d", string, i +1, j +1);
                            (*m)[i][j] = q;
                        }
                        else
                        {
                            while (j--)
                            {
                                free((*m)[i][j]);
                                fprintf(stderr, "- deallocazione elemento %d\n", j);
                            }
                            free((*m)[i]);
                            retval = FALSE;
                            break;
                        }
                    }
                }
                else
                {
                    retval = FALSE;
                }
    
                if (!retval)
                {
                    size_t k;
                    for (k = 0; k < i; ++k)
                    {
                        fprintf(stderr, "- riga %d:\n", k);
                        if (NULL != (*m)[k][0])
                        {
                            for (j = 0; j < c; ++j)
                            {
                                free((*m)[k][j]);
                                fprintf(stderr, "  - deallocazione elemento %d\n", j);
                            }
                        }
                        free((*m)[k]);
                        fprintf(stderr, "  - deallocazione riga %d\n", k);
                    }
                    free(*m);
                    break;
                }
            }
        }
        return retval;
    }
    
    /********************************************************************/
    boole_t alloc_struct_matrix(myStruct_t ***ms, const size_t r,
                                const size_t c, size_t *le)
    {
        return TRUE;
    }
    
    /********************************************************************/
    /* EOF: alloc_example.c                                             */
    /********************************************************************/


    E' inoltre caldamente consigliato l'uso di Valgrind, o equivalentemente di DrMemory, quando si giocherella con puntatori assortiti e allocazione dinamica.
    Ultima modifica di M.A.W. 1968; 30-11-2014 a 15:41 Motivo: mistype
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.