PDA

Visualizza la versione completa : [C] Uso di fgets() non ripete la richiesta di inserimento


TheFe
11-05-2012, 18:19
Ciao a tutti!

mi scuso se posto una domanda già fatta, ma pur leggendo gli altri topic non riesco a trovare soluzione!

Sto scrivendo un programma in C per l'università: è una specie di quiz, il codice è il seguente



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

#define MAX_TITLE_LEN 40
#define MAX_Q_LEN 300
#define MAX_A_LEN 30
#define DEBUG

int punteggio = 0;

void stampa_domande (char[], FILE*, FILE*);
void acquisisci_risposta (FILE*);
void score (void);

int main () {

int i;
char titolo[MAX_TITLE_LEN + 1], password[MAX_TITLE_LEN + 1];
char percorso_d[MAX_TITLE_LEN + 1], percorso_r[MAX_TITLE_LEN + 1], percorso_p[MAX_TITLE_LEN + 1];
char domanda[MAX_Q_LEN + 1];
char scelta;
FILE *d, *r, *p;

printf ("Benvenuto!\n");
printf ("Inserisci il titolo del film di cui vuoi le domande: ");
gets (titolo);

do {

for (i = 0; titolo[i] != '\0'; i++) {

titolo[i] = tolower (titolo[i]);
if (titolo[i] == ' ')
titolo[i] = '-';
}

strcpy (percorso_d, titolo);
strcpy (percorso_r, titolo);
strcpy (percorso_p, titolo);
strcat (percorso_d,"/domande.txt");
strcat (percorso_r, "/risposte.txt");
strcat (percorso_p, "/password.txt");

d = fopen (percorso_d, "r");
r = fopen (percorso_r, "r");

if (d == NULL) {
printf ("Non ho trovato il file\n");
return 0;
}
else
printf ("%s: ho aperto i file.\n", titolo);

while(fgets (domanda, MAX_Q_LEN, d) != NULL)
stampa_domande (domanda, d, r);

printf ("Hai totalizzato %d punti.\n", punteggio);

if (punteggio == 40 || punteggio > 40) {
p = fopen (percorso_p, "r");
fscanf (p, "%s", password);
fclose (p);
printf ("Complimenti!! Livello superato!\nLa Password per aprire l'archivio corrispondente a %s è %s\n", titolo, password);
}
else {
printf ("Peccato! Livello fallito!\n");
fclose (d);
}

printf ("Un'altra partita? (y, n) ");
scanf ("%c", &scelta);

if (scelta == 'y') {
printf ("Inserisci il titolo del film di cui vuoi le domande: ");
gets (titolo);

#if defined (DEBUG)
printf ("new_title: %s\n", titolo);
#endif
}

} while (scelta != 'n');

return 0;

}

void stampa_domande (char domanda[], FILE *d, FILE *r) {

printf ("%s ", domanda);
acquisisci_risposta (r);

return;
}

void acquisisci_risposta (FILE *r) {

char risp_es[MAX_A_LEN + 1], risposta[MAX_A_LEN + 1];
int check;

gets (risposta);
fscanf (r, "%s", risp_es);

check = strcmp (risp_es, risposta);

if (check == 0) {
punteggio += 10;
return;
}
else
return;
}


in pratica all'inizio del runtime l'utente specifica il nome di un film (di cui sono state caricate domande e risposte), il programma fa delle domande e l'utente risponde con risposte aperte oppure vero/falso.

tutto ok, se non fosse che quando arrivo per la prima volta all'inizio del main e mi chiede "un'altra partita?" io faccio "y" e lui, saltando completamente la gets (titolo) in fondo termina il programma perchè non mi fa dire su quale altro film voglio essere interrogato. :dhò:

Cosa devo fare??? :bhò:

Who am I
11-05-2012, 18:37
Mai usare la scanf, che ti sporca il buffer di input.
Tutto l' input dell' utente viene messo in un' area di memoria e poi viene letto.Se l' utente digita caratteri che non vengono letti, questi rimangono nel buffer e vengono letti durante la successiva funzione di input, inquinando così il risultato.
gets() non sporca il buffer perché legge tutti i caratteri, però ha il problema che non fa alcun controllo sulla quantità di caratteri letti, il che può causare un segmentation fault.

In definitiva: usa solo la fgets (http://www.cplusplus.com/reference/clibrary/cstdio/fgets/) (tieni conto del fatto che legge anche il carattere '\n'), e se vuoi leggere degli interi converti la stringa in int con atoi (http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/).

Esempio:



char buffer[100];
int num;
puts("Digita un numero : ");
fgets(buffer,100,stdin);
num=atoi(buffer);

TheFe
12-05-2012, 00:34
ho fatto come dici tu, ma non è cambiato nulla! :dhò:

oregon
12-05-2012, 00:51
Cioè? Adesso cosa hai scritto?

Who am I
12-05-2012, 13:10
Tra parentesi ti sei dimenticato di copiare il terminatore nella stringa titolo:




for (i = 0; titolo[i] != '\0'; i++) {

titolo[i] = tolower (titolo[i]);
if (titolo[i] == ' ')
titolo[i] = '-';
}
titolo[strlen(titolo)]='\0';


Comunque posta il codice che hai scritto finora.

oregon
12-05-2012, 13:13
Attenzione a linee come queste

titolo[strlen(titolo)]='\0';

perché, se ci rifletti un po', non hanno senso ...

Who am I
12-05-2012, 22:44
Originariamente inviato da oregon
Attenzione a linee come queste

titolo[strlen(titolo)]='\0';

perché, se ci rifletti un po', non hanno senso ...

Hai ragione, non ci avevo pensato.La strlen non restituisce il risultato corretto perché il terminatore non c'è ancora.
Correggo:



for (i = 0; titolo[i] != '\0'; i++) {

titolo[i] = tolower (titolo[i]);
if (titolo[i] == ' ')
titolo[i] = '-';
}
titolo[i]='\0';

torn24
13-05-2012, 11:28
per Who am I
secondo me ti voleva dire , che gets() aggiunge il terminatore di riga '\0'
gets() (http://www.cplusplus.com/reference/clibrary/cstdio/gets/)
con l'istruzione :
titolo[strlen(titolo)]='\0';
dici sostituisci strlen(titolo) , che è il terminatore , con il terminatore :)


stessa cosa per l'ultimo codice che hai postato ,
se esce da ciclo con questa condizione titolo[i]!='\0' , è inutile questa assegnazione

titolo[i]='\0'; , titolo[i] è gia il terminatore stringa !

Loading