Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316

    [C] Replicare funziona explode/split

    codice:
    void explode(char **str) {
        int elem = 0, i = 0, i2 = 0;
        char *prova = "-1,-1,2,3,5,6,7,8,9";
        char *tmp = NULL;
        char **ret = NULL;
    
        for (; i < strlen(prova); i++) {
            if (tmp != NULL) {
                tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
            } else {
                tmp = (char *)malloc(1 * sizeof(char));
            }
            
            tmp[i] = *(prova+i);
            
            /*printf("\nsize: %ld\n", strlen(tmp));
            printf("\ntmp: %s\n", tmp);*/
                   
            if (*(prova+i) == ',') {
                elem += 1;
    
                if (ret == NULL) {
                    ret = (char **)malloc(elem * sizeof(char));
                } else {
                    ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
                }
                
                ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
                
                for (; i2 < (strlen(tmp)-1); i2++) {
                    strcpy(ret[elem - 1], tmp[i2]);
                    
                }
                
                free(tmp);
                tmp = NULL;
                
            }
        }
        
        free(tmp);
        
        printf("\nElementi: %d\n", (elem+1));
    Vorrei replicare la funzione explode di PHP o split di Python/JS per scopo didattico (senza strtok grazie).

    2 quesiti:
    - Lo "strcpy" non mi funziona. Perchè?
    - Oltretutto come posso poi ritornare l'array dopo aver deallocato la memoria con free a ret?

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    - Lo "strcpy" non mi funziona. Perchè?
    Che vuol dire? Come "non funziona"?

    - Oltretutto come posso poi ritornare l'array dopo aver deallocato la memoria con free a ret?
    Non devi chiamare la free e la funzione deve restituire il puntatore

    Posta anche codice di esempio con un main che utilizza la tua funzione.
    (ma a che serve il parametro str della funzione? come mai utilizzi prova all'interno della funzione?)
    Ultima modifica di oregon; 18-06-2017 a 22:04
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    A dir la verità non cambia quasi per niente in quanto mi ero concentro nel far funzionare la funzione, però in linea di massima dovrebbe essere:

    codice:
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char** explode(char sep, char *prova);
    
    int main (void)
    {    
        char **new;
        
        new = explode(',', "-1,-1,2,3,5,6,7,8,9");
       
        return 0;
    }
    
    char** explode(char sep, char *prova) {
        int elem = 0, i = 0, i2 = 0;
        //char *prova = "-1,-1,2,3,5,6,7,8,9";
        char *tmp = NULL;
        char **ret = NULL;
        
        for (; i < strlen(prova); i++) {
            if (tmp != NULL) {
                tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
            } else {
                tmp = (char *)malloc(1 * sizeof(char));
            }
            
            tmp[i] = *(prova+i);
    
            if (*(prova+i) == sep) {
                elem += 1;
    
                if (ret == NULL) {
                    ret = (char **)malloc(elem * sizeof(char));
                } else {
                    ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
                }
                
                ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
                
                for (; i2 < (strlen(tmp)-1); i2++) {
                    strcpy(ret[elem - 1], tmp[i2]);
                    
                }
                
                free(tmp);
                tmp = NULL;
                
            }
        }
        
        free(tmp);
        
        printf("\nElementi: %d\n", (elem+1));
        
        return ret;
    }
    Ultima modifica di zacca94; 18-06-2017 a 22:24

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    La funzione va scritta nella sua forma finale.

    La linea con la strcpy non può essere compilata perché il secondo argomento che passi

    tmp[i2]

    è un carattere e non una stringa. La stringa è tmp.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    Errore:
    root@matias-desktop:/# gcc try.c -o try
    try.c: In function ‘explode’:
    try.c:43:39: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
    strcpy(ret[elem - 1], tmp[i2]);
    ^
    In file included from try.c:1:0:
    /usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
    extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
    ^


    (ho inserito 2 messaggi che mi diceva fosse troppo lungo)

  6. #6
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    Scusa ora provo, non mi sta funzionando il forum, ora provo a modificare secondo i tuoi suggerimenti.

  7. #7
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    Ho provato ad eliminare totalmente strcpy, a questo punto se posso dargli un valore con malloc alla array multdimensionale uguale alla lunghezza del "tmp"... questa è la funzione, però non funziona:

    codice:
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char** explode(char sep, char *prova);
    
    int main (void)
    {    
        char **new;
        
        new = explode(',', "-1,-1,2,3,5,6,7,8,9");
       
        return 0;
    }
    
    char** explode(char sep, char *prova) {
        int elem = 0, i = 0, i2 = 0;
        //char *prova = "-1,-1,2,3,5,6,7,8,9";
        char *tmp = NULL;
        char **ret = NULL;
        
        for (; i < strlen(prova); i++) {
            if (tmp != NULL) {
                tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
            } else {
                tmp = (char *)malloc(1 * sizeof(char));
            }
            
            tmp[i] = *(prova+i);
    
            if (*(prova+i) == sep) {
                elem += 1;
    
                if (ret == NULL) {
                    ret = (char **)malloc(elem * sizeof(char));
                } else {
                    ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
                }
                
                ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
                ret[elem -1] = tmp;
                
                /*for (; i2 < (strlen(tmp)-1); i2++) {
                    strcpy(ret[elem - 1], tmp);
                    
                }*/
                
                free(tmp);
                tmp = NULL;
                
            }
        }
        
        free(tmp);
        
        printf("\nElementi: %d\n", (elem+1));
        
        return ret;
    }
    Errore:
    root@matias-desktop:/home/matias/Desktop# gcc try.c -o try
    root@matias-desktop:/home/matias/Desktop# ./try
    *** Error in `./try': realloc(): invalid next size: 0x000000000197a030 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ffbdf84e7e5]
    /lib/x86_64-linux-gnu/libc.so.6(+0x82a5a)[0x7ffbdf859a5a]
    /lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7ffbdf85ac89]
    ./try[0x40075f]
    ./try[0x40065d]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ffbdf7f7830]
    ./try[0x400579]
    ======= Memory map: ========
    00400000-00401000 r-xp 00000000 00:2c 4194365 /home/matias/Desktop/try
    00600000-00601000 r--p 00000000 00:2c 4194365 /home/matias/Desktop/try
    00601000-00602000 rw-p 00001000 00:2c 4194365 /home/matias/Desktop/try
    0197a000-0199b000 rw-p 00000000 00:00 0 [heap]
    7ffbd8000000-7ffbd8021000 rw-p 00000000 00:00 0
    7ffbd8021000-7ffbdc000000 ---p 00000000 00:00 0
    7ffbdf5bf000-7ffbdf5d5000 r-xp 00000000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7ffbdf5d5000-7ffbdf7d4000 ---p 00016000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7ffbdf7d4000-7ffbdf7d5000 rw-p 00015000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
    7ffbdf7d7000-7ffbdf996000 r-xp 00000000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
    7ffbdf996000-7ffbdfb96000 ---p 001bf000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
    7ffbdfb96000-7ffbdfb9a000 r--p 001bf000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
    7ffbdfb9a000-7ffbdfb9c000 rw-p 001c3000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
    7ffbdfb9c000-7ffbdfba0000 rw-p 00000000 00:00 0
    7ffbdfba7000-7ffbdfbcd000 r-xp 00000000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
    7ffbdfdca000-7ffbdfdcc000 rw-p 00000000 00:00 0
    7ffbdfdcc000-7ffbdfdcd000 r--p 00025000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
    7ffbdfdcd000-7ffbdfdce000 rw-p 00026000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
    7ffbdfdce000-7ffbdfdd0000 rw-p 00000000 00:00 0
    7ffbdfdd0000-7ffbdfdd3000 rw-p 00000000 00:00 0
    7fff1cb0d000-7fff1cb2e000 rw-p 00000000 00:00 0 [stack]
    7fff1cb47000-7fff1cb49000 r--p 00000000 00:00 0 [vvar]
    7fff1cb49000-7fff1cb4b000 r-xp 00000000 00:00 0 [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
    Aborted (core dumped)

  8. #8
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,466
    Righe come queste

    ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
    ret[elem -1] = tmp;

    non hanno senso. Assegni due valori diversi uno dopo l'altro allo stesso elemento, creando un memory leak ...

    Fossi in te rivedrei tutto l'algoritmo che stai usando, anche perché non si riesce a capire molto.

    E farei degli esercizi molto più semplici con puntatori, stringhe e caratteri perché devi chiarirti melgio il loro utilizzo.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  9. #9
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    Righe come queste

    ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
    ret[elem -1] = tmp;

    non hanno senso. Assegni due valori diversi uno dopo l'altro allo stesso elemento, creando un memory leak ...
    Ok ho fatto dei miglioramenti anche riscrivendo il codice e ordinandolo un pò:

    codice:
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char **explode(char sep, char *str);
    
    int main (void)
    {
        int i, i2;
        
        char **new;
    
        new = explode(',', "100,2,3,4,5,6,7,8,9,");
        
        printf("%s ", new[0]);
        printf("%s ", new[1]);
        return 0;
    }
    
    char **explode(char sep, char *str)
    {
        int elem = 0
          , i    = 0
          , i2;
    
        char *tmp = NULL
          , **ret = NULL;
    
        ret = (char **)malloc(sizeof(char **) * (strlen(str)));
        for (; i < strlen(str); i++)
        {
            if (*(str + i) == sep || *(str + i) == '\n')
            {
                printf("\n- %s\n", tmp);
                
                ret[elem] = (char *)malloc(sizeof(char) * (strlen(tmp)));
                for (i2 = 0; i2 < strlen(tmp); i2++)
                {
                    ret[elem][i2] = tmp[i2];
                }
    
                elem++;
                free(tmp);
                tmp = NULL;
            }
            else
            {
                /* Se è il primo ciclo alloca, altrimenti re-alloca uno spazio più grande */
                if (tmp != NULL) tmp = (char *)realloc(tmp, sizeof(char) * (strlen(tmp) + 1));
                else             tmp = (char *)malloc (sizeof(char) * 1);
    
                tmp[i] = *(str + i);
            } 
        }
        
        free(tmp);
        
        printf("\nElementi: %d\n", (elem + 1));
        
        return ret;
    }
    Però mi assegna solo il primo elemento (100), gli altri se li mangia... penso di fare casino con il free e l'assegnazione di NULL.

  10. #10
    Utente di HTML.it
    Registrato dal
    Jun 2008
    Messaggi
    1,316
    C'è l'ho fatta:

    codice:
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    char **explode(char sep, char *str);
    
    int main (void)
    {
        int i;
    
        char **new;
    
        new = explode(',', "100,222,33,4444,55555,6,7,8,9,");
    
        for (i = 0; i < 9; i++)
        {
            printf("%s ", new[i]);
        }
        return 0;
    }
    
    char **explode(char sep, char *str)
    {
        int elem = 0
          , i    = 0
          , i2
          , i3;
    
        char *tmp = NULL
          , **ret = NULL;
    
        ret = (char **)malloc(sizeof(char) * (strlen(str)));
        for (; i < strlen(str); i++)
        {
            if (*(str + i) == sep || *(str + i) == '\n')
            {
                ret[elem] = (char *)malloc(sizeof(char) * (strlen(tmp)));
                for (i2 = 0; i2 < strlen(tmp); i2++)
                {
                    ret[elem][i2] = tmp[i2];
                }
    
                elem++;
                //free(tmp);
                tmp = NULL;
            }
            else
            {
                /* Se è il primo ciclo alloca, altrimenti re-alloca uno spazio più grande */
                if (tmp != NULL) tmp = (char *)realloc(tmp, (sizeof(char)) * (strlen(tmp) + 1));
                else {
                    tmp = (char *)malloc(sizeof(char) * 1);
                    i3 = 0;
                }
    
                tmp[i3++] = *(str + i);
            }
        }
    
        free(tmp);
    
        printf("\nElementi: %d\n", (elem + 1));
    
        return ret;
    }
    Avevo sbagliato questa riga: tmp[i] = *(str + i);
    dove i rappresentava l'indice della posizione della stringa, mentre dovevo partire da 0 ogni volta che riallocavo.

    Ora voglio dei consigli riguardo alla gestione del codice, ergo: è palese che essendo inesperto ho scritto più righe di codice quando potevo fare lo stesso procedimento più facilmente (per esempio ho notato che molti codici re-allocano direttamente).

    E altra domanda: il "\n" lo devo salvare a fine riga o posso saltarlo?

    Grazie
    Ultima modifica di zacca94; 19-06-2017 a 02:26

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 © 2024 vBulletin Solutions, Inc. All rights reserved.