Разбор строк C ++ в Double с исключениями? - PullRequest
2 голосов
/ 04 сентября 2010

В Java, если бы я хотел создать какое-то приложение, которое могло бы получать как двойные, так и строковые значения в качестве подходящего ввода, я бы, вероятно, сделал следующее:

String input = getInput();//
try { 
    double foo = Double.valueOf(input);
    //Do stuff with foo here 
} catch (NumberFormatException e) { 
    //Do other validation with input
} 

Как бы вы поступили так в c ++?atof() возвращает 0.0 для неверного ввода, но как бы вы отличили это от действительного двойного числа "0.0"?Кроме того, я могу включить в этот проект только <iostream>, <string>, <cstdlib> и <cassert>.Я предполагаю, что мне нужно каким-то образом использовать cin, но как вы можете получить исходный ввод после того, как cin не удастся проанализировать некоторую строку как двойную?

Редактировать: Возможно, я мог бы использовать следующее, но, как я уже говорил, мне не разрешено импортировать <sstream> по этому назначению по некоторым причинам

string input;
getline(cin, input);

double x;
istringstream foo(input);
foo >> x
if(cin){
    //do manipulations with x
}
else{
    //since it's not a number, check if input is a valid command etc..
}

Ответы [ 5 ]

5 голосов
/ 04 сентября 2010

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

Единственный реальный вопрос - это точное обстоятельство, при котором вы хотите, чтобы ввод обрабатывался как строка.Например, если входная строка была чем-то вроде «1.23e2 нечисловые данные», хотите ли вы просто использовать «1.23e2» в качестве числа, или вы хотите рассматривать все это как строку?

В любом случае, вы захотите нам strtod за конвертацию - разница только в том, как вы реагируете на то, что он возвращает.В частности, strtod принимает два параметра вместо одного, как atof.Второй параметр - это указатель на указатель на символ.Предполагая, что вы передаете ненулевой указатель, strtod установит его так, чтобы он указывал на последний символ входной строки, который он успешно преобразовал.Если он указывает на начало входной строки, ничего не было преобразовано.Если это указывает на конец, все было преобразовано.Если он где-то посередине, часть строки преобразована, а часть нет.

В настоящий момент я собираюсь предположить, что вы хотите получить двойное значение, содержащее любое число, которое может быть преобразовано в началестрока и все, что не может быть преобразовано, рассматривается как строка:

#include <stdlib.h>
#include <stdio.h>

int main() { 
    char input[] = "12.34 non-numeric data";
    char *string;
    double value = strtod(input, &string);

    printf("Number: %f\tstring: %s\n", value, string);
    return 0;
}
2 голосов
/ 04 сентября 2010

C ++ потоки связывают флаги хорошего, плохого и сбойного состояния. Они хранятся в ios_base::goodbit, ios_base::badbit и ios_base::failbit соответственно, но обычно доступны через ios::good(), ios::bad() и ios::fail(). Также есть ios_base::eofbit и ios::eof(), но давайте пока проигнорируем это.

Если синтаксический анализ завершается неудачно, возникает плохой бит. Кроме того, потоковые объекты могут быть преобразованы в булево-совместимый тип. Если поток находится в хорошем состоянии, то оператор

if( stream )

оценивает stream как истину. В противном случае он оценивает его как ложное. Имея это в виду, получение значения из стандартного ввода сводится к следующему:

#include <iostream>

// ...
double d = 0;
if ( std::cin >> d ) {
    // input is a double. handle that here.
} else {
    // input isn't a double. handle that here.
}
1 голос
/ 04 сентября 2010

попробуйте "strtod" в stdlib.h

0 голосов
/ 04 сентября 2010

Вы можете взглянуть на boost::lexical_cast, что позволит вам написать в значительной степени эквивалент Java-кода:

string input;
getline(cin, input);

try {
    double x = boost::lexical_cast<double>(input);
    //Do manipulations with x
} catch (boost::bad_lexical_cast &) {
    //Do other validation with input
}
0 голосов
/ 04 сентября 2010

Стандартная библиотека C ++, похоже, избегает исключений для многих вещей, которые люди могут ожидать от них, и это может быть не тот ответ, который вы хотите услышать, но анализ парных разрядов не совсем ракетостроение, так что, возможно, все будет в порядкечтобы сделать это «вручную»?

Одна заметка, если вы сделаете это, вы, вероятно, захотите собрать ее в целое число, а затем преобразовать в двойное и разделить на 10 ^ number_of_digits_after_decimal_point.

...