true, что означает, что значения одинаковы. Таким образом, равными окажутся значения 0.3333, 0.33333, 0.333333, 0.33333333333 и 0.33333323438.
Чтобы выполнить операцию «doubleEquals. Если так, то при наличии теста на равенство верните true, а в противном случае — false. В противном случае выполните прямое сравнение.
3.5. Лексический анализ строки, содержащей число в экспоненциальной форме
Имеется строка, содержащая число в экспоненциальной форме, и требуется сохранить значение числа в переменной типа double.
Наиболее простым способом анализа числа в экспоненциальной форме является использование встроенного в библиотеку C++ класса stringstream, объявленного в <sstream>, как показано в примере 3.7.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
double sciToDub(const strings str) {
stringstream ss(str);
double d = 0;
ss >> d;
if (ss.fail()) {
string s = 'Невозможно отформатировать ';
s += str;
s += ' как число!';
throw (s);
}
return (d);
}
int main() {
try {
cout << sciToDub('1.234e5') << endl;
cout << sciToDub('6.02e-2') << endl;
cout << sciToDub('asdf') << endl;
} catch (string& e) {
cerr << 'Ошибка: ' << e << endl;
}
}
Далее показан вывод этого кода.
123400
0.0602
Ошибка: невозможно отформатировать asd как число!
Класс stringstream — это string, который ведет себя как поток (что неудивительно). Он объявлен в <sstring>. Если требуется выполнить анализ string, содержащей число в экспоненциальной форме (см. также рецепт 3.2), то с этой работой прекрасно справится stringstream. Стандартные классы потоков уже «знают», как анализировать числа, так что не тратьте без острой необходимости время на повторную реализацию этой логики.
В примере 3.7 я написал простую функцию sciToDub, принимающую параметр типа string и возвращающую содержащийся в ней double, если он допустим. В sciToDub я использую stringstream следующим образом.
stringstream ss(str); // Конструирование из строки типа string
double d = 0;
ss >> d;
if (ss.fail()) {
string s = 'Невозможно отформатировать ';
s += str;
s += ' как число!';
throw (s);
}
return (d);
Наиболее важной частью здесь является то, что все, что требуется сделать, — это использовать для чтения из строкового потока в double оператор сдвига вправо (>>), как это делается при чтении из cin.
Ну, это не совсем stringstream записано значение, которое не может быть записано в переменную в правой части оператора >>, то для потока будет выставлен бит fail. Этот бит можно проверить с помощью функции-члена fail (на самом деле это функция-член basic_ios, который является родительским классом для stringstream). Кроме того, переменная справа от оператора >> в случае ошибки значения не меняет.
Однако с целью обобщения можно избежать написания отдельных версий sciToDub для типов int, float, double и чего-либо еще, что может потребоваться преобразовать, если написать шаблон функции. Рассмотрим такую новую версию.
template<typename T>
T strToNum(const string& str) {
stringstream ss(str);
T tmp;
ss >> tmp;
if (ss.fail()) {
string s = 'Невозможно отформатировать ';
s += str;
s += ' как число!';
throw (s);
}
return (tmp);
}
Теперь, чтобы преобразовать string в числовой тип, можно сделать так.
double d = strToNum<double>('7.0');
float f = strToNum<float>('7.0');
