quinta-feira, 18 de novembro de 2021

Limpando o buffer de entrada em C

Buffer é uma área de armazenamento temporário. Todos os dispositivos padrão de entrada e saída contêm um buffer de entrada e saída. No C, os streams (fluxos de dados) são armazenados em um  buffer, por exemplo, no caso da entrada padrão, quando pressionamos uma  tecla no teclado, seu código  é armazenado no buffer pelo sistema operacional para posteriormente ser lido pelo programa.

Em algumas ocasiões, pode ser necessário limpar um conteúdo indesejado do buffer para obter uma próxima entrada desejada e não um valor residual da entrada anterior. Por exemplo, ao se utilizar um scanf ( ) , o <enter > digitado permanecerá no buffer, fazendo com que ele possa  "pular" um próximo scanf ( ) que aguarde um caractere ou uma string..

Uma opção bastante utilizada é a função fflush (), que deveria  normalmente ser  usada apenas para fluxo de saída. Sua finalidade é limpar (ou liberar) o buffer de saída e mover os dados do buffer para o console (no caso de stdout) ou disco (no caso de fluxo de saída em arquivo). Sua sintaxe é

int fflush (FILE * ostream);

onde ostream aponta para um fluxo de saída ou um fluxo de atualização em que a operação mais recente não foi inserida. A função fflush faz com que todos os dados não gravados para esse fluxo sejam entregues ao SO para serem gravados no arquivo.

De acordo com o padrão C,  usar fflush (stdin) para limpar o buffer de teclado pode apresentar um comportamento indefinido. No entanto, alguns compiladores permitem isso.  Veja o exemplo


#include <stdio.h>

int main()

{

    char c1, c2;

    printf("Digite um caractere: ");

    scanf("%c",&c1);// Entra um caractere + o <enter>

    fflush(stdin); /* Retira o <enter> do buffer para 

                   permitir a entrada do próximo 

                   caractere */

    printf("Digite outro caractere: ");

    scanf("%c",&c1);

    printf("C1 = %c e C2 =%c", c1, c2);

}

Não se trata  de uma questão de "quão ruim" isso é. fflush (stdin) simplesmente não é portável  (assim como  o __fpurge(stdin)  do Linux), então não deve ser usado se o desejo é gerar um  código portável entre compiladores.

Na sequência apresentaremos algumas alternativas ao uso de fflush(stdin):

Alternativa 1:

#include <stdio.h>

int main()

{

    char c1, c2;

    printf("Digite um caractere: ");;

    scanf("%c",&c1); /* Entra um caractere mais o 

                     <enter> */

    printf("Digite outro caractere: ");

    scanf(" %c",&c2); /* o espaço faz o programa C 

                      desconsiderar o <enter> */

    printf("C1 = %c e C2 =%c", c1, c2);

}


Alternativa 2:

#include <stdio.h>

int main()

{

    char c1, c2;

    printf("Digite um caractere: ");;

    scanf("%c%*c",&c1); /* Vão ser lidos 1 caractere e 

                         o '\n', o %*c faz o <enter>

                         ser descartado */

    printf("Digite outro caractere: ");

    scanf("%c",&c2); 

    printf("C1 = %c e C2 =%c", c1, c2);

}


Alternativa 3 (pode ser usada com getchar):

include <stdio.h>

#define LIMPABUFFER while(getchar()!='\n')

/* lê todos os caracteres do buffer e os descarta

(incluindo o '\n'), ou seja, esvazia o buffer de 

entrada */

int main()

{

    char c1, c2;

    printf("Digite um caractere: ");

    scanf("%c%, &c1); 

    LIMPABUFFER;

    printf("Digite outro caractere: ");

    scanf("%c", &c2); // ou c2 = getchar() 

    printf("C1 = %c e C2 =%c", c1, c2);

}


terça-feira, 9 de novembro de 2021

 Leitores:

Estou disponibilizando um script Scilab com uma interface gráfica para solução de transitórios de circuitos de primeira e segunda ordem (usuários Linux devem comentar as linhas 522 e 523):

- Circuito RC

- Circuito RL

- Circuito RLC série

- Circuito RLC paralelo

Fontes aceitas:

- Fonte constante

- Fonte senoidal: A sen(wt)

- Fonte exponencial: A e^(bt)

Esta versão está em teste, podendo ainda conter algum bug. Segue link:

https://drive.google.com/file/d/12OueuN9_sel0Q2bve048cP2vVMwDMGyg/view?usp=sharing