PROBLEMA funzione fgets

U

Utente cancellato 359755

Ospite
Salve a tutti, ho scritto un programma dove è possibile "organizzare" un'agenda. Affinché fosse possibile inserire anche lo spazio ho usato la funzione fgets che confesso di non aver compreso bene. Vi chiedo il favore di "spiegarmi" se possibile, ovviamente come si utilizza la funzione e il perché il programma mi salta la richiesta relativa al Titolo Appuntamento e salta a Descrizione Appuntamento.
Allego parte del codice
C:
int main() {
    int hh, mm, me, g, i;
    char strtmp[100];
    char strtmp2[300];
    Agenda Anno2020;
            printf("Il programma crea un'agenda e riodina gli impegni per data.\nQuando non si vogliono piu' inserire impegni inserire come giorno 32\n");
    while (g!=32){
        printf("\nInserire il giorno dell'appuntamento ");
            scanf("%d", &g);
                Anno2020.numero[i].n_giorno=g;
        if(g!=32){
        printf("Inserire il mese dell'appuntamento ");
            scanf("%d", &me);
                Anno2020.numero[i].mese=me;
        printf("Inserire a che ora c'e' l'appuntamento nel formato hh ");
            scanf("%d",&hh);
                Anno2020.numero[i].ora=hh;
        printf("Inserire a che minuto dell'appuntamento nel formato mm ");
            scanf("%d", &mm);
                Anno2020.numero[i].minuti=mm;
        printf("Inserire il Titolo dell'appuntamento ");
            fgets(&strtmp, 100, stdin);
                strcpy(Anno2020.numero[i].TitoloAppuntamento,strtmp);
        printf("Inserire una descrizione dell'appuntamento ");
            fgets(&strtmp2, 300, stdin);
                strcpy(Anno2020.numero[i].DescrizioneAppuntamento, strtmp2);
    i++;   
    }
}
BubbleSort_me(Anno2020.numero, i);
stampa (Anno2020, i);
        
    system ("PAUSE");
    return 0;
}
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,220
1,852
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Il programma ti salta la richiesta perchè rimane nel buffer un carattere di "new line" lasciato da scanf
In sostanza quando digiti qualcosa e premi invio, questo viene mantenuto nel buffer; fgets() va a leggere il buffer e si interrompe quando trova un "new line"... solo che essendo sporco (appunto, dalla presenza del new line) si interrompe subito (perchè è come se avessi premuto Invio).

Dovresti utilizzarlo prima della scanf, oppure evitare di combinarlo con la scanf (o ancora, puoi fare un flush del buffer ad esempio).
 
  • Mi piace
Reazioni: Andretti60
U

Utente cancellato 359755

Ospite
Quindi mi basta aggiungere un fflush(stdin); per risolvere il problema la quale mi "pulisce" stdin?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,220
1,852
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Aggiungi a scanf un \n dopo alla d (o metti uno spazio). Dovrebbe venir consumato già dalla scanf.
Puoi anche leggere un carattere dopo la scanf... anche se non è proprio pulito come metodo.

L'utilizzo di fflsuh con stdin non sarebbe da fare (undefined behavior).
 
  • Mi piace
Reazioni: fabio93
U

Utente cancellato 359755

Ospite
Facendo così mi succede che non esce il printf ma mi fa prima inserire i dati inerenti Titolo Appuntamento e poi lo visualizza. Allego immagine per maggiore comprensione
 

Allegati

  • s.PNG
    s.PNG
    168 KB · Visualizzazioni: 98

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,220
1,852
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Usa esplicitamente \n.
 
U

Utente cancellato 359755

Ospite
stessa cosa
 

Allegati

  • s.PNG
    s.PNG
    167.3 KB · Visualizzazioni: 58

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,220
1,852
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Ma che compilatore stai utilizzando?
 

Andretti60

Utente Èlite
6,440
5,091
Mischiare gets() e scanf() è pericoloso ed è una pratica da evitare (come pure getchar)
La cosa migliore da fare quando di legge in file (o anche da terminale) è di usare fgets() leggendo una linea alla volta, memorizzare tutta la linea in una stringa temporanea e poi usare sscanf() per leggere i vari componenti (e avere quindi modo anche di controllare possibili errori di formattazione).
Il problema è causato da quei orribili caratteri di ritorno (che a volte sono due a seconda del sistema operativo), ”scartarli” a mano produce code poco trasportabile e che può facilmente causare errori.
 
  • Mi piace
Reazioni: DispatchCode
U

Utente cancellato 359755

Ospite
e quindi scusami, non riesco a capire. Dovrei sostituire le scanf con tutte fgets anche se sono variabili semplici, ossia numeri?
grazie
 

Andretti60

Utente Èlite
6,440
5,091
Si, usi solo gets() o solo scanf()
Non mischiarle.
È una delle cose che si impara subito quando di studia IO del vecchio linguaggio C. Analogo a non mischiare read() con fread(). Crea solo problemi, credimi.
 
U

Utente cancellato 359755

Ospite
facendo così invece il programma "impazzisce" e non esce più neanche dal ciclo while d.PNG
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,220
1,852
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Ora che ci faccio caso, come condizione del while stai usando 'g', ma incrementi 'i'.
Per altro 'i' non è inizializzata, quindi avrà un valore "randomico". Questo è sicuramente un errore già di per sè.
 
  • Mi piace
Reazioni: _Achille

_Achille

Utente Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Ora che ci faccio caso, come condizione del while stai usando 'g', ma incrementi 'i'.
Per altro 'i' non è inizializzata, quindi avrà un valore "randomico". Questo è sicuramente un errore già di per sè.
Nemmeno g è inizializzato.
Correttamente, il ciclo dovrebbe essere un do - while

E ogni tanto qualche riga vuota si può lasciare quando è giusta… tanto da capirci qualcosa…
 
  • Mi piace
Reazioni: DispatchCode

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili