Error using scanf("%[ n]") in sequence

Asked

Viewed 548 times

2

#include <stdio.h>

typedef struct person{
    char name[100];  
    char address[100];
    int age;
} Person;

int main()
{
    Person pessoa;

    printf("Digite seu nome:\n");
    scanf("%99[^\n]", pessoa.name);

    printf("Digite seu endereço:\n");
    scanf("%99[^\n]", pessoa.address);

    printf("Digite sua idade:\n");
    scanf("%d", &pessoa.age);

    printf("Nome: %s\nEndereço: %s\nIdade: %d\n", pessoa.name, pessoa.address, pessoa.age);

    return 0;
}

I would like to know why after using the scanf("%99[^\n]", pessoa.name); the second

scanf("%99[^\n]", pessoa.address); is being automatically skipping

  • José, you have already tried to scan %s?

  • Yes, but it was causing the same error, even with only one scanf in the code

  • From what I could understand, in the link you provided, when I give a enter the delivery buffer does not consume the correct n?

3 answers

3

They are giving too complicated solutions...

How to do:

Person pessoa;

printf("Digite seu nome:\n");
scanf(" %99[^\n]", pessoa.name); // um espaco antes de %99[^\n]

printf("Digite seu endereço:\n");
scanf(" %99[^\n]", pessoa.address);  // um espaco antes de %99[^\n]

printf("Digite sua idade:\n");
scanf("%d", &pessoa.age); // aqui nao precisa do espaco antes do %d

Ready!

Explanation: in a scanf a blank space consumes all whitespace (' '), tabs (' X9'), line forward (' n') and cursor return (' r') that are in sequence.

2


This is because in the first two calls from scanf() you ask to read exclusively characters that are not line breaks. This implies the scanf() leave the line break character in the buffer of stdin until a call consumes the breaking character, that is, until the third call (scanf("%d")).

What you can do to solve is "spy" the next character that is on buffer right after each of the first two calls from scanf() and consume it if it is a line break. Example:

int main()
{
    Person pessoa = { "", "", -1 };
    char c;

    printf("Digite seu nome:\n");
    scanf("%99[^\n]", pessoa.name);

    /* Retira o primeiro (ou próximo) caractere que está no buffer
     * do stdin e devolve (para o mesmo buffer) caso não seja uma
     * quebra de linha. */
    c = getc(stdin); 
    if (c != '\n')
        ungetc(c, stdin);

    printf("Digite seu endereço:\n");
    scanf("%99[^\n]", pessoa.address);

    /* "Espia" novamente o buffer do stdin para consumir a quebra
     * de linha. Essa segunda chamada não é obrigatória porque o
     * próximo scanf() será com a format string %d, mas deixei aqui
     * para manter o padrão de sempre consumir um newline após as
     * chamadas scanf("%[^\n]"). */
    c = getc(stdin);
    if (c != '\n')
        ungetc(c, stdin);

    printf("Digite sua idade:\n");
    scanf("%d", &pessoa.age);

    printf("Nome: %s\nEndereço: %s\nIdade: %d\n", pessoa.name, pessoa.address, pessoa.age);

    return 0;
}
  • Fernando you could inform me what this stretch c = getc(stdin);&#xA; if (c != '\n')&#xA; ungetc(c, stdin); is doing under the hood.

  • @Joséisaac added comments on the code snippets. Make sure they are sufficient to understand. If it’s not, let me know I can improve the explanation

  • thank you very much, I could understand perfectly, vlw.

0

I recommend using any of these functions:

void limpa_linha() {
    scanf("%*[^\n]"); /* Lê todos os caracteres "indesejados" e descarta os mesmos, exceto o '\n' */
    scanf("%*c"); /* Lê o caractere '\n' e descarta o mesmo, limpando assim o stdin */ 
}

Or that:

void fflush_stdin() {
    char ch;
    while ((ch = getchar()) != '\n' && ch != EOF); /* getchar() em loop */
}

Use of one of them:

Person pessoa;

printf("Digite seu nome:\n");
scanf(" %99[^\n]", pessoa.name); /* um espaco antes de %99[^\n] para descartar os eventuais espaços em branco antes da string ser digitada */
limpa_linha();

printf("Digite seu endereço:\n");
scanf(" %99[^\n]", pessoa.address); 
limpa_linha();

printf("Digite sua idade:\n");
scanf("%d", &pessoa.age); 
limpa_linha();

Browser other questions tagged

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