PDA

View Full Version : [C]aiuto per esercizio


---Kat999---
24-05-2007, 15:18
Salve a tutti, avrei bisogno di una mano con un esercizio C riguardo l'allocazione dinamica della memoria visto che tra poco ho l'esame appunto di C.

Premetto che ho iniziato a programmare da relativamente poco, quindi mi scuso se vi potrà sembrare una cosa banale o stupida ma io è un po che provo a far funzionare questo programma e non ci riesco :)
L'esercizio è il secondo di questa pagina: http://www.informatica.uniroma2.it/upload/2005/LPR/IIappello.pdf

Quello che volevo provare a fare io era creare un vettore di stringhe (con dimensione immesa da input), con la dimensioni delle singole stringhe a loro volta immesse da input.

Il fatto però è che non ho per niente dimestichezza con l'allocazione dinamica della memoria (come scritto prima ho iniziato a programmare da poco), quindi la mia idea potrebbe essere semplicemente implementata male, oppure sballata sin dal principio, ditemi voi. Questo è il codice:

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

int main()
{
char *str, *p;
int nstr, lstr, i;

printf("Quante stringhe vuoi inserire: \n");
scanf("%d", &nstr);

if (nstr > 0) {

str = (char *) calloc(nstr, sizeof(char *)); /* dovrebbe allocare memoria
per un vettore di NSTR stringhe */

for ( i = 0; i < nstr; i++) {

printf("Quanto e' lunga la prossima stringa? \n");
scanf("%d", &lstr);
p = (char *) calloc(lstr, sizeof(char)); /*dovrebbe allocare memoria per la stringa lunga LSTR */
scanf("\n");
gets(p);
str[i] = (char *) calloc(lstr, sizeof(char)); /*dovrebbe allocare memoria per la stringa da copiare in str[i] */
strcpy(str[i], p); /*copio p in str[i] */

free(p);

}
}

for(i = 0; i < nstr; i++)
puts(str[i]);

for(i = 0; i < nstr; i++)
free(str[i]);

system("PAUSE");


return 0;
}


Il progr si blocca quando tenda di eseguire l'istruzione strcpy(ecc ecc)
Spero che non lo troviate troppo ridicolo :D
Cmq ad intuito direi che sbaglio sicuramente qualcosa nell'usare la variabile str, no?

ilsensine
24-05-2007, 15:25
Di do un indizio:

str[i] = (char *) calloc(lstr, sizeof(char));

Se il tuo compilatore non ti ha generato un warning su questa riga, buttalo.

Secondo indizio: str deve essere char **

andbin
24-05-2007, 15:43
Io aggiungo:
- se allochi dinamicamente spazio per la stringa devi allocare 1 byte in più per contenere il carattere nullo. Nel tuo caso 'lstr' immagino che sia il numero di caratteri escluso il nullo, quindi nella allocazione devi fare lstr+1.
- gets() è insicura, usa fgets, specificando come stream 'stdin'.
- potresti anche evitare di allocare ad ogni ciclo un blocco di memoria temporaneo.

---Kat999---
25-05-2007, 18:45
grazie per i consigli, in effetti bastava dichiarare str come ** e il programma funzionava. Poi seguendo gli altri consigli ho usato fgets ed eliminato *p che non serve a nulla :)

Anche se effettivamente non capisco bene perchè con l'uno va e l'altro no, praticamente con **str dichiaro un puntatore che contiene come valore a sua volta l'indirizzo di un altro puntatore? Cioè se avessi saputo già quante stringhe c'erano da memorizzare, invece che saperlo da input, mi sarebbe bastato dichiarare che ne so *str[4] e il progr. avrebbe funzionato no? Perchè per farlo dinamicamente devo dichiarare invece **str?

Poi un altra cosa: quando libero memoria per str alla fine, devo fare il ciclo

for ( i = 0; i < nstr; i++)
free(str[i]);


o basta scrivere free(str); ?

Grazie per gli aiuti.

andbin
25-05-2007, 20:40
Anche se effettivamente non capisco bene perchè con l'uno va e l'altro no, praticamente con **str dichiaro un puntatore che contiene come valore a sua volta l'indirizzo di un altro puntatore? Cioè se avessi saputo già quante stringhe c'erano da memorizzare, invece che saperlo da input, mi sarebbe bastato dichiarare che ne so *str[4] e il progr. avrebbe funzionato no? Perchè per farlo dinamicamente devo dichiarare invece **str?char *str[4] vuol dire "un array di 4 puntatori a char" e sarebbe appunto corretto nel caso in cui tu sapessi a priori quante stringhe al massimo devi poter gestire.

Mentre char **str vuol dire "un puntatore a puntatore a char". In questo caso devi allocare prima un array di puntatori con:

str = (char **) calloc(nstr, sizeof(char *));

e poi ad ogni puntatore dell'array devi assegnare il puntatore ad un array di char (per le stringhe).

In pratica sei in una situazione di questo tipo:
http://img476.imageshack.us/img476/1153/array2d9hf.gif

Poi un altra cosa: quando libero memoria per str alla fine, devo fare il ciclo

for ( i = 0; i < nstr; i++)
free(str[i]);


o basta scrivere free(str); ?Devi prima deallocare gli array relativi alle stringhe e poi deallocare l'array principale.

---Kat999---
26-05-2007, 10:18
perfetto, tutto claro, mucho thk :D