Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - impiccato
Forum - C/C++ - impiccato - Pagina 2

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Zizzius (Honoris User)
Guru


Messaggi: 675
Iscritto: 28/02/2005

Segnala al moderatore
Postato alle 22:46
Mercoledì, 22/06/2005
Sar? breve.

Innanzitutto, non posso non dire che il testo del tuo programma ? alquanto disordinato.
In linea generale:
- le variabili devono esprimere, mediante il loro nome, la loro funzione;
- se questo non ? possibile, ? opportuno inserire un commento, in particolar modo per le variabili globali;
- le variabili del tuo programma non hanno nessuno di questi due requisiti;
- difatti, hai dichiarato molte variabili che poi non hai mai usato (ad esempio: end) o hai creato dei duplicati (doit e started fanno esattamente le stesse cose);
- e ancora: in generale ? buona cosa commentare adeguatamente il codice, in modo da rendere pi? facile l?analisi per trovare gli errori, sia da parte del programmatore stesso, sia da parte di persone esterne (vedi il sottoscritto).

Testo quotato

Postato originariamente da chica87:

ne avr? fatte 1000 versione nemmeno una funziona!




Questo dimostra infatti che lo stile di programmazione ? inadeguato.

In tutti i casi, non voglio demonizzare nessuno. Quindi passo subito al sodo.
Gli errori pi? macroscopici ? quelli che effettivamente costituiscono la causa del non funzionamento del programma ? sono i seguenti:

Alla riga 202, ovvero dopo l?acquisizione della parola segreta dal file di testo, ? necessaria l?istruzione
word[j]=?\0?; //carattere nullo di terminazione
N.B.: qui come in seguito uso l?espressione [j] per designare la posizione all?interno del vettore perch? l?uso della variabile viene interpretato come codice html e fa diventare tutto in corsivo. La variabile j va dunque letta i.

Tornando a noi, l?istruzione sopra citata ? necessaria perch? pone un limite alla parola contenuta in word. La funzione strlen() (richiamata pi? di una volta) individua proprio la posizione del carattere nullo di terminazione.

Alla riga 55 c?? una di quelle sviste tali che, una volta che il programmatore se ne rende conto, si mangia le dita. Si tratta dell?istruzione
if (word[j]==let);
, in cui il punto e virgola ? di troppo.

Una volta corrette queste due cose, il programma funziona (nel senso stretto del termine), ma non ci si pu? ancora dichiarare soddisfatti.
Esaminiamo ora pi? a fondo il programma.

Innanzitutto, come ho gi? detto, le variabili globali devono avere nomi auto-esplicativi e devono essere commentate nella loro funzione.
Inoltre, la variabile end in specifico ? del tutto inutile (viene forse usata da qualche parte?).


Bene. Ora, ti puoi rendere conto tu stessa che ? piuttosto scomodo l?avere la funzione main() in fondo al codice. E? opportuno anteporla alle altre funzioni, avendo cura di dichiarare prima di essa i prototipi di funzione.
In soldoni:
// prototipi di funzione
int menu();
void about();
void stampa_parola();
int check_parola(char);
void carica_parola();
void stampa_omino(int);
void playgame(int);
// main()
int main()
<corpo della funzione main>
<a seguire, le altre funzioni>



Alle righe 21-32, hai optato per una struttura del tipo:
if (?)
{ do
{ (?)
} while(?)
}

Siamo fortunati! Pensa un po', il C mette a disposizione il ciclo do-while, che pu? sostituire a meraviglia questa porzione di codice.


Come ho gi? detto, ? molto importante avere un corretto stile di programmazione. Cosa significa in pratica? Beh, per cominciare ecco come ci si comporta con i blocchi di istruzioni, delimitati da parentesi graffe:
- la condizione o qualsivoglia enunciato va sulla medesima riga della parentesi graffa aperta:
esempio: if(a == b) {
- seguono le istruzioni del blocco, opportunamente indentate (con il tasto tabulazione)
- infine, si chiude la parentesi.
Quando si esamina un programma (specialmente se fatto da altri) ? molto importante il colpo d?occhio: il programmatore deve dunque rispettare talune ?regole? (o chiamiamole convenzioni) di stile e attenersi coerentemente per tutta la durata del programma.


Diamo un?occhiata alla funzione stampa_parola(). Cosa fa? Semplicemente stampa su video la stringa res.
Questa funzione ? superflua, oltre che scorretta nella sua implementazione:
- non considera assolutamente il problema della portabilit?, anche se forse questo errore ? pi? la regola che l?eccezione (se non altro, si trova in buona compagnia);
- al suo interno, vi ? un uso ridondante delle parentesi graffe.
- per due volte consecutive, inizializzi i a 0.
In definitiva, ? nettamente migliore sostituire totalmente questa funzione con
printf(?%s?, res);
che svolge lo stesso compito della funzione da te creata.


int check_parola. E gi? qua ? scorretta. Il valore di ritorno pu? essere 0 o 1: perch? quindi non bool check_parola? Ma non ? tutto: la scelta degli identificatori ? molto importante. E? preferibile is_correct oppure isCorrect, che evidenzia come un valore di ritorno true significhi ?lettera corretta? e false significhi il contrario.
Inoltre, alla riga 54, il ciclo
for (i=0;i<strlen(word)-1;i++)
va sostituito con
for (i=1;i<strlen(word)-1;i++)

Hai ripetuto due volte di seguito l?istruzione
i=0;
E anche su ok c?? poi da ridire: ? meglio
bool indovinato;
che mette in risalto la funzione di questa variabile (vale lo stesso discorso di isCorrect piuttosto che check_parola).
Tenendo poi presente che, una volta incontrata l?istruzione return, la funzione termina la propria esecuzione, la struttura di selezione finale dovrebbe essere sostituita con
if isCorrect
return true;
return false;



Alla riga 68 ? presente ancora una volta un?assegnazione del tutto inutile.


void stampa_omino(int casenum)
Cosa significa casenum?
E se casenum vale 0 (cosa che succede), cosa deve fare il programma?
Ora, alla sola vista di 44 invocazioni di printf() a chiunque sorge qualche dubbio, no? Non c?? forse un?alternativa?
Qual ? l?utilit? dell?istruzione
end=strlen(word)-2;
? (riga 139)


void playgame(int option)
num
: perch? viene inzializzata a 0?

doit e started: qual ? la differenza?

i=0; (che tornerai a ripetere pi? avanti)

system(?clear?); ? supportata solo in Linux


Dopodich? il programma prova ad aprire ?parole.txt?. E se non ci riesce? Scrive qualcosa, sullo schermo, ma non importa cosa, dal momento che l?istruzione dopo cancella il tutto con clrscr()... e poi? Torna da capo, ma secondo me l?esito sar? lo stesso. E per di pi? siamo gi? dentro all?opzione 1 (GIOCATORE vs COMPUTER)!!
A seguire, un frammento di codice che mi rifiuto di commentare:
time(&t);
srand(t);
t=rand();
t=(t%num_parole);
switch(t) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
do {
c=fgetc(fp);
num=c-'0';
} while(num!=t && c!=EOF); break;
}
// copio la parola...
i=0;
for(;; ) {
c=fgetc(fp);
if(c=='#')
break;
else
word[j]=c;
i++;
}

Ci sono pi? errori qua che non nel resto del programma.


I commenti sono un importante strumento per la messa a punto del software. Questo vale a patto che i commenti siano coerenti al codice a cui si riferiscono...
// stampo l?omino se necessario (riga 229)
"se necessario"? Eppure mi sembra che l?omino venga stampato in tutti i modi...
Ora, come devo interpretare il seguente frammento di codice
scanf("%c", &c);
fflush(stdin);
scanf("%c", &c);

?
In pratica, il programma chiede all?utente di inserire 2 volte il carattere da cercare!
Analizziamo dinamicamente le righe 229-246:
la prima volta, la condizione della struttura if alla riga 229 ? falsa, quindi, cosa fa il programma? Salta all?else, ovvero:
stampa_omino(cont);
printf("\nHai indovinato la lettera!!\n");

Ho indovinato la lettera? Oh, che bello! E dire che dovevo ancora incominciare a giocare!!
Immaginiamo ora che mi rimanga 1 solo tentativo di indovinare la lettera. Dico una lettera, che per? ? errata. Quindi, la struttura di selezione
if(check_parola(c)==0 && doit==1 && started==1)
fa si che venga visualizzato sulla schermo la seguente frase:
Hai ancora 0 tentativi!! (numero max 8)
Eppure, poco dopo il programma mi chiede nuovamente di inserire una lettera. E questa potrebbe essere anche l?ultima lettera che dovevo indovinare. Quindi? Ho forse vinto? No, ho perso!
Caso opposto: lettera dopo lettera, indovino la parola; ma dopo di ci?, cosa viene visualizzato sullo schermo? Inserisci una lettera!!!



In definitiva, non prendere questa arringa come una critica passiva al tuo programma o al tuo modo di programmare. Ho impiegato davvero molto tempo per correggere il codice che hai postato e spero davvero che tu abbia appreso qualcosa di nuovo.
Diciamo solo che la prossima volta ? meglio fare prima di tutto una alalisi approfondita "in proprio", cercando di seguire uno stile chiaro e rigoroso e quindi facilmente leggibile.

Se hai altre domande, sono qui.

Ultima modifica effettuata da Zizzius il 22/06/2005 alle 22:48
PM Quote
Avatar
Zizzius (Honoris User)
Guru


Messaggi: 675
Iscritto: 28/02/2005

Segnala al moderatore
Postato alle 22:57
Mercoledì, 22/06/2005
:ot: Vedo che sei entrata a far parte della Community! :k: Bene, mi fa piacere e ti do il mio benvenuto! :)

PM Quote
Avatar
Chica87 (Ex-Member)
Newbie


Messaggi: 7
Iscritto: 22/06/2005

Segnala al moderatore
Postato alle 2:07
Giovedì, 23/06/2005
zizzius, grazie x i tuoi consigli....
mi rendo conto ke devo imparare ancora mooolte cose...cmq, dai 1 okkiata alla mail please!!:asd::asd:;):D
a presto!!!

Ultima modifica effettuata da Chica87 il 25/06/2005 alle 14:09
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo