3.2. Преобразование чисел в строки
Имеются числовые типы (int
, float
), и вам требуется поместить их содержимое в string
, возможно, предварительно отформатировав.
Для выполнения этого имеется множество способов, каждый из которых имеет свои достоинства и недостатки. Первая представляемая мной методика использует для хранения строковых данных класс stringstream
, который является частью стандартной библиотеки и прост в использовании. Этот подход показан в примере 3.3. Смотри обсуждение альтернативных методик.
Пример 3.3. Форматирование числа как строки
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
using namespace std;
int main() {
stringstream ss;
ss << "В моей корзине " << 9 << " яблок.";
cout<<ss.str() <<endl; //stringstream::str() возвращает string
// с содержимым
ss.str(""); // Очистка строки
ss << showbase << hex << 16; // Показать основание в шестнадцатеричном формате
cout << "ss = " << ss.str() << endl;
ss.str("");
ss << 3.14;
cout << "ss = " << ss.str() << endl;
}
Вывод примера 3.3 выглядит так.
В моей корзине 9 яблок.
ss = 0x10
ss = 3.14
stringstream
— это удобный способ поместить данные в string
, поскольку он позволяет использовать все возможности форматирования, предоставляемые классами стандартного ввода и вывода. В простейшем случае в примере 3.3 я для записи комбинации текста и числовых данных в строковый поток просто использую оператор сдвига влево (<<
).
ss << "В моей корзине " << 9 << " яблок.";
Оператор <<
перегружен для встроенных типов и соответственно форматирует вывод. Когда требуется получить данные, хранящиеся в string
, используйте функцию-член str
.
cout << ss.str() << endl;
В <iomanip>
имеется большое количество манипуляторов потоками, и их использование при выводе числовых данных в строку позволяет выполнить все виды форматирования. В примере 3.3 для форматирования числа как шестнадцатеричного я использовал showbase
и hex
, но есть еще и другие возможности форматирования. Например, можно установить точность отображения, отличную от числа десятичных знаков по умолчанию.
ss << setprecision(6) << 3.14285;
Однако использование манипуляторов является не самой интуитивно понятной вещью, и именно поэтому создан рецепт, посвященный им. За дополнительной информацией о форматировании числовых данных с помощью манипуляторов потоками обратитесь к рецепту 10.2.
Конечно, как часто бывает в С++, имеется и другой способ. Библиотека Boost Format (написанная Сэмюэлем Кремппом (Samuel Krempp) содержит класс format
, который делает форматирование и преобразование очень простыми. Пример 3.4 показывает, как выполнить подобное преобразование.
Пример 3.4. Форматирование целых в шестнадцатеричное представление
#include <iostream>
#include <boost/format.hpp>
using namespace std;
using boost::format;
using boost.:io::str;
using boost::io::format_error;
int main() {
try {
format f("Имеется %1% способа. %2% %3% %4%");
f % 3;
f % "чтобы" % "это" % "сделать.";
cout << f << endl;
f.clear(); // Счистка буферов для форматирования чего-либо еще
f.parse("Это стоит $%d.");
f % 50;
cout << f << endl;
int x = 11256099;
string strx = str(format("%x") % x);
cout << strx << endl;
} catch (format_error &e) {
cout << e.what() << endl;
}
}
Вот что вы увидите при запуске этой программы.
Имеется 3 способа, чтобы это сделать.
Это стоит $50.
abc123
Использование класса format
требует двух шагов, включая создание объекта format
и передачу ему содержимого. Для простейшего случая в примере 3.4 я создал объект format с помощью простейшей версии его синтаксиса.
format f(" Имеется %1% способа, %2% %3% %4%");
В строке формата заполнители — это числа, обрамленные с обеих сторон символами %. Затем я начинаю передавать в объект содержимое указанного формата.
f % 3;
f % "чтобы" % "это" % "сделать;
Оператор %
в библиотеке форматирования был переопределен так, чтобы добавлять указанные в нем переменные в левую часть объекта format
. Его можно использовать как один раз на строку, так и несколько раз в одной строке. Он аналогичен оператору <<
для строк. Что же касается оператора <<
, он также был переопределен так, что объекты format
можно непосредственно записать в выходной поток. Кроме того, если требуется поместить результаты в строку, используйте функцию-член str
.
string s = f.str();
Если же вам нравится printf
, то можно использовать форматную строку printf
.
f.parse("Это стоит $%d.*");
f % 50;
Если будет записано слишком много или слишком мало переменных для указанного формата, то при попытке записать строку в поток или извлечь отформатированную строку будет выброшено исключение format_error
(или подкласс thereof
).
Класс format
достаточно мощен и содержит слишком много возможностей форматирования, чтобы их можно было описать здесь, и его стоит изучить. Чтобы скачать Boost или почитать документацию, посетите web-сайт Boost по адресу www.boost.org.
Также для преобразования чисел из числовых типов в строки можно использовать sprintf
или аналогичные ей функции. Обычно этого следует избегать, так как это небезопасно и для этого имеются лучшие альтернативы.
Глава 10.
3.3. Проверка, содержит ли строка допустимое число
Имеется строка string
и требуется определить, содержит ли она допустимое число.
Для проверки допустимости числа можно использовать шаблон функции lexical_cast
библиотеки Boost. При таком подходе допустимое число может включать предшествующий знак минус, предшествующий знак плюс, но не пробел. В примере 3.5 приводятся несколько образцов типов форматов, с которыми работает lexical_cast
.
Пример 3.5. Проверка числовой строки
#include <iostream>