Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Рецепты в этой главе предоставляют решения некоторых общих проблем, с которыми обычно сталкиваются при работе с числами в С++, но они не пытаются решать проблем, специфичных для конкретных приложений. При написании научного или инженерного приложения вам также следует взглянуть на главу 11, которая содержит рецепты ко многим общим научным и инженерным алгоритмам.

3.1. Преобразование строки в числовой тип

Проблема

Имеются числа в строковом формате, и вам требуется преобразовать их в числовой тип, такой как

int
или
float
.

Решение

Это

можно сделать двумя способами — с помощью функций стандартной библиотеки или с помощью класса
lexical_cast
из Boost (написанного Кевлином Хенни (Kevlin Henney) Функции стандартной библиотеки неуклюжи и небезопасны, но они стандартны, и в некоторых случаях потребуются именно они, так что в первом решении я представлю именно их.
lexical_cast
более безопасен, проще в использовании и интереснее, так что я представляю его в обсуждении.

Функции

strtol
,
strtod
и
strtoul
, определенные в
<cstdlib>
, преобразуют символьные строки, ограниченные нулем, в
long int
,
double
или
unsigned long
. Они могут использоваться для преобразования чисел, представленных в виде строк с любым основанием, в числовые типы. Код примера 3.1 демонстрирует функцию
hex2int
, которая предназначена для преобразования шестнадцатиричной строки в
long
.

Пример 3.1. Преобразование числовых строк в числа

#include <iostream>

#include <string>

#include <cstdlib>

using namespace std;

long hex2int(const string& hexStr) {

 char *offset;

 if (hexStr.length > 2) {

if (hexStr[0] == '0' && hexStr[1] == 'x') {

return strtol(hexStr.c_str, &offset, 0);

}

 }

 return strtol(hexStr.c_str, &offset, 16);

}

int main {

 string str1 = "0x12AB";

 cout << hex2int(str1) << endl;

 string str2 = "12AB";

 cout << hex2int(str2) << endl;

 string str3 = "0AFG";

 cout << hex2int(str3) << endl;

}

Вот вывод этой программы.

4779

4779

0

Первые две строки содержат шестнадцатеричное число 12AB. Первая из них содержит префикс

0x
, а вторая — нет. Третья строка не содержит правильного шестнадцатеричного числа. В этом случае функция просто возвращает 0.

Обсуждение

Некоторые люди склонны писать свои собственные функции для преобразования шестнадцатеричных чисел в целочисленные форматы. Но зачем изобретать колесо? Стандартная библиотека уже предоставляет

эту функциональность. Пример 3.1 представляет собой функцию-оболочку, упрощающую вызов
strtol
. Функция
strtol
— это старая функция библиотеки С, и она требует от вас передачи указателя на завершающуюся нулем строку, а так же адрес еще одного указателя на строку. Этот второй указатель получает адрес, на котором обработка строки завершилась. Однако в C++ большинство людей предпочитает работать с более мощным классом
string
, а не со старыми указателями на символьные строки. Поэтому функция
hex2int
принимает параметр типа
string
.

Функция

strtol
несколько странна в том, что она позволяет использовать два разных метода указания основания 16: 16 можно передать как третий параметр функции, а можно в качестве основания передать 0, но предварить строку символами
0x
(точно также, как это делается для обозначения шестнадцатеричных чисел в коде, но только помните, что в случае с
strtol
передается строка).

Пример 3.1 позволяет использовать оба метода. При передаче строки вида

0x12AB
функция обнаружит
0x
и передаст ее непосредственно в
strtol
, в качестве третьего параметра передав 0. В противном случае функция передаст строку, в качестве третьего параметра передав 16.

strtol
и
strtoul
работают одинаково, за исключением типа возвращаемого значения.
strtod
аналогична им, но не позволяет указывать основание.

Эти старые функции С не являются единственным способом преобразования строк в числа. Проект Boost предоставляет класс преобразования

lexical_cast
, который выполняет то же самое для числовых строк, записанных с основанием 10. Пример 3.2 показывает как он используется.

Пример 3.2. Использование lexical_cast

#include <iostream>

#include <string>

#include <boost/lexical_cast.hpp>

using namespace std;

int main {

 string str1 = "750" ;

 string str2 = "2.71";

 string str3 = "0x7FFF";

 try {

cout << boost::lexical_cast<int>(str1) << endl;

cout << boost::lexical_cast<double>(str2) << endl;

cout << boost::lexical_cast<int>(str3) << endl;

 } catch (boost::bad_lexical_cast& e) {

cerr << "Bad cast: " << e.what << endl;

 }

}

Вывод примера 3.2 таков.

750

2.71

Bad cast: bad lexical cast: source type value could not be

interpreted as target

(Неверное преобразование: неверное лексическое преобразование: значение исходного типа не может быть преобразовано в целевой.)

Поделиться:
Популярные книги

Жандарм 4

Семин Никита
4. Жандарм
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Жандарм 4

Прорвемся, опера! Книга 2

Киров Никита
2. Опер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прорвемся, опера! Книга 2

Шайтан Иван 2

Тен Эдуард
2. Шайтан Иван
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Шайтан Иван 2

Архил...? 4

Кожевников Павел
4. Архил...?
Фантастика:
фэнтези
попаданцы
альтернативная история
5.50
рейтинг книги
Архил...? 4

Идеальный мир для Лекаря 6

Сапфир Олег
6. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 6

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Кротовский, не начинайте

Парсиев Дмитрий
2. РОС: Изнанка Империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, не начинайте

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Фиктивный брак

Завгородняя Анна Александровна
Фантастика:
фэнтези
6.71
рейтинг книги
Фиктивный брак

Николай I Освободитель. Книга 2

Савинков Андрей Николаевич
2. Николай I
Фантастика:
героическая фантастика
альтернативная история
5.00
рейтинг книги
Николай I Освободитель. Книга 2

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Корпулентные достоинства, или Знатный переполох. Дилогия

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.53
рейтинг книги
Корпулентные достоинства, или Знатный переполох. Дилогия

Барон устанавливает правила

Ренгач Евгений
6. Закон сильного
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Барон устанавливает правила

Отдельный танковый

Берг Александр Анатольевич
1. Антиблицкриг
Фантастика:
боевая фантастика
альтернативная история
5.00
рейтинг книги
Отдельный танковый