Pergunta

Qual é a maneira mais segura e melhor de recuperar um tempo não assinado de uma string no C ++?

Eu conheço vários métodos possíveis.

Primeiro, convertendo um assinado há muito tempo retirado do ATOL.

char *myStr; // Initalized to some value somehow.
unsigned long n = ((unsigned)atol(myStr));

O problema óbvio com isso é: o que acontece quando o valor armazenado no Mystr é maior do que um longo longo pode conter? O que o ATOL recupera?

A próxima possibilidade é usar o strtoul.

char *myStr; // Initalized to some value somehow.
unsigned long n = strtoul(myStr, 0, 10);

No entanto, isso é um pouco mais complicado para minhas necessidades. Eu gostaria de uma função simples, string in, base longa sem assinatura 10 out. Além disso, o manuseio de erros deixa muito a desejar.

A possibilidade final que encontrei é usar o SSCANF.

char *myStr; // Initalized to some value somehow.
unsigned long n = 0;
if(sscanf(myStr, "%lu", n) != 1) {
    //do some error handling
}

Novamente, o manuseio de erros deixa muito a desejar e um pouco mais complicado do que eu gostaria.

A opção óbvia restante é escrever um invólucro em torno de uma das possibilidades anteriores ou algo que percorre a corda e converte manualmente cada dígito até atingir o ULONG_MAX.

Minha pergunta é: quais são as outras opções que meu Google-FU não encontrou? Qualquer coisa na biblioteca C ++ STD que converterá de maneira limpa uma string em um longo não assinado e lançará exceções sobre o fracasso?

Peço desculpas se isso é um idiota, mas não consegui encontrar nenhuma dúvida que correspondesse exatamente à minha.

Foi útil?

Solução

Uma maneira de fazer isso:

stringstream(str) >> ulongVariable;

Outras dicas

Você pode usar o strtoul sem nenhum problema. A função retorna um longo tempo não assinado. Se a conversão não puder ser executada, o retorno da função 0. Se o valor longo correto estiver fora de intervalo, a função retorna ulong_max e a variável Global Errno será definida como Erange.

template <class T>
T strToNum(const std::string &inputString,
           std::ios_base &(*f)(std::ios_base&) = std::dec)
{
    T t;
    std::istringstream stringStream(inputString);

    if ((stringStream >> f >> t).fail())
    {
        throw runtime_error("Invalid conversion");
    }
    return t;
}


// Example usage
unsigned long ulongValue = strToNum<unsigned long>(strValue);
int intValue             = strToNum<int>(strValue);

int intValueFromHex      = strToNum<int>(strHexValue,std::hex);
unsigned long ulOctValue = strToNum<unsigned long>(strOctVal, std::oct);

Se você pode usar as bibliotecas de impulso (www.boost.org), olhe para a biblioteca de conversão - é um cabeçalho apenas incluir

#include "boost/lexical_cast.hpp"

Então tudo que você precisa fazer é

unsigned long ul = boost::lexical_cast<unsigned long>(str);

Jeffrey Stedfast tem um lindo post sobre escrever rotinas de parsers para mono (em c).
Ele gera código que usa usa tipos nativos (você precisa de 32 bits para analisar 32 bits) e códigos de erro para transbordar.

Use a função DST em "ATOL"

Por exemplo, std :: string input = "1024";

std :: atol (input.c_str ());

O ATOL espera que o parâmetro seja da string tipo C, então C_STR () faz isso para você.

A maneira robusta será escrever uma função estática e usá -la

bool str2Ulong(const string& str,unsigned long & arValue)
{
   char *tempptr=NULL;
   arValue=strtoul(str,tempptr,10);

   return ! (arValue==0 && tempptr==str.c_str());

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top