Caracteres extraídos por istream >> double
Código de amostrana Coliru:
#include <iostream>
#include <sstream>
#include <string>
int main()
{
double d; std::string s;
std::istringstream iss("234cdefipxngh");
iss >> d;
iss.clear();
iss >> s;
std::cout << d << ", '" << s << "'\n";
}
Estou lendo o N3337 aqui (presumivelmente é o mesmo que o C ++ 11). Em [istream.formatted.arithmetic], temos (parafraseado):
operator>>(double& val);
Como no caso dos insersores, esses extratores dependem do objeto num_get <> (22.4.2.1) da localidade para realizar a análise dos dados do fluxo de entrada. Esses extratores se comportam como funções de entrada formatadas (conforme descrito em 27.7.2.2.1). Após a construção de um objeto de sentinela, a conversão ocorre como se fosse realizada pelo seguinte fragmento de código:
typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);
Olhando para 22.4.2.1:
Os detalhes desta operação ocorrem em três etapas
- Etapa 1: determinar um especificador de conversão
- Estágio 2: extraia os caracteres de in e determine um valor de char correspondente para o formato esperado pela especificação de conversão determinada no estágio 1.
- Etapa 3: armazenar resultados
Na descrição do Estágio 2, é muito longo para eu colar a coisa toda aqui. No entanto, diz claramente que todos os caracteres devem ser extraídos antes da tentativa de conversão; e ainda que exatamente os seguintes caracteres devem ser extraídos:
qualquer um0123456789abcdefxABCDEFX+-
O localdecimal_point()
O localthousands_sep()
Por fim, as regras para o Estágio 3 incluem:
- Para um valor de ponto flutuante, a funçãostrtold
.
O valor numérico a ser armazenado pode ser um dos seguintes:
- zero, se a função de conversão falhar ao converter o campo inteiro.
Tudo isso parece especificar claramente que a saída do meu código deve ser0, 'ipxngh'
. No entanto, ele realmente gera outra coisa.
Isso é um bug do compilador / biblioteca? Existe alguma disposição que estou ignorando para uma localidade para alterar o comportamento do Estágio 2? (Nooutra pergunta alguém postou um exemplo de sistema que realmente extrai os caracteres, mas também extraiipxn
que não estão na lista especificada em N3337).
Como apontado por perreal, este texto do estágio 2 é relevante:
Se o descarte for verdadeiro, se '' ainda não tiver sido acumulado, a posição do personagem será lembrada, mas o personagem será ignorado. Caso contrário, se '' já tiver sido acumulado, o personagem será descartado e o estágio 2 será encerrado. Se não for descartado, é feita uma verificação para determinar sec
é permitido como o próximo caractere de um campo de entrada do especificador de conversão retornado pelo Estágio 1. Nesse caso, ele é acumulado.
Se o caractere for descartado ou acumulado, o in será avançado por ++ in e o processamento retornará ao início do estágio 2.
Portanto, o estágio 2 pode terminar se o personagem estiver na lista de caracteres permitidos, mas não for um caractere válido para%g
. Não diz exatamente, mas presumivelmente isso se refere à definição defscanf
do C99, que permite:
e também
Em outro local que não o "C", podem ser aceitas formas adicionais de sequência de assunto específicas do local.
Então, na verdade, a saída do Coliru está correta; e de fato o processamentodevo tentativa de validar a sequência de caracteres extraídos até uma entrada válida para%g
, ao extrair cada caractere.
Próxima pergunta: é permitido, como no tópico ao qual vinculei anteriormente, aceitari
, n
, p
etc no estágio 2?
Esses são caracteres válidos para%g
, no entanto, eles não estão na lista de átomos que a Etapa 2 pode ler (ou seja,c == 0
para minha última citação, para que o personagem não seja descartado nem acumulado).