[risolto][c] strtok

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

[risolto][c] strtok

Messaggio da ienaplinsky »

Salve, avrei bisogno di splittare una stringa salvando ogni sottostringa in una matrice (una specie di explode), quindi alla mia funzione passo la stringa e il delimiter

Codice: Seleziona tutto

char **explode(const char *string, const char *delimiter) {
} 
volevo sapere , dato che copio il parametro string in un altra stringa con strcpy e poi inizio ad usare strtok, se bisogna fare le free sui tutti i token o sulla stringa temporanea, oppure su entrambi nella documentazione non ho trovato niente
Ultima modifica di ienaplinsky il giovedì 10 aprile 2014, 21:31, modificato 1 volta in totale.
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [c] strtok

Messaggio da ienaplinsky »

dopo alcune prove ho scoperto che la stringa temporanea punta al primo pezzo splittato, ora volevo capire ma i token si possono dellocare ?
dico questo perchè ho bisogno di salvaguardare la memoria dato che sono in un ciclo infinito di letture su dispositivi dedicati qualcuno ha qualche idea ?
devo scrivere una strtok mia ?
oppure non c'è bisogno di deallocare?
lascio un codice forse per spiegarmi meglio

Codice: Seleziona tutto

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

int main() {
  const char *string = "ciao|come|stai";
  char *tempString = malloc(sizeof(char) * (strlen(string) + 1));
  char **matrix = malloc(sizeof(char *) * 3);
  int i = 0;
  
  strcpy(tempString, string);
  char *token = strtok(tempString, "|");
  printf("indirizzo token = %p, indirizzo tempString = %p\n", token, tempString);
  
  while(token != NULL) {
    matrix[i] = malloc(sizeof(char) * (strlen(token) + 1));
    strcpy(matrix[i++], token);
    //free(token); come posso deallocare i token ? se decommento il programma non va a buon fine
    token = strtok(NULL, "|");
    printf("indirizzo token = %p, indirizzo tempString = %p\n", token, tempString);
  }
  
  while(i-- > 0) 
    printf("stringa = %s numero = %d\n", matrix[i], i);
  
  printf("stringa originale temp = %s\n", tempString);
  
  free(tempString);
  
  return 0;
}
antex
Prode Principiante
Messaggi: 85
Iscrizione: mercoledì 14 marzo 2012, 20:59

Re: [c] strtok

Messaggio da antex »

Non puoi deallocare le stringhe restituite da strtok, perché puntano all'interno di tempString (come si vede anche dall'output del tuo programma). In altre parole, strtok non alloca niente di suo: invece di allocare le sottostringhe, ti modifica la stringa originaria (è per questo che probabilmente ti tocca copiarla). Sei tu che usi malloc e tu che devi usare free su quello che hai allocato (matrix e i vari matrix, oltre al resto).

Mi sembra ti ripeterlo un po' troppo spesso ultimamente su questo forum, ma ci riprovo: usa valgrind, ti dice se hai mancato di deallocare qualcosa oppure se hai provato a deallocare qualcosa che non dovevi.
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [c] strtok

Messaggio da vbextreme »

sicuramente avrai letto un reference sulla strtok.
tale funzione restituisce un puntatore all'ultima occorrenza di uno dei caratteri ricercati.
Tale puntatore punterà all'area di memoria passata come "char* str",tale funzione userà una variabile statica interna per memorizzare la variabile str,in questo modo una sucessiva chiamata ad strtok con str == NULL farà continuare la ricerca all'interno della stringa.
avendo una stringa "Hello world" e un delimiter = " " strtok restituirà:
str+6:
*(str+6) = w;
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [c] strtok

Messaggio da ienaplinsky »

Si si ho letto la documentazione quindi i token non li devo deallocare basta che dealloco tempString?

Valgrind devo imparare ad usarlo
ixamit
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 499
Iscrizione: giovedì 14 novembre 2013, 10:16

Re: [c] strtok

Messaggio da ixamit »

ienaplinsky [url=http://forum.ubuntu-it.org/viewtopic.php?p=4561109#p4561109][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Si si ho letto la documentazione quindi i token non li devo deallocare basta che dealloco tempString?
Ciao, guarda che antex ha gia' risposto alla tua domanda e vbextreme e' stato ulteriormente chiaro. :ciao:
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [c] strtok

Messaggio da ienaplinsky »

Si scusate sono fuso grazie a tutti
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [risolto][c] strtok

Messaggio da vbextreme »

Giusto per essere chiari,il tuo codice potrebbe diventare:

Codice: Seleziona tutto

#define MAX_TOKEN 1024
int main()
{
    char string[] = "ciao|come|stai";
    char* vtk[MAX_TOKEN];
        memset(vtk,0,sizeof(char*)*MAX_TOKEN);

    int i = 0;

    vtk[i] = strtok(string, "|");

    for (; i < MAX_TOKEN && vtk[i]; vtk[++i] = strtok(NULL, "|"));

    for (i = 0; i < MAX_TOKEN && vtk[i]; i++)
    {
        printf("token[%d]:%s\n",i,vtk[i]);
    }

    return 0;
}
questo codice serve invece a comprendere come divide i token la strtok

Codice: Seleziona tutto

#define MAX_TOKEN 1024
int main()
{
    char string[] = "ciao|come|stai";
    char* tmptoken;


    tmptoken = strtok(string, "|");
    int countk = 1;

    for (; (tmptoken = strtok(NULL, "|")); countk++ );

    int i;
    for (tmptoken = string, i = 0; i < countk; i++)
    {
        printf("token[%d]:%s\n",i,tmptoken);
        tmptoken += strlen(tmptoken) + 1;
    }


    return 0;
}

Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

vbextreme ha scritto:Giusto per essere chiari,il tuo codice potrebbe diventare:

Codice: Seleziona tutto

#define MAX_TOKEN 1024
int main()
{
    char string[] = "ciao|come|stai";
    char* vtk[MAX_TOKEN];
        memset(vtk,0,sizeof(char*)*MAX_TOKEN);

    int i = 0;

    vtk[i] = strtok(string, "|");

    for (; i < MAX_TOKEN && vtk[i]; vtk[++i] = strtok(NULL, "|"));

    for (i = 0; i < MAX_TOKEN && vtk[i]; i++)
    {
        printf("token[%d]:%s\n",i,vtk[i]);
    }

    return 0;
}
Ho solo 256 MB di RAM e una lettura al minuto non posso occupare tutta questa memoria, per questo ogni elemento della matrice viene allocato in base alla lunghezza del token
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

A scusa forse intendevi di far puntare le stringhe della matrice ai token della stringa temporanea ? Poi riuscire i a deallocare le stringhe in un secondo momento ?
antex
Prode Principiante
Messaggi: 85
Iscrizione: mercoledì 14 marzo 2012, 20:59

Re: [risolto][c] strtok

Messaggio da antex »

Ma se devi memorizzare tutti i token, perché non eviti proprio di allocarli singolarmente e tieni solamente una copia (se ti serve) della stringa originaria? Questo ti fa anche risparmiare risorse computazionali (le malloc non sono velocissime, invece di averne N ne hai una sola).
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

antex ha scritto:Ma se devi memorizzare tutti i token, perché non eviti proprio di allocarli singolarmente e tieni solamente una copia (se ti serve) della stringa originaria? Questo ti fa anche risparmiare risorse computazionali (le malloc non sono velocissime, invece di averne N ne hai una sola).
si in effetti è giusto poi credo che basti deallocare solo il primo elemento della matrice che teoricamente dovrebbe puntare al primo carattere della stringa originaria
sbaglio?
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: [risolto][c] strtok

Messaggio da vbextreme »

la mia versione del codice occupa meno di un terzo della memoria rispetto alla tua.
Ad esempio tu prima occupi memoria con una stringa costante poi la copi dentro ad un'altra temporanea raddoppiando quindi l'uso della memoria.
Usi poi un vettore per memorizzare i puntatori alla prima stringa,passaggio inutile perché puoi processare direttamente caso per caso senza sprecare quei 4 byte di memoria che servono per ogni puntatore.
Infine non hai ancora capito la strtok.
La strtok ritorna un puntatore alla memoria che gli hai passato come primo parametro ma non alloca niente,non ti copia il token in un'altra area della memoria! Non fa altro che mettere degli \0 nei caratteri delimiter poi ti restituisce un puntatore iniziale,alla sucessiva chiamata si muove fino a dopo lo zero e ti ritorna il puntatore e cosi via finche non supera l'area di memoria della stringa e allora ritorna null.

Per finire maggiori dettagli sul codice portano a maggiori consigli
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

Allora scusate non sono a casa, in pratica sto usando una libreria per parsare i file ini , questa libreria salva i dati in una struttura e nella documentazione viene raccomandato di non fare le free ma di usare una funzione ad hoc della libreria per deallocare la struttura, per fare un esempio ho una funzione che ritorna una stringa questa stringa è allocata nella struttura per questo prima di deallocare la struttura salvo la stringa in un altra area di memoria , ad esmpio ad explode viene passata la stringa che sta nella struttura che sara deallocata ed ho bisogno di salvarla altrinenti le stringhe della matrice punterebbero all chi sa cosa comunque appena posso posto il codice
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

ok ragazzi grazie al vostro aiuto sono arrivato a questo risultato, poi per eliminare tempString basta fare la free su result[0] e quindi libero la memoria che ho allocato per tempString e poi la free su result

Codice: Seleziona tutto

char **explode(const char *string, const char *delimiter) {
  char *tempString = malloc(sizeof (char) * (strlen(string) + 1)); // questa la devo copiare per forza il parametro string appartiene a una struttura che sarà deallocata
  char *token = tempString;
  int row = 0;
  char **result = NULL;
  
  strcpy(tempString, string);
  row = contElementSplit(tempString, delimiter);
  result = malloc(sizeof (char *) * (row + 1));
  
  for(; i < row; i++) {
    result[i] = token;
    token += strlen(token) + 1;
  }
  
  result[i] = NULL;
  
  return result;
}

int contElementSplit(char *string, const char *delimiter) {
  int i = 0;
  char *token = strtok(string, delimiter);
  
  for (; (token = strtok(NULL, "|")); i++ );
  
  return i;
}
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: [risolto][c] strtok

Messaggio da ienaplinsky »

ok abbiamo superato anche il controllo di valgrind (utilissimo anche per il futuro grazie antex)

Codice: Seleziona tutto

==5190== HEAP SUMMARY:
==5190==     in use at exit: 0 bytes in 0 blocks
==5190==   total heap usage: 2 allocs, 2 frees, 27 bytes allocated
==5190== 
==5190== All heap blocks were freed -- no leaks are possible
==5190== 
==5190== For counts of detected and suppressed errors, rerun with: -v
==5190== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 13 ospiti