Вопрос

Какой самый безопасный и наилучший способ извлечь длину без знака из строки в C ++?

Я знаю о нескольких возможных методах.

Во-первых, преобразуем подписанный long, взятый из atol.

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

Очевидная проблема с этим заключается в том, что происходит, когда значение, хранящееся в myStr, больше, чем может содержать подписанный long?Что извлекает atol?

Следующая возможность - использовать strtoul.

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

Тем не менее, это немного сложнее для моих нужд.Мне бы нужна простая функция, string in, unsigned long base 10 out.Кроме того, обработка ошибок оставляет желать лучшего.

Последняя возможность, которую я нашел, - это использовать sscanf.

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

Опять же, обработка ошибок оставляет желать лучшего и немного сложнее, чем хотелось бы.

Оставшийся очевидный вариант - написать свой собственный либо оболочку вокруг одной из предыдущих возможностей, либо что-то еще, что циклически перебирает строку и вручную преобразует каждую цифру, пока она не достигнет ULONG_MAX .

Мой вопрос в том, какие еще варианты не удалось найти моему google-fu?Есть что-нибудь в библиотеке C ++ std, что будет чисто преобразовывать строку в unsigned long и выдавать исключения при сбое?

Приношу свои извинения, если это обман, но я не смог найти ни одного вопроса, который бы точно соответствовал моему.

Это было полезно?

Решение

Один из способов сделать это:

stringstream(str) >> ulongVariable;

Другие советы

Вы можете использовать strtoul без проблем.Функция возвращает значение long без знака.Если преобразование не может быть выполнено, функция возвращает 0.Если правильное значение long выходит за пределы диапазона, функция возвращает ULONG_MAX, а глобальной переменной errno присваивается значение 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);

Если вы можете использовать библиотеки Boost (www.boost.org), посмотрите на библиотеку преобразования - это только заголовок.

#include "boost/lexical_cast.hpp"

тогда все, что вам нужно сделать, это

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

У Джеффри Стедфала есть красивый пост о написании рутинных процедур для моно (в C).
Он генерирует код, который использует используемые нативные типы (вам нужны 32 -битные для анализа 32 -битных) и коды ошибок для переполнения.

Используйте встроенную функцию STD «атол»

Например, std :: string input = "1024";

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

Atol ожидайте, что параметр будет из строки типа C, поэтому c_str () делает это для вас.

Надежный путь будет написать статическую функцию и использовать ее

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

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

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top