• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Guest tsenart

[Resolvido] [C] - Como usar o scanf com strings

23 mensagens neste tópico

O pessoal queixa-se muito do scanf pois supostamente não dá para ler strings com espaços e outros caracteres.... Isto é um mito.

Pois bem...

Como podem experimentar em vez de usarem o %s e usarem o %[^\n] podem ler uma string. O que isto faz é ler uma cadeia de caracteres até encontrar um caracter da lista de caracteres(\n neste caso). Se quiserem limitar o tamanho da string a ler usam o limitador atrás dos parênteses rectos (ex: %60[^\n]).

Este modo de ler strings é melhor que o fgets(), na minha perspectiva, pois o fgets() não descarta o \n (New Line), o que se pode tornar muito chato.

EDIT:

Para limpar o buffer de entrada, podem usar estas duas chamadas à função scanf().

scanf("%*[^\n]"); scanf("%*c");

Triton: A tabela de especificadores em cima é referente ao scanf e printf. O %n funciona com o printf do seguinte modo (exemplo):

#include <stdio.h>

int main()
{
   int n, tmp;
   printf("Hello%n\n", &n);
   tmp = n;
   printf("Nº de chars escritos até agora: %d\n", tmp);
   printf("World!%n\n",&n);
   tmp += n;
   printf("Nº de chars escritos até agora: %d\n", tmp);
   return 0;
}

Output:

Hello
Nº de chars escritos até agora: 5
World!
Nº de chars escritos até agora: 11

Artigo no wiki em http://wiki.portugal-a-programar.pt/dev_geral:c:scanfparastrings

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Porreiro :D

Sempre fica aqui um resumo de como usar o scanf :)

Bom trabalho, se puderes, completa mais o post com outras informações das funcionalidades do scanf :P

abraços, HecKel

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Porreiraço o post!! :D

Isto pode ser referência para muita gente por isso podia-se mudar o título do tópico para um do tipo "Como usar o scanf" ou algo do género.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu não pretendo fazer um tutorial da função scanf... Para isso usem as man pages. Isto foi só para esclarecer aquela dúvida de como ler strings em C com o scanf.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Excelente post, aprendi dois especificadores que não conhecia.

Já agora, após uma consulta rápida à bíblia C in a Nutshell, o especificador %n não lê qualquer input, apenas atribui o número de caracteres lidos ao inteiro especificado. Não tinha percebido isso muito bem depois de ler o teu post...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Perfeito! E pensar que num projecto usava o fgets() e tive que criar uma função para retirar o "/n" !!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem... Já agora vou pôr aqui duas chamadas à função scanf que limpam o buffer.

scanf("%*[^\n]"); scanf("%*c");

A primeira chamada lê e descarta, ou seja, retira todos os caracteres que eventualmente existam no armazenamento tampão de entrada(buffer), até ao aparecimento do caracter '\n'. A segunda chamada lê e descarta um caracter apenas que, devido à instrução anterior, é o caracer '\n'. Logo, recorrendo a estas duas instruções, todos os caracteres da linha que estava a ser processada foram descartados. Consequentemente, foi lida uma linha completa do armazenamento tampão(buffer) de entrada e a posição de leitura ficou colocada no inicio da linha seguinte.
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

So falta acrescentar, digamos um pormenor teorico do proposito disso!

Isso é uma funcionalidade do scanf que permite o uso de Expressoes Regulares (http://pt.wikipedia.org/wiki/Express%C3%A3o_regular) como padrao de leitura.

Tal como ja foi explicado, [^\n] faz "match" com uma classe de caracteres que nao contenham o \n.

Mais informaçao sobre ER pode ser vista aqui http://www.regular-expressions.info/

Ou uma lista com as varias regras das ER aqui http://www.regular-expressions.info/reference.html

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hmm, e a sintaxe do regex aí é a UNIX ou Perl-style? (Unix suponho...)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

UNIX, nao sei se obdece a POSIX mas no man deve dizer qq coisita sobre isso...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Para limpar o buffer de entrada, podem usar estas duas chamadas à função scanf()

Código

GeSHi ©:

scanf("%*[^\n']"); scanf("%*c");

Created by GeSHI 1.0.7.20

aqui acho que se pode simplesmente fazer:

scanf("%*[^\n]\n");

e poupa-se uma chamada á função!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ou mesmo:

scanf("%*[^\n]%*c");

Queria perguntar se toda a gente consegue limpar o buffer com este código. É que a mim compila, mas não limpa o buffer. Pode ser erro meu, mas queria confirmar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Queria perguntar se toda a gente consegue limpar o buffer com este código. É que a mim compila, mas não limpa o buffer. Pode ser erro meu, mas queria confirmar.

Já tentei várias formas para passar aquilo para um único scanf como essa última e nenhuma limpa o buffer, parece que só mesmo com os dois scanf's.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

hmmm...

while (getchar() != '\n');

// ou

while (scanf("%c") != '\n');

Ambas limpam o buffer. Não conheço nenhuma forma no ISO C de o limpar sem testar pelo null terminator. A não ser que usem gets()

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

fflush(strdin);

não resolve?

antes de mais, está mal escrito

fflush(stdin);

segundo, essa solução funciona no windows e no linux, mais devido ao número de "pedidos" para tal. não é uma solução ISO C.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

testei

scanf("%*[^\n]"); scanf("%*c"); e scanf("%*[^\n]%*c");

Mas não resolveu ( não limpou o buffer), aliás, obtive resultados interessantes... Uso o compliador GCC no Ubuntu e o que funciona para limpar buffer do teclado é a função __fpurge(). Ou seja, usa-se o seguinte:

__fpurge(stdin); //limpa buffer do teclado sem falha, pelo menos no sistema que uso e complilador GCC.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Vi algures que o scanf dava entrada a virus, que se devia utilizar getchar, é possível substituir completamente p scanf pelo getchar?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Vi algures que o scanf dava entrada a virus, que se devia utilizar getchar

são essas afirmações que levam um gajo a dizer : "Jesus Cr1st0 !!!"

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora