Vamos Programar? – Introdução à Programação #22

2 Comentários

Um pouco mais sobre a função scanf e algumas dicas

O mundo está constantemente a evoluir: desde o mais pequeno inseto à espécie Humana. Dentro das palavras que mais ouvimos atualmente, incluímos “evolução”, “mudança”, “futuro”.

A tecnologia tem revolucionado o mundo das mais diversas formas: do mais simples aparelho para medir o tempo ao mais complexo acelerador de partículas. Se quer entrar no mundo da tecnologia e deixar a sua marca, pode começar aqui.

introprog22

O artigo de hoje irá incidir sobre algumas sugestões a referir dadas por leitores no artigo da semana passada, mas também iremos começar a abordar outro tópico.

Limpeza do buffer

No artigo número nove da presente saga introduzimos as seguintes funções:

_fpurge();
fflush();

Ambas as funções permitem-nos limpar o buffer de entrada, porém não são muito seguras. Em programação profissional de C (e outras linguagens), estas funções não são utilizadas por motivos de segurança.

Claro que existem “soluções” alternativas. O leitor José Carlos Ferreira, no artigo da semana anterior, sugeriu-nos o seguinte:

#define CLEAR_INPUT while (!getchar ())

O que nos permite utilizar o trecho de código:

while (!getchar ())

Recorrendo apenas ao nome “CLEAR_INPUT”.

Alternativa a gets e a scanf

Devido à falta de uma solução efetiva ao problema existente com a função scanf e à existência de alguns contra-tempos com a função gets foi sugerido, pelos leitores Zé e lmx a utilização da função fgets.

Sintaxe

Esta função tem algumas diferenças relativamente às funções mencionadas no título. Ora veja a sintaxe:

fgets(char *str, int n, FILE *stream);

Onde:

  • str – O apontador para um array de caracteres onde a \textit{string} será armazenada.
  • n – O número máximo de caracteres a serem lidos (incluindo o delimitador final). Geralmente é igual ao tamanho do array.
  • stream – O apontador para o ficheiro ou objeto donde serão lidos os caracteres.

Exemplo

Vejamos então um exemplo baseado no boletim de informação criado no artigo anterior.

#include 
#include 

int main()
{
    char nome[21],
        apelido[21],
        morada[51],
        codigoPostal[11];

    printf("Por favor insira os seus dados conforme pedido:\n\n");
    printf("Primeiro nome: ");
    fgets(nome, 21, stdin);

    printf("Último nome: ");
    fgets(apelido, 21, stdin);

    printf("Morada: ");
    fgets(morada, 51, stdin);

    printf("Código Postal: ");
    fgets(codigoPostal, 11, stdin);

    printf("\nO seu Cartão de Identificação:\n");
    printf("Nome: %s, %s\n", apelido, nome);
    printf("Morada: %s\n", morada);
    printf("Código Postal: %s\n", codigoPostal);
    return 0;
}

Remoção das Mudanças de Linha

Mas, se corrermos o código acima, iremos receber algo parecido com o seguinte:

O seu Cartão de Identificação:
Nome: Apelido
, Nome

Morada: Morada

Código Postal: CP

Como pode verificar, isto mostra que os arrays ficaram, também com os delimitadores da mudança de linha (“\n”). Para removermos estes delimitadores podemos recorrer à função “strtok”.

Sintaxe

Ora veja a sintaxe desta função.

strtok(char *str, const char *delim);

Onde:

  • str – O apontador para um array de caracteres onde a \textit{string} está armazenada.
  • delim – O delimitador em questão ou uma constante que o contenha.

Exemplo

Então, para que o exemplo acima imprima corretamente o Bilhete de Informação, devem ser adicionadas as seguintes linhas antes de ser imprimida qualquer informação:

strtok(nome, "\n");
strtok(apelido, "\n");
strtok(morada, "\n");
strtok(codigoPostal, "\n");

Mais uma vez, gostávamos de saber a sua opinião. Caso tenha alguma dúvida, pode sempre utilizar os comentários para colocar a questão. Caso o faça,  pedimos que utilize a keyword [DUVIDA] no início do seu comentários.


Resoluções de exercícios.

Esta saga

Henrique Dias

Mais episódios: 
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13][12] [14] [15] [16]
[17] [18] [19] [20] [21] [22] [23][24]

homefacebookgoogle-plus

Comentários

2

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

  1. Avatar de Jose Simoes
    Jose Simoes

    O fflush perfeitamente seguro (o que evidentemente não exclui que algum compilador faça “sei lá eu o quê” com a função).

    A questão é que lhe é atribuída frequentemente uma finalidade que não resulta do C padrão, nomeadamente a de limpar os buffers de entrada.

    http://www.cplusplus.com/reference/cstdio/fflush/?kw=fflush

    Em relação ao resto não posso estar mais de acordo. Nas versões mais recentes dos meus cursos introdutórios ao C/C++ simplesmente não ensinava sequer as gets ou scanf, dava a penas uma nota como coisa a evitar. A getc é segura, mas prefiro substituir-la por fgetc por uma questão de tornar a explicação mais coerente.

    MAIS se se precisar dos formatos habitualmente associados a scanf a única maneira estável de ler qualquer coisa é ler essa qualquer coisa para uma string muito grande (típico 512 caracteres) e depois usar calmamente sscanf. A string grande é reutilizada em cada leitura pelo que não esgota recursos significativos.

    1. Avatar de Henrique Dias

      Olá José Simões!

      Obrigado pelo seu feedback e pela informação sobre a função fflush. Esta saga está quase a acabar. Os próximos artigos serão “projetos”.

      Esperemos mais opiniões para continuar a saga “Vamos Programar?” e extendê-la a outras linguagens. Quando lançarmos a compilação final colocarei essa informação.

      Desejo-lhe um excelente resto de fim de semana. 🙂