[C] problema di implementazione
Ragazzi sto svolgendo questo esercizio in C. Ho un problema nelle righe numero 42 e 43. C'è un modo per passare alla funzione prendi s e s[j] in modo che la funzione mi possa ritornare gli ultimi caratteri delle stringhe considerate?????....Grazie a tutti per le risposte. Il tsto è questo:
/*scrivere una funzione in linguaggio C che utilizzando l'algoritmo del "bubble sort" ordini in ordine crescente un vettore di stringhe in funzione del valore del codice ASCII dell'ultimo carattere.*/ #include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 6 void stampa(char *a[MAX]); void ordina(char *s[MAX]); char* prendi(char *a[MAX]); int main(){ char *s[MAX]={"Fogli","Telefono","sole","MOUSE","BATTERIA","Casa"}; stampa(s); ordina(s); printf("\n"); stampa(s); printf("\n"); system("pause"); return 0; } void stampa(char *s[MAX]){ int i; for(i=0;i<MAX;i++) printf("[%s] ",s[i]); return; } void ordina(char *s[MAX]){ int i,j; char *temp_swap; char *temp_1; char *temp_2; temp_1=(char*)malloc(sizeof(char)); temp_2=(char*)malloc(sizeof(char)); temp_swap=(char*)malloc(sizeof(char)); for(i=0;i<MAX;i++){ for(j=MAX-1;j>=0;j--){ temp_1=prendi(s); //In questo punto: c'è un modo per passare s[i] e s[j]????? temp_2=prendi(s); if(*temp_1 > *temp_2){ temp_swap = strcpy(temp_swap,s[i]); s[i] = strcpy(s[i],s[j]); s[j] = strcpy(s[j],temp_swap); }}} free(temp_1); free(temp_2); free(temp_swap); return; } char* prendi(char *a[MAX]){ int i; char *temp_p; temp_p=(char*)malloc(sizeof(char)); for(i=0;i<MAX;i++){ temp_p=a[i]; while(*(temp_p+1)!='\0') //In questo modo prende l'ultimo temp_p++; //carattere della stringa passata } return(temp_p); }
Risposte
"fk16":
void ordina(char *s[MAX]){ int i,j; char *temp_swap; char *temp_1; char *temp_2; temp_1=(char*)malloc(sizeof(char)); temp_2=(char*)malloc(sizeof(char)); temp_swap=(char*)malloc(sizeof(char)); for(i=0;i<MAX;i++){ for(j=MAX-1;j>=0;j--){ temp_1=prendi(s); //In questo punto: c'è un modo per passare s[i] e s[j]????? temp_2=prendi(s); if(*temp_1 > *temp_2){ temp_swap = strcpy(temp_swap,s[i]); s[i] = strcpy(s[i],s[j]); s[j] = strcpy(s[j],temp_swap); }}} free(temp_1); free(temp_2); free(temp_swap); return; }
Perche' usi tutta questa memoria dinamica? temp_1 e temp_2 sono solo dei caratteri, giusto? E allora perche' devi malloc-arli? Basta dichiarare
char temp_1,temp_2;
E la funzione prendi() in modo che ritorni un char invece che un char *. Peraltro puoi anche evitare di usare temp_1 e temp_2.
Inoltre temp_swap deve contenere tutta una stringa, devi allocare spazio per piu' di un carattere. Per l'esattezza il massimo tra le lunghezze delle stringhe da ordinare.
Altra cosa che secondo me e' sbagliata e' che s punta alle stringhe in ingresso. Sei all'interno di due cicli, dovresti passare s e s[j] a prendi(), non s. Il tipo char *s[MAX] e' un array di puntatori (cf. K&R), per cui s da solo e' un puntatore ad un puntatore (all'inizio del primo array), mentre ogni elemento s dell'array e' un puntatore ad un char (in realta' alla i-esima stringa, ma questo il puntatore non lo sa - lui punta all'inizio della stringa).
Forse questa e' la risposta alla tua domanda?
char* prendi(char *a[MAX]){ int i; char *temp_p; temp_p=(char*)malloc(sizeof(char)); for(i=0;i<MAX;i++){ temp_p=a[i]; while(*(temp_p+1)!='\0') //In questo modo prende l'ultimo temp_p++; //carattere della stringa passata } return(temp_p); }
Questa e' secondo me sbagliata in conseguenza dell'errore della sezione precedente. Dovresti fargli cercare l'ultimo carattere di ogni stringa, visto che viene eseguito dentro un loop. Quindi io la scriverei
char prendi(char *a) { if(*a == '\0') return(*a); // stringa vuota, ritorna carattere nullo while(*a) { a++; } return(*(a-1)); // poiche' la stringa non e' vuota, il terminatore ha un carattere che lo precede }
e non hai bisogno di variabili ausiliarie.
Ciao, grazie tante della risposta e anche per aver esplicato gli errori che ho fatto. Ti volevo chiedere solo una cosa che ancora non capisco, quando tu dici:
"Inoltre temp_swap deve contenere tutta una stringa, devi allocare spazio per piu' di un carattere. Per l'esattezza il massimo tra le lunghezze delle stringhe da ordinare."
Non capisco cosa sbaglio....l'allocazione della memoria di temp_swap non è corretta??è sbagliata fare questa asseganzione forse?????
"temp_swap = strcpy(temp_swap,s);"
Grazie ancora per l'eventuale risposta.
"Inoltre temp_swap deve contenere tutta una stringa, devi allocare spazio per piu' di un carattere. Per l'esattezza il massimo tra le lunghezze delle stringhe da ordinare."
Non capisco cosa sbaglio....l'allocazione della memoria di temp_swap non è corretta??è sbagliata fare questa asseganzione forse?????
"temp_swap = strcpy(temp_swap,s);"
Grazie ancora per l'eventuale risposta.
"fk16":
Ciao, grazie tante della risposta e anche per aver esplicato gli errori che ho fatto. Ti volevo chiedere solo una cosa che ancora non capisco, quando tu dici:
"Inoltre temp_swap deve contenere tutta una stringa, devi allocare spazio per piu' di un carattere. Per l'esattezza il massimo tra le lunghezze delle stringhe da ordinare."
Non capisco cosa sbaglio....l'allocazione della memoria di temp_swap non è corretta??è sbagliata fare questa asseganzione forse?????
"temp_swap = strcpy(temp_swap,s);"
piu' in alto nel codice hai allocato
temp_swap = (char *)malloc(sizeof(char));
questo richiede al sistema di allocare da qualche parte lo spazio per un carattere, il cui puntatore viene messo in temp_swap. Tu invece vuoi che temp_swap punti a una stringa, per cui devi allocare lo spazio sufficiente, tipo
temp_swap = (char *)malloc(sizeof(char)*max_len);
laddove max_len e' il numero di caratteri della stringa piu' lunga. In questo modo quando copi con strcpy() una stringa nello spazio puntato da temp_swap non "la fai fuori dal vaso".
Ora ho capito, il nostro professore neanche le ha spiegate queste cose, lui durante il corso ha detto solo come si usano la malloc e la calloc e niente di più. Comunque grazie mille per i chiarimenti.
Ti chiedo l'ultima cosa e non ti disturbo più. Quando compilo mi va in crash. Io suppongo che sia una questione di allocazione della memoria, perchè come mi hai detto prima se temp_swap aveva bisogno di aver allocato una memoria sufficiente per poter memorizzare il valore di una stringa, allora anche *s[MAX] ha bisogno di allocare una certa quantità di memoria o no?
"fk16":
Ti chiedo l'ultima cosa e non ti disturbo più. Quando compilo mi va in crash. Io suppongo che sia una questione di allocazione della memoria, perchè come mi hai detto prima se temp_swap aveva bisogno di aver allocato una memoria sufficiente per poter memorizzare il valore di una stringa, allora anche *s[MAX] ha bisogno di allocare una certa quantità di memoria o no?
No, quella e' statica. Una scrittura come
char *c = "pippo";
alloca la stringa a destra, e assegna a c l'indirizzo della stringa stessa.
Lo stesso vale per un array come il tuo.
Prova a testare ogni singola funzione, e cerca di capire quale e' la funzione che da il crash, poi magari posta quella.
Se hai usato il programma che hai postato originariamente deve per forza crashare, pero' se hai fatto delle modifiche io non posso saperlo.
Comunque un problema che sicuramente c'e' (e mi sono dimenticato di metterlo in evidenza prima) e' che se copi una stringa su un'altra di lunghezza minore vai a sovrascrivere qualcosa che non dovresti. E le tue stringhe sono tutte lunghe diverse. Il problema si potrebbe risolvere eliminando la dipendenza da strcpy(), usando un vettore ausiliario di puntatori, che vengono inizializzati all'indirizzo delle stringhe da ordinare. In questo modo nel bubble-sort invece di scambiare le stringhe puoi scambiare i puntatori ausiliari (che poi e' pure computazionalmente piu' efficiente).
Praticamente una cosa come
char *aux[MAX]; char *dummy; ... for(i=0;i<MAX;i++) aux[i] = s[i];
e poi nel bubble-sort usi aux invece di s, e invece di strcpy() per scambiare puoi usare semplicemente
dummy = aux[i]; aux[i] = aux[j]; aux[j] = dummy;
che scambia solo i puntatori ausiliari. L'output si trova in aux[].
Potresti pure farlo usando solo gli s, ma mi sembra piu' pulito cosi', visto che le parole in input potrebbero anche venire da una struttura diversa da un array.
Se hai bisogno cmq non farti problemi a postare ancora.
Allora, questa è la nuova implementazione del programma.
C'è ancora un problema:
Praticamente il risultato del compilatore mi mostra il vettore di puntatori inziale. Mi sono scritto su un foglio i vari passaggi che esegue il compilatore e mi sono accorto che:
i=o j varia sole Telefono MOUSE BATTERIA Casa Fogli (Notare che sole non è la stringa col carattere più piccolo)
i=1 j varia sole MOUSE BATTERIA Casa Fogli Telefono
i=2 j varia sole MOUSE Casa Fogli Telefono BATTERIA
i=3 j varia sole MOUSE Casa Telefono Fogli BATTERIA
i=4 j=5 sole MOUSE Casa Telefono Fogli BATTERIA (Notare che in codice ASCII e=101, E=69, a=97, o=111, i=105, A=65)
Quindi non sono ordinati in modo giusto e poi sull' output viene stampato:
Fogli Telefono sole MOUSE BATTERIA Casa.
Per favore aiutami perchè non ci sto capendo più niente........
C'è ancora un problema:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAX 6 #define MAX_LEN 9 void stampa(char *a[MAX]); void ordina(char *s[MAX]); char prendi(char a[MAX]); int main(){ char *s[MAX]={"Fogli","Telefono","sole","MOUSE","BATTERIA","Casa"}; stampa(s); ordina(s); printf("\n"); stampa(s); printf("\n"); system("pause"); return 0; } void stampa(char *s[MAX]){ int i; for(i=0;i<MAX;i++) printf("[%s] ",s[i]); return; } void ordina(char *s[MAX]){ int i,j; char *str[MAX]; char *temp_swap; char a; char b; for(i=0;i<MAX;i++) str[i]=s[i]; temp_swap=(char*)malloc(sizeof(char)*MAX_LEN); for(i=0;i<MAX;i++){ for(j=MAX-1;j>i;j--){ a=prendi(s[i]); b=prendi(s[j]); if(a > b){ temp_swap = str[i]; str[i] = str[j]; str[j] = temp_swap; printf("%s ",str[i]); //ho messo queste due printf solo per vedere quali elementi mi selezionava nel bubblesort printf("%s \n",str[j]); }}} free(temp_swap); return; } char prendi(char *a) { if(*a == '\0') return(*a); while(*a !='\0') { a++; } return(*(a-1)); }
Praticamente il risultato del compilatore mi mostra il vettore di puntatori inziale. Mi sono scritto su un foglio i vari passaggi che esegue il compilatore e mi sono accorto che:
i=o j varia sole Telefono MOUSE BATTERIA Casa Fogli (Notare che sole non è la stringa col carattere più piccolo)
i=1 j varia sole MOUSE BATTERIA Casa Fogli Telefono
i=2 j varia sole MOUSE Casa Fogli Telefono BATTERIA
i=3 j varia sole MOUSE Casa Telefono Fogli BATTERIA
i=4 j=5 sole MOUSE Casa Telefono Fogli BATTERIA (Notare che in codice ASCII e=101, E=69, a=97, o=111, i=105, A=65)
Quindi non sono ordinati in modo giusto e poi sull' output viene stampato:
Fogli Telefono sole MOUSE BATTERIA Casa.
Per favore aiutami perchè non ci sto capendo più niente........
"fk16":
Allora, questa è la nuova implementazione del programma.
C'è ancora un problema:
void ordina(char *s[MAX]){ int i,j; char *str[MAX]; char *temp_swap; char a; char b; for(i=0;i<MAX;i++) str[i]=s[i]; temp_swap=(char*)malloc(sizeof(char)*MAX_LEN); for(i=0;i<MAX;i++){ for(j=MAX-1;j>i;j--){ a=prendi(s[i]); b=prendi(s[j]); if(a > b){ temp_swap = str[i]; str[i] = str[j]; str[j] = temp_swap; printf("%s ",str[i]); //ho messo queste due printf solo per vedere quali elementi mi selezionava nel bubblesort printf("%s \n",str[j]); }}} free(temp_swap); return; }
Guarda, e' molto piu' semplice di quello che pensi.
Anzitutto nella bubble-sort alle righe
a=prendi(s[i]); b=prendi(s[j]);
ti sei dimenticato di sostituire l'array originale con l'array ausiliario str[].
Inoltre, ricordati che l'output e' nel vettore ausiliario, invece il tuo programma continua pervicacemente a stampare quello originario

Questi sono i tipici bachi da stanchezza, li conosco pure troppo bene

Comunque, visto che il programma ha tutto sommato un utilizzo limitato, forse usare l'array ausiliario e' overkilling, prova a eliminarlo e risostituire ovunque s[] (se hai un buon editor fa tutto lui

Acevo in mente possibili generalizzazioni, ma chiaramente se il programma e' la soluzione di un esercizio potrebbe giustamente non fregartene niente...scusa se ti ho fatto fare il giro lungo...
Altra cosa, una semplice imprecisione che non inficia niente nel programma: adesso nel bubble-sort scambi solo i puntatori, e' diventato inutile allocare lo spazio per una stringa puntata da temp_swap: basta eliminare le righe con malloc() e free().
Per convincerti che funziona fai i classici disegnini con scatoline e freccette (coi puntatori aiutano, per la mia esperienza).
Grazie tante finalmente è riuscito.....non ne potevo più...ti ringrazio per la tua pazienza.
