PDA

Visualizza la versione completa : [C] Uso di puntatore a puntatore per la duplicazione di stringhe


Lasentinella
19-05-2007, 13:21
Ho un main con


char **t;
int n
printf("Quante stringhe vuoi inserire?");
scanf("%d",&n);
t=leggi(n);


e il seguente metodo che, da 0 a n-1, fa inserire all'utente le stringhe, poi le duplica con strdup() e le assegna ad un puntatore di puntatore. Infine, restituisce il punt. di punt.
(Devo farlo per scuola, quindi devo per forza usare questa sequenza di passi!)



char **leggi(int n){
int i;
char **p=malloc(n*sizeof(char));
char *s;

for(i=0;i<n;i++){
printf("Stringa n. %d: ",i+1);
scanf("%s",&s);
p[i]=strdup(s);
}

for(i=0;i<n;i++)
printf("%c",p[i]);

return p;
}


ho aggiunto alla fine la stampa di p[] per vedere se la duplicazione funziona...ma niente da fare :cry: Cosa avrò sbagliato? Mi viene da pensare che sia sbagliato il malloc...ma non capisco!!
Grazie :ciauz:

UltraBeginner
19-05-2007, 13:48
Originariamente inviato da Lasentinella
Ho un main con


char **t;
int n
printf("Quante stringhe vuoi inserire?");
scanf("%d",&n);
t=leggi(n);


e il seguente metodo che, da 0 a n-1, fa inserire all'utente le stringhe, poi le duplica con strdup() e le assegna ad un puntatore di puntatore. Infine, restituisce il punt. di punt.
(Devo farlo per scuola, quindi devo per forza usare questa sequenza di passi!)



char **leggi(int n){
int i;
char **p=malloc(n*sizeof(char));
char *s;

for(i=0;i<n;i++){
printf("Stringa n. %d: ",i+1);
scanf("%s",&s);
p[i]=strdup(s);
}

for(i=0;i<n;i++)
printf("%c",p[i]);

return p;
}


ho aggiunto alla fine la stampa di p[] per vedere se la duplicazione funziona...ma niente da fare :cry: Cosa avrò sbagliato? Mi viene da pensare che sia sbagliato il malloc...ma non capisco!!
Grazie :ciauz:

Ciao Sentinella,
questo codice dovrebbe funzionare



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

char **leggi(int n){
int i;
char **p=(char **)malloc(n*sizeof(char *));
char *s=(char *)malloc(sizeof(char)*80);


for(i=0;i<n;i++){
printf("Stringa n. %d: ",i+1);
scanf("%s",s);
p[i]=(char *)malloc(sizeof(char)*strlen(s));
strcpy(p[i],s);
}

for(i=0;i<n;i++)
printf("%s",p[i]);

free(s);
return p;

}

int main()
{

char **t;
int n;
printf("Quante stringhe vuoi inserire?");
scanf("%d",&n);
t=leggi(n);

system("pause");

}


In particolare hai fatto questi errori:
char **p=malloc(n*sizeof(char)); // non hai detto a malloc che tipo di puntatore restituire e hai specificato il sizeof in maniera errata. In questo caso malloc deve restituire un puntatore a puntatore e deve allocare memoria per ospitare puntatori a carattere non a caratteri.

char **p=(char **)malloc(n*sizeof(char *));

char *s; // non hai allocato la memoria per questo puntatore
scanf("%s",&s); // quando passi una stringa o un vettore alla scanf non devi usare & perchè è sufficiente passare s che contiene l indirizzo della prima cella del vettore/stringa
printf("%c",p[i]); // per stampare la stringa devi usare %s

Spero di esserti stato di aiuto, buon fine settimana! :ciauz: :ciauz:

Lasentinella
19-05-2007, 17:03
Grazie infinite, ora funziona :)
Ti chiedo un altro piccolo aiuto..
Dopo la lettura delle stringhe si passa al nuovo metodo la prima posizione e l'ultima come parametri:



selsort(v,v+n-1);


La funzione sel sort è questa:



void selsort(char **begin, char **end){

for(;begin<end;begin++){
swap(begin, begin[pos_min(begin,end)]);
}


Per ogni elemento dell'array, scambia l'elemento stesso col minore degli elementi successivi (non so spiegarlo bene...QUI (http://it.wikipedia.org/wiki/Selection_sort) trovi la descrizione del "Selection Sort"..ma magari lo conosci già :fighet: )


Il primo problema è che compilando ottengo l'errore "conflicting types for pos_min"...ti scrivo anche lo swap, perché anche con questo metodo ottengo lo stesso errore.



void swap(char **a, char **b){
char **papp;
**papp=**a;
**a=**b;
**b=**papp;
}


Risolto questo problema dovrei aver finito, penso :zizi:
Grazie ancora!

p.s.
Ma se te sei UltraBeginner io cosa sono? :cry:

Lasentinella
20-05-2007, 13:37
Risolto da solo il problema precedente, ora il problema finale ( :cry: ):


void swap(char **a, char **b){

char **papp;
papp=a;
a=b;
b=papp;
printf("SCAMBIO : %s - %s\n",*a,*b);

}

Questo codice, richiamato da selsort, scambia **a e **b. Se inserisco 's' e 'a', leggo infatti:
SCAMBIO: a - s.
Quando, però, torno a selsort, è come se non li avessi scambiati. Riottengo s e a!!!!!!!
Il selsort è questo:


void selsort(char **begin, char **end){

for(;begin<end;begin++){
swap(begin, pos_min(begin,end));

}

}
Com'è possibile che non memorizzi lo scambio?? :confused:

UltraBeginner
20-05-2007, 13:41
Originariamente inviato da Lasentinella
Grazie infinite, ora funziona :)
Ti chiedo un altro piccolo aiuto..
Dopo la lettura delle stringhe si passa al nuovo metodo la prima posizione e l'ultima come parametri:



selsort(v,v+n-1);


La funzione sel sort è questa:



void selsort(char **begin, char **end){

for(;begin<end;begin++){
swap(begin, begin[pos_min(begin,end)]);
}


Per ogni elemento dell'array, scambia l'elemento stesso col minore degli elementi successivi (non so spiegarlo bene...QUI (http://it.wikipedia.org/wiki/Selection_sort) trovi la descrizione del "Selection Sort"..ma magari lo conosci già :fighet: )


Il primo problema è che compilando ottengo l'errore "conflicting types for pos_min"...ti scrivo anche lo swap, perché anche con questo metodo ottengo lo stesso errore.



void swap(char **a, char **b){
char **papp;
**papp=**a;
**a=**b;
**b=**papp;
}


Risolto questo problema dovrei aver finito, penso :zizi:
Grazie ancora!

p.s.
Ma se te sei UltraBeginner io cosa sono? :cry:

Reciao lasentinella,

ecco il codice corretto



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

void selection(char ** a, unsigned long N);

char **leggi(int n){
int i;
char **p=(char **)malloc(n*sizeof(char *));
char *s=(char *)malloc(sizeof(char)*80);


for(i=0;i<n;i++){
printf("Stringa n. %d: ",i+1);
scanf("%s",s);
p[i]=(char *)malloc(sizeof(char)*strlen(s));
strcpy(p[i],s);
}

printf("\n\nStampo la matrice allocata dinamicamente non ordinata\n");
for(i=0;i<n;i++)
printf("%s\n",p[i]);

free(s);
return p;

}

int main()
{

char **t;
int n,i;
printf("Quante stringhe vuoi inserire?");
scanf("%d",&n);
t=leggi(n);
selection(t,n);

printf("\n\nStampo la matrice allocata dinamicamente ordinata con il selection sort\n");
for(i=0;i<n;i++)
printf("%s\n",t[i]);

system("pause");

}

void selection(char ** a, unsigned long N) {

int i, j, min;
char temp[80];

for (i=0; i < N-1; i++)
{
min = i;
for (j= i + 1; j < N; j++)
if (strcmp(a[j],a[min])<0)
min = j;

strcpy(temp,a[min]);
strcpy(a[min],a[i]);
strcpy(a[i],temp);
}
}


[QUOTE]Il primo problema è che compilando ottengo l'errore "conflicting types for pos_min"...ti scrivo anche lo swap, perché anche con questo metodo ottengo lo stesso errore.[\QUOTE]

Bhe, perchè come secondo elemento devi passare la dimensione (ovvero il numero di righe) della tua matrice allocata dinamicamente, valore che richiedi all utente e che poi vai a mettere nella variabile n. Puoi vedere infatti che io ho passato come parametri l inizio della nostra matrice (e cioe il puntatore a puntatore t nella funziona main) e il numero di righe n.

Dopo di che per implementare il selection sort è bastato seguire la guida di wikipedia e fare in modo che la funzione li riportata funzionasse con le stringhe.

Buona domenica! :ciauz:



p.s.
Io sono sempre UltraBeginner (scrivo codice solo da 1 anno e mezzo!). Però un consiglio te lo posso dare: leggi tutti i post di questo forum, imparerai un sacco di cose anche perchè qui ci sono persone serie e disponibili, oserei dire dei veri e propri maestri tra cui ti posso citare Oregon, MItaly, fastcode, Andbin,Xaratroom,King64 e tanti altri di cui non ricordo il nick. Detto questo in gamba e buona programmazione!!! :) :)

Lasentinella
20-05-2007, 14:27
Acc, siamo riusciti a scrivere il post nello stesso momento...i tuoi suggerimenti sono stati utilissimi, ho un solo problema: Le funzioni richieste sono tutte puntatori a puntatori...ti scrivo il codice :


char **leggi_stringhe(int n){
int i;
char **p=(char **)malloc(n*sizeof(char*));
char *s=(char *)malloc(sizeof(char)*80);

for(i=0;i<n;i++){
printf("Stringa n. %d: ",i+1);
scanf("%s",s);
p[i]=(char *)malloc(sizeof(char)*strlen(s));
p[i]=strdup(s);
}

free(s);

return p;
}

void selsort(char **begin, char **end){

for(;begin<end;begin++){
swap(begin, pos_min(begin,end));

}

char **pos_min(char **begin, char **end){


char **res;
char **w;
char **app;
res = begin+1;

for (w=begin; w<end; w++){
if (strcmp(*w, *res)< 0)
res=w;

}

return res;

}

void swap(char **a, char **b){

char **papp;
papp=a;
a=b;
b=papp;
printf("SCAMBIO : %s - %s\n",*a,*b);

}

void stampa_stringhe(char **t, int n){
int i;
for(i=0;i<n;i++)
printf("%s",t[i]);

}

void elimina(char **p, int n){
int i;
for(i=0;i<n;i++)
free(p[i]);
free(p);
}

int main(void)
{
char **v;
int n;
printf("Numero di stringhe da ordinare: ");
scanf("%d", &n);
v=leggi_stringhe(n);
if( v!=NULL ) {
selsort(v,v+n-1); // Ordina
printf( "\nVettore ordinato:\n" );
stampa_stringhe(v,n); // Stampa
elimina(v,n); // Libera la memoria
}
else printf( "Input fallito." );
system("PAUSE");
}



L'unico problema che ho è che la funzione SWAP scambia correttamente le due stringhe ma, tornando alla funzione chiamante (selsort), le due stringhe tornano ad essere nelle posizioni iniziali. La cosa non è strana?
Cioé, se io inserisco 's' e poi 'a', swap le scambia (e infatti la printf lo dimostra), ma tornati al selsort, 's' torna ad essere in prima posizione e 'a' in seconda.
:cry:

Grazie ancora, sei gentilissimo! Buona domenica anche a te :)

oregon
20-05-2007, 14:34
La swap deve essere



void swap(char **a, char **b)
{
char *papp;

papp=*a;
*a=*b;
*b=papp;
}


Controlla tu il perche' ...

Lasentinella
20-05-2007, 14:48
Originariamente inviato da oregon
La swap deve essere



void swap(char **a, char **b)
{
char *papp;

papp=*a;
*a=*b;
*b=papp;
}


Controlla tu il perche' ...
*a dovrebbe indicare il contenuto del puntatore (il valore a cui punta), ma
papp=*a; non dovrebbe voler dire fai puntare papp al contenuto di a? Non si dovrebbe fare o papp=a; oppure *papp=*a ?

oregon
20-05-2007, 14:57
Originariamente inviato da Lasentinella
*a dovrebbe indicare il contenuto del puntatore (il valore a cui punta)

In questo caso, il valore a cui punta a e' a sua volta un puntatore ... (ricorda che a e' un doppio puntatore)



papp=*a; non dovrebbe voler dire fai puntare papp al contenuto di a? Non si dovrebbe fare o papp=a; oppure *papp=*a ?

Questa non l'ho capita ...

UltraBeginner
20-05-2007, 15:07
Originariamente inviato da Lasentinella
*a dovrebbe indicare il contenuto del puntatore (il valore a cui punta), ma
papp=*a; non dovrebbe voler dire fai puntare papp al contenuto di a? Non si dovrebbe fare o papp=a; oppure *papp=*a ?

Forse un disegnino puo spiegare la situazione

dop.punt punt. a char stringa di char
(a)1 --> 3 --> ziao

(b)2 --> 4 --> ciao

come vedi facendo

papp=*a;
*a=*b; // scambio
*b=papp;

metti nel puntatore di appoggia papp quello a cui punta a (il valore 3). Poi scambi i valori a cui puntano a e b. Alla fine riponi nella casella a cui punta b il valore di a.

Dopo queste operazioni avrai la seguente situazione

dop.punt punt. a char stringa di char
(a)1 --> 4 --> ciao

(b)2 --> 3 --> ziao

ovvero ora facendo *a punterai alla casella di memoria 4 che puntava a ciao.

Spero sia chiaro, non sono proprio Giotto io! :D


:ciauz:

Loading