O cenário é: inserir inteiros e caracteres alternadamente e lê-los em variáveis do tipo correto. Adotei a abordagem mais direta: ler de qualquer maneira como se fossem todos inteiros; em caso de falha, redefinir os sinalizadores cin e ler como caracteres.
int a;
char c;
while (true) {
cin >> a;
if (cin.fail()) {
if (cin.eof()) {
cout << "eof" << endl;
break;
}
cin.clear();
cin >> c;
cout << "fail: " << c << ": " << int(c) << endl;
}
else {
cout << "success: " << a << endl;
}
}
Funciona perfeitamente, exceto pelos dois caracteres: +
, -
. Por exemplo, quando você insere 2 4 + 5 *
, a saída seria:
success: 2
success: 4
fail: 5: 53
fail: *: 42
eof
Para *
, funciona; mas para +
, parece que +
se perde e 5
é lido. Fiz alguns testes sozinho (por exemplo, usando cin.get()
instead) e descobri que: após cin >> a
falha ao encontrar +
, +
é consumido e a posição do fluxo aponta para o espaço entre +
e 5
.
O que torna +
um caractere -
especial? Após algumas pesquisas, acredito que o motivo possivelmente seja: quando cin
se espera um número inteiro, o caractere +
ou -
que ele encontra é aceito como um possível prefixo de números inteiros como +5, -3, etc. Isso leva ao fato de que ele +
é consumido, em vez de permanecer no fluxo de entrada como outros caracteres.
Como você interpreta o problema? Como corrigir o código para que ele funcione corretamente?
PS: Sei que uma solução alternativa é ler todas elas como strings e depois fazer uma análise mais aprofundada. Só estou curioso para saber se é possível modificá-las com base na abordagem original. Dessa forma, eu poderia ser mais claro sobre os mecanismos por trás de cin
.
Acho que este post já pode ser encerrado. Obrigado por todos os comentários e respostas. As opiniões e conselhos que vocês compartilharam são muito apreciados, com os quais aprendi muito.
Como eu disse, não se trata de uso prático e, em primeiro lugar, não estou procurando uma solução completa. Na prática, certamente adotarei as abordagens baseadas em strings sugeridas por você. É apenas um pequeno problema que encontrei, e depois decidi fazer uma breve digressão e brincar um pouco com a questão.
Quanto à questão que levantei, ou seja, corrigir o código, aprendi um pouco com as respostas abaixo e a documentação oficial. Usar funções como essa cin.putback() cin.peek() cin.tellg() cin.seekg()
ajudará a resolver o problema.
Os comentários à sua pergunta mostram que há muito mais em que pensar do que a mera questão "+/-".
No entanto, para abordar essa questão, sua análise está correta no sentido de que esses personagens podem ser interpretados como o começo de uma história
int
e foram consumidos.Uma solução alternativa para esse problema é analisar
char
porchar
e não porint
e tratar especificamente+
e-
:Observe o uso de
putback
que permite "desconsumir"+
ou-
e então tente ler umint
.entrada:
saída
Mas lembre-se: é apenas uma solução rápida para esse problema específico, mas analisar uma expressão possivelmente malformada levantará muitos outros problemas que não serão resolvidos apenas elaborando essa correção.
Sim,
+
e-
pode fazer parte de números inteiros ao ler de um fluxo. Você pode verificar isso por meio de um exemplo mais simples.A saída é :
Para a sua tarefa, sugiro manter o tratamento do fluxo separado da lógica de análise. Se você puder dispor de um pouco mais de memória e alocações, leia todas as entradas primeiro. Iterar uma string é mais simples do que entrar deliberadamente em um estado de erro do fluxo e reiniciá-lo.
Demonstração ao vivo
Não usar a extração de fluxo para analisar números inteiros tem o custo de usar
std::isdigit
e uma conversão dechar
paraint
(subtraindo'0'
). Presumo que você queira ler números inteiros de um único dígito. A leitura de números maiores pode ser feita consumindo mais caracteres da string comisdigit(c)!=0
de uma só vez.