Perché Fgets non sta introducendo il primo valore?

Sto scrivendo un programma per scrivere rapidamente i miei file html. E quando sono venuto a scrivere il contenuto della mia pagina ho avuto un problema.

#include int main() { int track; int question_no; printf("\nHow many questions?\t"); scanf("%d",&question_no); char question[question_no][100]; for(track=1;track<=question_no;track++) { printf("\n
%d. ",track); printf("\nQuestion number %d.\t",track); fgets(question[track-1],sizeof(question[track-1]),stdin); printf("\n\n\tQ%d. %s
",track,question[track-1]); } }

In questo programma sto scrivendo alcune domande e le loro risposte (nel file html). Quando eseguo il test di questo programma, inserisco il valore di question_no in 3. Ma quando inserisco la mia prima domanda non va in question[0] e di conseguenza la prima domanda non viene emessa. Il resto delle domande è stato inserito senza problemi.

Ho cercato alcune domande su StackOverflow e ho scoperto che fgets() cerca l’ultimo carattere \0 e che \0 interrompe.
Ho anche scoperto che dovrei usare il buffer per inserire bene attraverso fgets() quindi ho usato: setvbuf e setbuf ma anche questo non ha funzionato (potrei averlo scritto male). Ho anche usato fflush(stdin) dopo la mia prima e ultima (anche) istruzione scanf per rimuovere qualsiasi carattere \0 dallo stdin ma che non ha funzionato.

C’è un modo per accettare il primo input di fgets() ?
Sto usando stdin e stdout per ora. Non sto accedendo, leggendo o scrivendo alcun file.

Usa anche i comandi per il primo prompt. Dovresti anche malloc tuo array perché non sai quanto tempo sarà in fase di compilazione.

 #include  #include  #define BUFSIZE 8 int main() { int track, i; int question_no; char buffer[BUFSIZE], **question; printf("\nHow many questions?\t"); fgets(buffer, BUFSIZE, stdin); question_no = strtol(buffer, NULL, 10); question = malloc(question_no * sizeof (char*)); if (question == NULL) { return EXIT_FAILURE; } for (i = 0; i < question_no; ++i) { question[i] = malloc(100 * sizeof (char)); if (question[i] == NULL) { return EXIT_FAILURE; } } for(track=1;track<=question_no;track++) { printf("\n
%d. ",track); printf("\nQuestion number %d.\t",track); fgets(question[track-1],100,stdin); printf("\n\n\tQ%d. %s
",track,question[track-1]); } for (i = 0; i < question_no; ++i) free(question[i]); free(question); return EXIT_SUCCESS; }

Array 2D in C

Una matrice di type 2D può essere rappresentata da una serie di puntatori da type o di type** equivalente type** (puntatore al puntatore al type ). Ciò richiede due passaggi.

Utilizzando la char **question come esempio:

Il primo passo è allocare un array di char* . malloc restituisce un puntatore all'inizio della memoria che ha allocato, oppure NULL se ha fallito. Quindi controlla se la question è NULL .

La seconda è di rendere ognuno di questi punti char* al proprio array di char . Quindi il ciclo for alloca un array della dimensione di 100 char per ogni elemento della question . Ancora, ognuno di questi malloc potrebbe restituire NULL quindi è necessario verificarlo.

Ogni malloc merita un free quindi è necessario eseguire il processo in senso inverso quando hai finito di usare la memoria che hai assegnato.

riferimento malloc

strtol

long int strtol(const char *str, char **endptr, int base);

strtol restituisce un long int (che nel codice sopra è castato in un int ). Si divide in tre parti:

  1. Qualsiasi spazio bianco che precede il contenuto numerico della stringa
  2. La parte che riconosce come numerica, che proverà a convertire
  3. Il resto della stringa

Se endptr non è NULL , punta alla terza parte, quindi sai dove finisce lo strtol . Potresti usarlo in questo modo:

 #include  #include  int main() { char * endptr = NULL, *str = " 123some more stuff"; int number = strtol(str, &endptr, 10); printf("number interpreted as %d\n" "rest of string: %s\n", number, endptr); return EXIT_SUCCESS; } 

produzione:

 number interpreted as 123 rest of string: some more stuff 

riferimento strtol

Questo perché il carattere di nuova riga precedente è rimasto nel stream di input di scanf (). Nota che fgets () si ferma se incontra anche una nuova riga.

fgets () legge al massimo un carattere in meno rispetto alla dimensione dal stream e li memorizza nel buffer indicato da s. La lettura si interrompe dopo un EOF o una nuova riga. Se una nuova riga viene letta, viene archiviata nel buffer

Non mischiare fgets () e scanf (). Una soluzione banale è usare getchar () subito dopo scanf () per consumare la nuova riga a sinistra nel stream di input di scanf ().

Secondo la documentazione ,

La funzione fgets () legge i byte dallo stream nell’array puntato da s, finché i byte n-1 non vengono letti, oppure un viene letto e trasferito a s, oppure si verifica una condizione di fine file

In caso di scanf("%d",&question_no); una nuova riga è lasciata nel buffer e viene letta da

 fgets(question[track-1],sizeof(question[track-1]),stdin); 

e esce.

Per scaricare il buffer dovresti farlo,

 while((c = getchar()) != '\n' && c != EOF) /* discard */ ; 

per cancellare i caratteri extra nel buffer