Problema com ciclo while

Eu to com um problema com meu ciclo.
O código funciona assim:
Manda digitar uma letra, o usuário digita, aperta enter e o ciclo se repete, se o usuário digitar espaço ele vai contar, e isso vai se repetir até o usuário finalizar com um ponto. E depois exibe quantos espaços foram dados. O único problema é que ele exibe 3 vezes a frase “Digite uma letra:” por que ele ta fazendo isso?

class espacos{
public static void main(String args[])
throws java.io.IOException{
char c;
int count=0;  
do{
System.out.println("Digite uma letra:");
c = (char) System.in.read();
if(c==32) count++;
}while(c!=46);
System.out.println("O numero de espacos digitados foi: " + count); 
}}

PS: Já tentei trocar para ciclo while, for,

A frase está sendo repetida pois se encontra dentro do laço!

Amigo isso eu sei, mas ela se REPETE 3 VEZES antes de deixar eu digitar uma letra.

Exemplo de saida:

Digite uma letra:
(DIGITANDO UMA LETRA)
Digite uma letra:
Digite uma letra:
Digite uma letra:
(DIGITANDO UMA LETRA)
Digite uma letra:
Digite uma letra:
Digite uma letra:
(DIGITANDO UMA LETRA)

Em vez de aparecer uma única vez. Entendeu?


Consertei trocando o char por uma string, dai usando o read.nextLine. E dai usei switch pra controlar o loop.
Ficou gigante mas rodou.

Mas ainda quero saber por que isso ta acontecendo… Já sei que o problema ta no system.in.read();

utilize a scanner para entrada de String vê se te ajuda isso:

import java.util.Scanner;

public class Espacos {

static int qntEspacos;
static String resp;

public static void main(String args[]) {
do {

   System.out.print("Digite uma palavra:");
   resp = new Scanner(System.in).nextLine();

   for (int c = 0; c < resp.length(); c++) {

         if (resp.charAt(c) == ' ') {

               qntEspacos++;
        }
   } 

  System.out.println("a palavra tem" + qntEspacos + " espacos");
  qntEspacos = 0;

} while (resp != “sair”);
}
}

Como eu havia dito anteriormente, eu consegui resolver usando string, porem quero saber o motivo de não funcionar usando System.in.read(); por que ele buga o ciclo while.

O enter também é um char (alias, em windows são 2). Por isso ele apresenta 3 vezes a mensagem (Duas delas ela passa no ciclo com o char 10 e char 13. Se colocares um else no teu if para imprimir o código do char vais ver que te aparece este 10 e 13.

System.in é um InputStream. O método read() lê exatamente 1 byte, nada mais, nada menos.

Pelo fato de sua entrada possuir mais de um byte (letra/espaço + enter), estes bytes ficam no buffer de entrada, esperando para serem lidos pelo método read(). Assim, ele lê um byte, volta no loop, e lê mais um byte restante do buffer, e assim sucessivamente.

A sugestão do @Pablo_Enrique_Gomes está corretíssima.

Há como limpar o buffer como no c que tem o fflush(stdin); ?

Como o amigo disse acima, o read() lê 1 byte (nada mais, nada menos).
O que acontece é o seguinte: quando você digita uma letra e aperta ENTER, o System.in entende que você também quer armazenar a tecla ENTER - uma vez que essa teclada significa quebra de linha. Então o que o read() faz, é ler essa quebra de linha, pois ela já está no buffer de memória. Por isso tantas repetições ocorrem dentro do laço.

Sempre podes ler todos os bytes disponíveis antes de pedir a letra. Não sei se será a melhor maneira mas de repente é a única que me ocorre:

do{
    System.in.read(new byte[System.in.available()]);  
    ...