Ir para conteúdo
Fórum Script Brasil

Hiago Couto

Membros
  • Total de itens

    0
  • Registro em

  • Última visita

Sobre Hiago Couto

Últimos Visitantes

O bloco dos últimos visitantes está desativado e não está sendo visualizado por outros usuários.

Hiago Couto's Achievements

0

Reputação

  1. Oi.

    Tenho uma duvida sobre um post seu (a saber: 

    ). Sou iniciante em programação e gostaria de saber o porque do uso do número 1 entre a porcentagem e o d(Ex: %1d). Além disso tenho dúvidas sobre o "*c", testei o código com e sem ele e deu o mesmo resultado.

    Ps: O código funcionou bem, minha dúvida é o porque de ter funcionado. rs

    Desde já agradeço a atenção.

    Hiago Couto, 2017

     

    1. vangodp

      vangodp

      Enter é considerado um char, igual que outros tantos, '1', 'a', ' ', '\t', '\0', etc. O enter é o '\n'.
      Quando seu programa chegar em um scanf que estiver pedindo um char ou uma string, você irá digitar o que se pede, ato seguido você digitará enter('\n') para indicar que já terminou de entrar com os dados, esse é exatamente o problema. Tudo o que digitamos vai parar no buffer de entrada. Se temos por exemplo que ler 2 chars consecutivos teríamos algo como isso:
      char a;
      char b;
      scanf("%c", &a);
      scanf("%c", &b);

      quando o programa chegar no primeiro scanf o programa vai se deter para esperar que você digite o valor da variável a, você irá digitar um char qualquer e pulsar enter, 2 pelo preço de 1 >_<, ao buffer irá parar "x\n", ou seja x mais o \n, dai o programa espera um char, que é o a, dai a = 'x', x sai do buffer e vai parar no a, agora no buffer tem ainda o \n, como falei \n é um char, porem é um char que não imprime nada, faz um salto de linha, dai b = '\n', O enter vai parar no b, o programa não vai se deter, vai atribuir os 2 chars que estiverem no buffer nas seguintes 2 variáveis do tipo char ou string que aparecerem, até que o buffer permaneça vazio. Resumindo... no primeiro scanf você digitaria um char e pulsaria enter, o enter iria parar ao buffer junto com a letra que você deseja, e a partir desse momento o enter causaria erros no seu programa, você teria o que conhecemos por "lixo" no buffer.

      Existem varias formas de se abordar esse problema, mas basicamente todas se dividem em 2 formas, uma é "ignorar" a letra que não é desejada que é o caso do %*c, e outra é ler os valores do buffer até ele estar vazio antes de fazer uso dele novamente.

      O especificador de formato %*c é o contrario de %c, se o %c lê um char, o especificador %*c o ignora, então quando tiver %c seguido de %*c quer dizer que você está lendo um char e ignorando outro, porque como falei na hora de entrar com um char você digita uma letra e aperta enter, isso na realidade são 2 letras, então %c%*c lê uma e ignora a outra.

      As outras formas são limpando o buffer, existem varias maneiras de se fazer isso.
      Alguns livros recomendam você usar o fflush(stdin) mas não é uma boa pratica pois fflush foi criado para ser usado com stdout(buffer de saída padrão) e não com o stdin(buffer de entrada padrão), o fato que funcione é pura sorte, mas pode gerar erros muito difíceis de encontrar.

      A melhor forma de esvaziar o buffer é ler tudo o que estiver nele. Por exemplo se eu usar o getchar eu retiro uma letra do buffer, se eu jogar essa letra em uma variável que não irei usar não importa muito. Essa função que lhe irei deixar aqui esvazia todas as letras que estiverem no buffer, é só chamar ela depois de cada leitura. Use ela sempre antes de ler um char ou uma string e seu programa nunca terá erros.

      //funcion que vacia el buffer
      void flush_in() {
          int ch;
          
          while ( ( ch = fgetc ( stdin ) ) != EOF && ch != '\n' ) {}
      }


      Um exemplo de uso poderia ser esse:

      /funcion que vacia el buffer
      void flush_in() {
          int ch;
          
          while ( ( ch = fgetc ( stdin ) ) != EOF && ch != '\n' ) {}
      }
      
      int main () {
      
          char a, b;
          
          printf ( "Entre a primeira letra" );
          scanf ( "%c", &a );
          //flush_in();
          
          
          printf ( "Entre a segunda letra" );
          scanf ( "%c", &b );
          
          
          printf ( "\n\nPrimera: %c \nSegunda: %c", a, b );
          
          getchar();
          return 0;
      }

      O programa dará erro, você não será capaz de ler o segundo char, porem se tirar o comentário de adiante da função flush_in() antes de ler o segundo char você verá que o programa não dará erros, pois o buffer estará limpo antes de ler o segundo char.

      Provavelmente essa seja a melhor forma de limpar o buffer que exista. A outra é ignorando o char que causa o erro, se não entrar ao buffer chars indesejados não há motivo para limpar.

      Busque mais informação de como limpar o buffer em C, ou lixo no buffer, erros de entrada em C, etc. Faça muita leitura para entender.

       

    2. vangodp

      vangodp

      Sobre o %1d, para isso você deve entender primeiro o comportamento que tem %d.
      O especificador %d Lê um inteiro que vai desde −32,767 até +32,767, então como naquele caso que você indica, ele quer digitar por exemplo, "1234", e quer que o 1 fique na primeira variável, o 2 na segunda, o 3 na terceira e assim por diante. Ele quer separar um numero de 4 cifras em 4 unidades e atribuir uma unidade a cada variável, sendo 4 neste caso. Porem se ele digitar 1234, como vai saber o programa se tem que guardar 1234 na primeira? Ou 1 na primeira e o resto na segunda? Ou um em cada uma? Com %1d se ele digitar 1234, e somente o 1 vai parar na primeira, se fosse %2d iria a parar um 12 na primeira e o resto dependeria do tipo de especificador que vier em seguida.

      Um especificador não é exatamente uma coisa fixa. Por exemplo o especificador %s poderia aparecer como %24s, %*s, %.10s etc etc. Em teoria um especificador pode estar composto por estas partes:
      %[flags][width][.precision][length]specifier 
      Para saber o que significa tudo isso entre aqui:
      Especificadores para printf: http://www.cplusplus.com/reference/cstdio/printf/
      Especificadores para scanf:http://www.cplusplus.com/reference/cstdio/scanf/
      Especificadores para fprintf:http://www.cplusplus.com/reference/cstdio/fprintf/
      Especificadores para fscanf:http://www.cplusplus.com/reference/cstdio/fscanf/

      Teria alguns outros como sscanf, sprintf, etc. Não são iguais os especificadores entre diferentes funções. Poderia até ser igual porem ter diferentes finalidades em diferentes funções.

      Procure praticar bastante com os especificadores. Busque em internet.

       

    3. Hiago Couto

      Hiago Couto

      Cara, não sei nem como te agradecer. Você tirou varias dúvidas minhas e me ajudou a entender um pouco mais sobre como funciona o buffer, farei questão de pesquisar mais sobre especificadores e limpeza de buffer.

      Muito obrigado pela atenção. 

×
×
  • Criar Novo...