View Full Version : [C] Buffer di caratteri: inizializzarlo & funzioni per stringhe
Matrixbob
10-03-2007, 14:29
Non so se è corretto, ma io faccio così:
titolo_str[0]='\0';
strcpy(titolo_str, "##### TITOLO DEL ITEM #####\n");
Forse è meglio usare la strcat?!
Secondo me no, perchè se il buffer è sporco, nel concatenare può fare dei casini.
Ammesso che pulire/ripulire/inizializzare 1 buffer di caratteri si faccia come faccio io. :stordita:
xorshadow
10-03-2007, 14:59
Per inizializzare un buffer si fa così di solito:
memset(buffer, 0, DIMENSIONE_BUFFER);
riempie TUTTO il buffer di zeri e non solo il primo carattere.
Per riempirlo è meglio che usi la versione sicura di strcpy,ovvero strncpy che ti aiuta a prevenire pericolosi buffer overflow.
Matrixbob
10-03-2007, 17:42
Per inizializzare un buffer si fa così di solito:
memset(buffer, 0, DIMENSIONE_BUFFER);
riempie TUTTO il buffer di zeri e non solo il primo carattere.
Per riempirlo è meglio che usi la versione sicura di strcpy,ovvero strncpy che ti aiuta a prevenire pericolosi buffer overflow.
Io mi son fatto questa funzioncina:
void pulisci_str(char *stringa, int lunghezza)
{
int i;
for (i=0; i<lunghezza; ++i) { stringa[i]='\0'; }
}
, perchè secondo me 1 vettore di caratteri va inizzializzato con il carattere nullo \0 no?!:help:
Matrixbob
10-03-2007, 18:57
se inizializzi solo il primo carattere, non è detto che gli altri non siano sporchi, per cui si usa memset, che inizializza tutti i caratteri con '\0'
Quindi memset fa già quello che io ho fatto nella mia funzioncina?!
Cancello la mia funzione e uso memset?!
Matrixbob
10-03-2007, 18:59
Per riempirlo è meglio che usi la versione sicura di strcpy,ovvero strncpy che ti aiuta a prevenire pericolosi buffer overflow.
Ovvero come si usa sta strncopy?!
Non so se è corretto, ma io faccio così:
titolo_str[0]='\0';
strcpy(titolo_str, "##### TITOLO DEL ITEM #####\n");
Forse è meglio usare la strcat?!
Secondo me no, perchè se il buffer è sporco, nel concatenare può fare dei casini.Non vedo come possa fare casini. strcpy() copia tutti i caratteri della stringa sorgente, nullo compreso.
Es.
char str[50];
strcpy (str, "Hello");
strcat (str, " World");
è più che corretto.
xorshadow
10-03-2007, 23:36
Non vedo come possa fare casini. strcpy() copia tutti i caratteri della stringa sorgente, nullo compreso.
Es.
char str[50];
strcpy (str, "Hello");
strcat (str, " World");
è più che corretto.
Nel tuo esempio è impossibile che ci siano problemi, visto che stai passando al buffer una stringa costante.
Metti il caso, invece, che tu stia facendo un'applicazione di rete e che debba copiare il contenuto di una stringa ricevuta in input dall'utente.
Nel migliore delle ipotesi l'utente ingenuamente passa una stringa più lunga del tuo buffer e il programma va in crash.
Nel peggiore dei casi, invece, trovi un hacker che ti provoca un bel buffer overflow e prende il controllo della tua macchina.
Quindi è buona norma scordarsi completamente della strcpy e usare strncpy che permette di limitare il numero di caratteri copiati nel tuo buffer.
DanieleC88
11-03-2007, 08:07
Per inizializzare un buffer si fa così di solito:
memset(buffer, 0, DIMENSIONE_BUFFER);
riempie TUTTO il buffer di zeri e non solo il primo carattere.
Alternativamente, invece che malloc(), potrebbe anche usare calloc() al momento dell'allocazione, visto che azzera da sola il contenuto della memoria allocata.
Matrixbob
11-03-2007, 13:11
Come diceva qualcuno è 1 apz che cicla con quei buffer che erano variabili globali.
Quindi ho pensato di cambiare tecnica adesso:
ho fatto che togliere i buffer di dimensioni fisse, ed adopero la seguente tenica adesso:
bla bla bla
lunghezza=strlen("");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
sprintf(str_tmp, "e%d = ImageReader(\"no_input.png\",0,250,25.00).ConvertToYV12()\n", count_item);
strcat(enclosure_str, str_tmp);
free(str_tmp);
bla bla bla
Speriamo di non aver fatto 1 :oink: !!! :O
Matrixbob
11-03-2007, 13:13
Alternativamente, invece che malloc(), potrebbe anche usare calloc() al momento dell'allocazione, visto che azzera da sola il contenuto della memoria allocata.
Ehm ... la malloc proprio non l'ha menzionata nessuno. :)
[PS]
Ma mettere tutti \0 equivale a riempire la stringa di 0?!
DanieleC88
11-03-2007, 13:21
Ehm ... la malloc proprio non l'ha menzionata nessuno. :)
[PS]
Ma mettere tutti \0 equivale a riempire la stringa di 0?!
Primo, dal momento che ti preoccupavi di azzerare la stringa con memset() deducevo che tale operazione non fosse stata già effettuata prima, quindi presumevo che l'allocazione fosse stata fatta con malloc(): facendola con calloc() non hai bisogno di azzerare niente.
Secondo, '\0' è una sequenza di escape, e non va a riempire ogni carattere della stringa con il carattere '0' (ASCII 49), ma con un carattere non visualizzabile che indica un carattere nullo (ASCII 0, usato appunto come terminatore di stringa dalle operazioni del C).
Matrixbob
11-03-2007, 13:43
Primo, dal momento che ti preoccupavi di azzerare la stringa con memset() deducevo che tale operazione non fosse stata già effettuata prima, quindi presumevo che l'allocazione fosse stata fatta con malloc(): facendola con calloc() non hai bisogno di azzerare niente.
La definizione di 1 VAR globale è lo stesso di una malloc?! :mbe:
Secondo, '\0' è una sequenza di escape, e non va a riempire ogni carattere della stringa con il carattere '0' (ASCII 49), ma con un carattere non visualizzabile che indica un carattere nullo (ASCII 0, usato appunto come terminatore di stringa dalle operazioni del C).
Ma quindi il memset come l'andavo a richiamare per avere 1 risultato equivalente alla mia funzione:
//richiamata
pulisci_str(stringa, SIZEBUF);
//definita
void pulisci_str(char *stringa, int lunghezza)
{
int i;
for (i=0; i<lunghezza; ++i) { stringa[i]='\0'; }
}
:confused:
memset(buffer, 0, DIMENSIONE_BUFFER);
oppure
memset(buffer, '\0', DIMENSIONE_BUFFER);
Matrixbob
11-03-2007, 13:46
Ma soprattutto, questa tecnica ora è corretta, funziona?!
bla bla bla
lunghezza=strlen("");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
sprintf(str_tmp, "e%d = ImageReader(\"no_input.png\",0,250,25.00).ConvertToYV12()\n", count_item);
strcat(enclosure_str, str_tmp);
free(str_tmp);
bla bla bla
Matrixbob
11-03-2007, 14:50
ARRIVANO I GUAI: pare che la sprintf mi scazzi le stringhe!
Pezzo del mio codice:
lunghezza=strlen("##### TITOLO DEL ITEM #####\n");
titolo_str=(char*) calloc(lunghezza, sizeof(char));
strcpy(titolo_str, "##### TITOLO DEL ITEM #####\n");
printf("titolo_str: %s\n", titolo_str);
getchar();
lunghezza=strlen("");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
printf("str_tmp1: %s\n", str_tmp);
printf("canale_titolo: %s", canale_titolo);
getchar();
sprintf(str_tmp, "bottom_subs%d = Subtitle(bottom,\"\"\"%s\\n", count_item, canale_titolo);
printf("str_tmp2: %s\n", str_tmp);
getchar();
strcat(titolo_str, str_tmp);
printf("titolo_str: %s\n", titolo_str);
getchar();
free(str_tmp);
http://img88.imageshack.us/img88/2704/imgoo5.gif
Cavolo mi sono proprio impastato!!! :help:
Qui ho proprio bisogno di 1 vostro aiuto.
Forse le stringhe che hanno a che fare con sprintf è meglio se le lascio di dimensione fissa sovradimensionata?!
Matrixbob
11-03-2007, 15:13
Adesso ho fatto così, ma ho paura che scazzi nuovamente quando i %s e %d vengono sostituiti: :(
lunghezza=strlen("##### TITOLO DEL ITEM #####\n");
titolo_str=(char*) calloc(lunghezza, sizeof(char));
strcpy(titolo_str, "##### TITOLO DEL ITEM #####\n");
lunghezza=strlen("bottom_subs%d = Subtitle(bottom,\"\"\"%s\\n");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
sprintf(str_tmp, "bottom_subs%d = Subtitle(bottom,\"\"\"%s\\n", count_item, canale_titolo);
strcat(titolo_str, str_tmp);
free(str_tmp);
... però attendo fiducioso da voi il giusto verbo!! :D
xorshadow
11-03-2007, 16:18
Adesso ho fatto così, ma ho paura che scazzi nuovamente quando i %s e %d vengono sostituiti: :(
lunghezza=strlen("##### TITOLO DEL ITEM #####\n");
titolo_str=(char*) calloc(lunghezza, sizeof(char));
strcpy(titolo_str, "##### TITOLO DEL ITEM #####\n");
lunghezza=strlen("bottom_subs%d = Subtitle(bottom,\"\"\"%s\\n");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
sprintf(str_tmp, "bottom_subs%d = Subtitle(bottom,\"\"\"%s\\n", count_item, canale_titolo);
strcat(titolo_str, str_tmp);
free(str_tmp);
... però attendo fiducioso da voi il giusto verbo!! :D
Il problema in realtà è un pò più complesso.
Tu vuoi copiare una stringa di cui non conosci a priori la lunghezza (a causa della formattazione di sprintf) . Dovresti fare così:
1) Usi snprintf e non sprintf che ti permette di limitare il caratteri copiati (guardati il manuale per sapere come funziona)
2) Algoritmo "serio" : crei un buffer di dimensioni piccole(anche 0 byte) con malloc, copi la stringa con snprintf , guardi il valore di ritorno, se questo è maggiore della dimensione del buffer vuol dire che il buffer non bastava e la stringa è stata troncata, in questo caso devi riallocare il buffer creandolo più grande (pari al valore di ritorno dell snprintf+1) e riprovi a fare la copia.
lunghezza=strlen("");
str_tmp=(char*) calloc(lunghezza, sizeof(char));
sprintf(str_tmp, "e%d = ImageReader(\"no_input.png\",0,250,25.00).ConvertToYV12()\n", count_item);
strcat(enclosure_str, str_tmp);
free(str_tmp);
E' errato...allochi a str_tmp un solo byte...in quanto lunghezza è pari a 1.
L'unico modo per dimensionare in modo corretto la stringa è convertire prima su un buffer temporaneo count_item.
char template[] = "e%d = ImageReader(\"no_input.png\",0,250,25.00).ConvertToYV12()\n";
str_tmp = (char *)malloc(12 * sizeof(char));
sprintf(str_tmp, "%d", count_item);
lunghezza = strlen(str_tmp) + strlen(template) - 2; //-2 perché tolgo i caratteri dovuti a "%d"
free(str_temp);
str_tmp = (char *)malloc((lunghezza + 1) * sizeof(char));
sprintf(str_tmp, template, count_item);
strcat(enclosure_str, str_tmp);
free(str_temp);
Ricordati che perà enclosure_str deve avere abbastanza spazio per contenere anche l'altra stringa..
xorshadow
11-03-2007, 19:29
Come ho già detto prima (versione semplificata e senza error check):
nchars = snprintf(NULL, 0, "Quello che %s devi %d formattare", arg1, arg2);
char* buff = malloc(nchars + 1);
snprintf(buff,nchars + 1,"Quello che %s devi %d formattare", arg1, arg2);
Semplice, veloce (la versione non semplificata che ti ho suggerito su può essere più veloce), riutilizzabile. Tutto qui.
Interessante questa snprintf...non la conoscevo. Ho visto che è anche nello standard C99, ottimo ;)
Matrixbob
11-03-2007, 19:59
Bene bene, s'imparano sempre delle belle cose.
C'è anche la matrixNbob function?! :sofico:
Mi farò 1 bel stamp di questo 3D poi come promemoria. :)
DanieleC88
11-03-2007, 21:07
il carattere '\0' corrisponde al valore ascii zero, quindi riempire una stringa di caratteri '\0' equivale ad assegnare a ciascun byte il valore 0.
E io che avevo scritto? :p :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.