Problem with fgets in C

Asked

Viewed 245 times

1

This is the excerpt of my code with the problem:

int main (void) {

    int n_sentencas, n_perguntas;

    scanf("%d %d", &n_sentencas, &n_perguntas);
    fflush(stdin);

    char** sentenca; // ponteiro para matriz que armazena as sentencas
    sentenca = malloc(n_sentencas * sizeof(char*)); // alocacao das linhas da matriz que vao representar uma sentenca cada
    char** pergunta; // ponteiro para matriz que armazena as perguntas
    pergunta = malloc(n_perguntas * sizeof(char*)); // alocacao das linhas da matriz que vao representar uma pergunta cada


    for (int i = 0; i <= n_sentencas; i++) { // for que le as sentencas
        sentenca[i] = malloc(400 * sizeof(char));
        fgets(sentenca[i], 400, stdin);
    }

    for (int i = 0; i < n_perguntas; i++) { // for que le as perguntas
        pergunta[i] = malloc(400 * sizeof(char));
        fgets(pergunta[i], 400, stdin);
    }

    for (int i = 0; i < n_sentencas; i++) { // for que imprime as sentencas
        printf("sentenca %d: \n", i+1);
        printf("%s\n", sentenca[i]);
    }

    for (int i = 0; i < n_perguntas; i++) { // for que imprime as perguntas
        printf("pergunta %d: \n", i+1);
        printf("%s\n", pergunta[i]);
    }

The problem that occurs is that the first row of the matrix sentenca is always ignored, as in the example below:

Entree:

3 2
bom
dia
amigos
como vao voces?
(nessa linha deveria ter uma quinta entrada, mas o programa imprime os valores apenas 
com 4 strings na entrada, ao invés de 5)

Then the exit is as follows:

sentenca 1:


sentenca 2:
bom

sentenca 3:
dia

pergunta 1:
amigos

pergunta 2:
como vao voces?

I’d like to know how to fix it.

  • The problem and solution is the same as I speak in this question. In your case the solution is to consume the \n with fgetc(stdin) after the first scanf. Although fflush(stdin); try to do the same, this will only work in some implementations, and typically in linux does not work.

  • @Isac I tried to use fflush to solve this problem and it didn’t work, so I ended up having to ask here, since I didn’t know the fgetc. Incidentally, that \n that’s the one?

  • It is the enter that you put to enter the values, and that the scanf did not consume and ends up being the only thing that the first fgets reads

1 answer

0


Let’s see

Will take two shares to solve the problem. A second action to be taken has two alternatives, being at your discretion which one to choose. Particularly, I prefer the second case.


First action

Change the section below:

for (int i = 0; i <= n_sentencas; i++) { // for que le as sentencas

... For this:

for (int i = 0; i < n_sentencas; i++) { // for que le as sentencas

The operator <= did not make the program read n_sentencas but rather read n_sentencas+1. Switch operator <= by the operator < solves part of the problem.

Explaining: when reading the questions, the first of them was read in a section of memory that does not understand the memory reserved but that was adjacent to the memory of the last of the sentences.

Second action

CASE 1 - Change the section below:

fflush(stdin);

... For:

setbuf(stdin, NULL);

setbuf will discard the buffer since, in practice, it will not exist buffer to the stdin. The buffer is the problem for storing the ENTER, represented in line jump form \n. Thus without buffer, the ENTER that you pressed for data entry if it materializes will be discarded.

In case you need the buffer, create a buffer in the code section you want:

char buffer[BUFSIZ];
setbuf(stdin, buffer);

CASE 2 - Alternatively to case 1, erase:

fflush(stdin);

... And change:

scanf("%d %d", &n_sentencas, &n_perguntas);

... For:

scanf("%d %d%*c", &n_sentencas, &n_perguntas);

The * in %*c will discard the next dice of the chosen type (in this case, c character). It will therefore not be written or even stored in the buffer any character. In this case, the ENTER will not be stored or written.

Just be careful not to give one or more random spaces or even other characters. Each character is one %*c the most necessary that you do not go because it is accident of course. Thus, the case 1 is more efficient if it is not automatic data entry due to program user errors.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.