5

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

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

Во-первых, преобразование подписанного долго взято из 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); 

Однако, это немного сложнее для моих нужд. Мне нужна простая функция, строка в, 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? Любая вещь в библиотеке std C++, которая будет чисто преобразовывать строку в unsigned long и исключать исключения при ошибке?

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

+0

'atol':« Если правильное значение выходит за пределы диапазона представляемых значений, возвращается LONG_MAX или LONG_MIN ». http://www.cplusplus.com/reference/clibrary/cstdlib/atol/ –

+0

Пара вопросов, я не уверен, что они дубликаты: (1) http://stackoverflow.com/questions/1243428/convert- string-to-int-with-bool-fail-in-c/1243435 (2) http://stackoverflow.com/questions/1435253/c-syntax-question-if-var-type-int/1435268 – GManNickG

+3

Я не знаю Не понимаю, что у вас есть против strtoul. Это идеальная функция для этого. Передайте 0 для базы и преобразуйте числа с любыми базовыми префиксными строками, которые понимает ваша библиотека C, например «0x». –

ответ

5

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

stringstream(str) >> ulongVariable; 
+0

Я отредактировал вопрос, чтобы уточнить, что я работаю со строками в стиле C в этом случае. Таким образом, это должно было бы быть streamstream (string (myStr)) >> ulongvariable. Который считает расточительным неэффективным для меня:/Я предпочел бы, чтобы это было чем-то более чистым и более прямым. –

+1

На самом деле это не обязательно, потому что 'std :: string' имеет неявный конструктор, который принимает строку C-стиля в качестве параметра. Этот конструктор позволяет вам писать просто 'stringstream (" whatever ")'. – hrnt

+0

* smack сам * конечно. Тем не менее, он имеет результат создания двух классов - и всех функций управления памятью, присущих этому, - чтобы сделать то, что может выполнить простая функция с одним внутренним циклом. Хотелось бы, чтобы в стандартной библиотеке было что-то подобное. –

5

Вы можете использовать strtoul без проблем. Функция возвращает unsigned long. Если преобразование не может быть выполнено, функция возвращает 0. Если правильное длинное значение выходит за допустимые пределы, функция возвращает ULONG_MAX и глобальную переменную errno в значение ERANGE.

+0

Ищет, если это возможно, обработку ошибок в стиле исключения, а не в стиле errno. –

+0

Обработка ошибок в стиле исключения, но не накладные расходы через классы? Звучит немного парадоксально imo :) –

+0

Ну, функции могут выполнять обработку ошибок в стиле исключения. Я просто не хочу создавать экземпляры двух классов, которые мне не нужны каждый раз, когда я хочу преобразовать длинный. Кажется очень расточительным! –

4
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); 
1

Jeffrey Stedfast has a beautiful post о написании процедур парсера для моно (в C).
Он генерирует код, который использует собственные типы (вам нужно 32 бит для разбора 32 бит) и коды ошибок для переполнения.

2

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

#include "boost/lexical_cast.hpp" 

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

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

Я изучу библиотеки boost, я рассматривал возможность использования библиотеки интерпретации python, поэтому использование boost может хорошо работать для моих нужд. Было бы неплохо, если бы для этого была простая чистая функция, для тех, кто не хочет зависимости от библиотек boost. –

0

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

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

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

} 
+1

Пример неправильный, tempptr is (char *), strtoul ожидает (char **) – nrathaus

1

Использовать встроенную функцию std atol

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

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

Atol ожидает, что параметр имеет тип c string, поэтому c_str() делает это для вас.

 Смежные вопросы

  • Нет связанных вопросов^_^