|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 | |
|
Senior Member
Iscritto dal: Jun 2008
Città: Pordenone (PN)
Messaggi: 3699
|
[C] Piccolo aiuto con le stringe
Ciao a tutti! Son tornato con qualche altro dubbio. Sto cercando di provare le varie funzioni presenti in C riguardo le stringhe, come ad esempio la "strcmp" utilizzata per il confronto tra due stringhe. Sto quindi provando a fare una semplice funzioncina che prende in ingresso due stringhe e fa il confronto. Questo è il codice che ho scritto:
Quote:
Grazie, Hieicker
__________________
PC» PSU: Evga Supernova GQ 750W | CPU: Intel Core i5 6600k | MOTHERBOARD: AsRock Z170 Extreme 4 | RAM: HyperX Fury 16Gb DDR4 2666Mhz | VGA: Gigabyte GTX1070 G1 Playstation 4 | PSN Gamertag: Hieicker
Ultima modifica di Hieicker : 16-01-2013 alle 15:57. |
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Jun 2008
Città: Pordenone (PN)
Messaggi: 3699
|
Ok grazie Antonio, anche se non ho ben presente cosa intendi con "terminatore". Comunque se vedi, la parte di codice in cui dovrei inserire il numero, attualmente è commentata, quindi non viene applicata.
__________________
PC» PSU: Evga Supernova GQ 750W | CPU: Intel Core i5 6600k | MOTHERBOARD: AsRock Z170 Extreme 4 | RAM: HyperX Fury 16Gb DDR4 2666Mhz | VGA: Gigabyte GTX1070 G1 Playstation 4 | PSN Gamertag: Hieicker
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: May 2008
Città: Torino - Valenza (AL)
Messaggi: 1221
|
prova ad usare
stringa = (char*) malloc((numero+1)*sizeof(char)) perchè ti serve anche il terminatore di stringa '/0' poi non ho capito alcune cose del codice: la funzione push_stringa(stringa) quando la usi? fai la malloc solo per stringa e non per stringa2? se specifichi n caratteri per la stringa poi non controlli che l'utente ne inserisca davvero (al massimo) n-1, ricadendo quindi nell'errore del terminatore mancante. Credo che il sigseg ti venga fuori proprio perchè una volta premuto invio, provi a mettere n+1 caratteri in un'area di memoria grande n, quindi cerchi di accedere ad un'area "vietata" (spiegato un po' a cazzo di cane perchè a lezione stavo poco attento, mi bastava che i programmi che facevo funzionassero )EDIT: Quote:
comunque se la parte commentata non viene applicata, tu crei soltanto due puntatori a stringa, non allochi lo spazio per scriverci dentro (cosa che faresti con la malloc commentata) EDIT2: sono andato a rinfrescarmi la memoria. prova ad usare anche la fgets(stringa,numero,stdin) che legge numero caratteri dallo standard input Ultima modifica di M@Rk0 : 16-01-2013 alle 16:22. |
|
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Dal listato sembra che manchi l'allocazione della memoria (malloc()) per
char *stringa; char *stringa2; se l'input delle stringhe, suppongo, dovrebbe avvenire con la funzione push_stringa(stringa); (e stringa2 ??) forse lo fai li dentro (allora manca '*' e '&') Se invece utilizzi solo la (come sembra dal codice) confronta_stringa() allora ti manca sicuramente la malloc per le 2 stringhe (la scanf non alloca spazio).
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#5 | |
|
Bannato
Iscritto dal: Dec 2012
Messaggi: 41
|
Quote:
![]() Tornando, nella funzione confronta_stringa().. Codice:
int numero;
printf("quanti caratteri devono comporre la stringa?\n");
scanf("%d", &numero);
stringa = (char*) malloc(numero*sizeof(char));
Ora se quello che sto dicendo non sono boiate dovresti dichiarare una terza stringa interna a quella funzione. |
|
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Manca la malloc di stringa2 e lo spazio per il terminatore (\0).
Inoltre ti conviene impostare a size dei caratteri da accettare con la scanf() per non incorrere in un buffer overflow. percio' se allochi numero*sizeof(char) dovrai avere in input numero*sizeof(char)-1 @stohuman Si puo' riallocare un spazio gia' allocato con la "realloc"
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#7 |
|
Bannato
Iscritto dal: Dec 2012
Messaggi: 41
|
Ero a conoscenza solo di malloc e calloc, sto ancora studiando questa parte
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Quote:
È comunque buona pratica fare come dici tu Lo specifico perchè quando io ho studiato sta cosa nessuno me lo aveva detto e sono diventato matto per capire come mai se allocavo un array di char andava e se lo facevo uguale con degli interi mi dava problemi.
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Jun 2008
Città: Pordenone (PN)
Messaggi: 3699
|
Ragazzi grazie a tutti per il prezioso aiuto
La funzione push_stringa è una cosa a parte, quindi non tenetene conto
__________________
PC» PSU: Evga Supernova GQ 750W | CPU: Intel Core i5 6600k | MOTHERBOARD: AsRock Z170 Extreme 4 | RAM: HyperX Fury 16Gb DDR4 2666Mhz | VGA: Gigabyte GTX1070 G1 Playstation 4 | PSN Gamertag: Hieicker
|
|
|
|
|
|
#10 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
[quote=darksax;38872526]
... percio' se allochi numero*sizeof(char) dovrai avere in input [b]numero*sizeof(char)-1 mi autoquoto Per chiarezza si dovrebbe scrivere numero*sizeof(char) - sizeof(char)
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: May 2008
Città: Torino - Valenza (AL)
Messaggi: 1221
|
[quote=darksax;38873192]
Quote:
![]() comunque il problema sussiste sempre se non c'è un controllo su quanti caratteri verranno poi immessi da tastiera, quindi consiglierei l'uso di fgets(stringa,numero,stdin) |
|
|
|
|
|
|
#12 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Ed in ultimo...
utilizzando la malloc devi ricordarti della free()
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: May 2008
Città: Torino - Valenza (AL)
Messaggi: 1221
|
comunque se è un programma fine a se stesso per testare le funzioni che operano su stringhe, tanto vale barare:
non inizializzi i due puntatori a stringa nel main, la funzione perde gli argomenti, e nella funzione inizializzi le due stringhe con Codice:
char stringa[numero+1]; char stringa2[numero+1];
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Jun 2008
Città: Pordenone (PN)
Messaggi: 3699
|
Ciao ragazzi! Aggiornamento. Ho allocato le due stringhe ed ora la funzione sembra svolgere le sue istruzioni egregiamente. Tuttavia come dite voi potrei ottimizzarla ulteriormente. Innanzitutto non ho usato un terminatore. Nel manuale che sto leggendo non è ancora stato nominato, quindi vi chiedo... A che scopo viene utilizzato?
Inoltre non ho ben capito se sbaglio qualcosa nella alloc o nel modo in cui gli passo l'input. Ecco il codice. Ho aggiunto le due funzioni free per deallocare la memoria alla fine della funzione. Quote:
__________________
PC» PSU: Evga Supernova GQ 750W | CPU: Intel Core i5 6600k | MOTHERBOARD: AsRock Z170 Extreme 4 | RAM: HyperX Fury 16Gb DDR4 2666Mhz | VGA: Gigabyte GTX1070 G1 Playstation 4 | PSN Gamertag: Hieicker
|
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jul 2003
Città: Alessandria
Messaggi: 10167
|
Lo '\0' viene utilizzato semplicemente per indicare la fine di una stringa.
Può essere utile in altre funzioni o in altri casi per capire quando la stringa è finita ( ad esempio strlen ritorna il numero di caratteri della stringa fino al terminatore '\0' -escluso ).
__________________
Dell XPS 13 (9350) :: i5-2500K - HD6870 - AsRock Z68 Pro3 - Corsair Vengeance 8GB (4x2) DDR3 :: Samsung Galaxy S4 GT-i9505
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: May 2008
Città: Torino - Valenza (AL)
Messaggi: 1221
|
il terminatore di stringa '\0' (carattere che corrisponde a NULL) serve alle funzioni (anche quelle che potresti scrivere tu!) per sapere dove finisce una stringa (come strlen ad esempio).
Quando dici char stringa[10]; quello che succede è (in parole povere) che viene allocata in memoria un'area contigua di 10 Byte. Magari in quei 10 Byte prima c'era scritto qualcosa che non è più utilizzato, e c'è rimasto. Infatti se provi a fare un programma che alloca una stringa e poi la stampa direttamente vedrai che marasma di caratteri senza senso ti può venir fuori. ES: questa è la memoria prima di fare char stringa[10]; Codice:
Indirizzi di memoria: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |... ------------------------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--- Contenuto: # | @ | 3 | x | + | ù | * | # | # | ò | ç | : | % | & | £ | € |... mettiamo che alla richiesta di allocazione di memoria, lo scheduler del Sistema Operativo assegni lo spazio [3,4,5,6,7,8,9,A,B,C]. Ora, se fai printf("%c",stringa[0]); il risultato sarà il carattere 'x'. mentre con printf("%s",stringa); darà in output "x+ù*##òç:%". se a questo punto fai scanf("%s", stringa); e scrivi "ciao", il contenuto della memoria sarà questo: Codice:
Indirizzi di memoria: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |... ------------------------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--- Contenuto: # | @ | 3 | c | i | a | o | \0| # | ò | ç | : | % | & | £ | € |... ora la printf di stringa darà in output "ciao", perchè legge fino al terminatore. se il terminatore non fosse stato aggiunto (in automatico dalla scanf), avresti stampato "ciao##òç:%" il terminatore serve ad esempio anche per leggere manualmente una stringa, magari carattere per carattere facendo un ciclo Codice:
int i=0;
while(stringa[i]!='\0')
{
fai_qualcosa(argomento1,argomento2);
i++;
}
ah ho visto ora il reply di kwb (che quando ho iniziato a scrivere non c'era) e in sostanza ho detto quello
Ultima modifica di M@Rk0 : 17-01-2013 alle 22:22. |
|
|
|
|
|
#17 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Inoltre la scanf() al termine dell'input di una stringa inserisce il terminatore.
Quindi se inserisci 10 caratteri in realta ne ritrovi 11... Ecco spiegato xche' i buffer stringa e stringa2 devono prevedere nella malloc un "+sizeof(char)"... stringa = (char*) malloc(numero*sizeof(char)); stringa2 = (char*) malloc(numero*sizeof(char)); Facendo cosi' sei a rischio....(prima o poi vai in crash)
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#18 |
|
Member
Iscritto dal: Jan 2008
Città: Roma
Messaggi: 126
|
Riprendendo l'esempio di M@Rk0, prova ad immaginare se le due variabili stringa siano allocate in modo contiguo nella memoria (stringa seguita dal buffer stringa2) ma inserite nell'ordine stringa2 e poi stringa e ricordando che la scanf aggiunge un \0 alla fine dell'input. Ammettiamo che la malloc ritorni questi 2 puntatori Codice:
*stringa = 0x02 *stringa2 = 0x0c Codice:
0 1 2 3 4 5 6 7 8 9 a b c d e f 0000 . . . . . . . . . . . . s t r i 0010 n g a _ 2 2 \0 . . . . . . . . . Codice:
0 1 2 3 4 5 6 7 8 9 a b c d e f 0000 . . s t r i n g a _ 1 1 \0 t r i 0010 n g a _ 2 2 \0 . . . . . . . . . Quale sara' il confronto? *stringa = 0x02 vale "stringa_11" *stringa2 = 0x0c vale "" Quindi il confronto e' giustamente falso (xche' ho inserito valori differenti) ma i valori che utilizzo sono differenti da quelli che mi aspetto!!!! Ma sopratutto se dopo Stringa2 la zona di memoria era occupata da un'altra variabile (x esempio un'altro puntatore) utilizzando quest'ultima variabile avrei un risultato catastrofico Questo e' il famoso Buffer Overflow ed e' uno dei bachi piu' facili da generare e piu' difficili da trovare, anche xche' normalmente l'errore ti si presenta a km di distanza dalla parte di codice sbagliata....
__________________
La forza dei forti sta nel traversare le traversie con occhio sereno! (PK) ... I computer sono esattamente come gli esseri umani: fanno qualsiasi cosa tranne che pensare. (John Van Neumann) Siamo brevi, il mondo è sovraffollato di parole. (Stanisław Jerzy Lec) |
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Jun 2008
Città: Pordenone (PN)
Messaggi: 3699
|
Eccomi
Lo stato attuale della funzione è il seguente: int confronta_stringa(char *stringa, char *stringa2){ int numero; printf("quanti caratteri devono comporre ogni stringa?\n"); scanf("%d", &numero); stringa = (char*) malloc(numero*sizeof(char)); stringa2 = (char*) malloc(numero*sizeof(char)); printf("Inserisci la prima stringa\n"); scanf("%s", stringa); printf("inserisci la seconda stringa\n"); scanf("%s", stringa2); if (!strcmp(stringa, stringa2)) printf("Le stringe da te inserite sono uguali"); free(stringa); free(stringa2); return 0; } Da quello che ho capito, usando la scanf non devo utilizzare il terminatore perchè lo aggiunge da sola giusto? Tuttavia devo controllare che non venga inserito una stringa più grande dello spazio allocato. Che tipo di controllo posso mettere? Come si autogestisce la macchina in questo caso? Grazie
__________________
PC» PSU: Evga Supernova GQ 750W | CPU: Intel Core i5 6600k | MOTHERBOARD: AsRock Z170 Extreme 4 | RAM: HyperX Fury 16Gb DDR4 2666Mhz | VGA: Gigabyte GTX1070 G1 Playstation 4 | PSN Gamertag: Hieicker
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 11:23.











)









