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





quarta-feira, 14 de julho de 2021

Posicionando o cursor no Code::Blocks

 Prezados leitores:

Depois de alguns anos sem posts, estou reativando o blog para levar informações adicionais para  os meus alunos e, eventualmente, comentar assuntos fora da área de eletrônica embarcada.

Nessa postagem falarei sobre o posicionamento do cursor na tela para aplicativos de console, informação voltada aos iniciantes na programação C.

A função gotoxy (int x, int y)  disponível no Turbo C / C ++,  não é padrão do ANSI C.

Esta função é usada para mover o cursor  para um local desejado na tela. O canto superior esquerdo do monitor tem coordenadas (0,0) e o canto inferior direito pode ser qualquer coordenada, dependendo do tamanho da tela. O compilador GCC não disponibiliza a função gotoxy. 

Se você estiver desenvolvendo aplicativos de console sem uma biblioteca gráfica de terceiros, a função gotoxy será útil.

Se você precisa de uma implementação semelhante a função gotoxy em uma máquina Windows com o compilador GCC, o código-fonte lhe será útil:

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>


int main()

{

    COORD p;

    p.X = 10;

    p.Y = 5;

    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);

    printf("CURSOR\n\n");

    system("pause");

}

Mais informações sobre a função  "setconsolecursorposition" em:

https://docs.microsoft.com/pt-br/windows/console/setconsolecursorposition


Se você precisa de uma implementação no GCC Linux , segue abaixo  um código-fonte compatível:

#include<stdio.h>

 void gotoxy(int, int) ;


int main ()

{

    int x=10, y=5;

    gotoxy(x,y); 

    printf("CURSOR\nPressione qualquer tecla para continuar. . . ");

    getchar();

    return 0;

}

// Função gotoxy() 

void gotoxy(int x,int y)    

{

    printf("\e[%d;%df",y,x);

}

 /* 

\e é o caractere de escape que avisa o seu terminal que as informações que seguem

 não devem aparecer na tela, constituindo-se um comando para o terminal (ou  emulador).

O 'f' (pode ser 'H') final indica que se deseja posicionar o cursor no lugar da tela

indicado pelas coordenadas que o precedem.

*/

Boa leitura

sábado, 10 de março de 2018

Cartão de Referência do C (ANSI)

Prezados:

Estou disponibilizando a versão em português do  C Reference Card (ANSI) de autoria de Joseph H Silverman.
A cópia e a distribuição do cartão estão permitidas sempre que o copyright se mantenha em todas as cópias.

Boa utilização!






terça-feira, 1 de agosto de 2017