2012-02-27 3 views
4

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

Код анализирует текстовые файлы, созданные нашими клиентами. Иногда они используют десятичные точки, а иногда и десятичные запятые, но не тысячи разделителей.

+3

Вы не можете подставить запятые для десятичной точки в качестве этапа предварительной обработки? Факт локализации в iostreams будет способом продвижения вперед, но удачи, пытаясь понять их ... – Nim

+0

Я согласен с Nim, всякий раз, когда я это делаю, я просто нормализую входные данные перед обработкой –

ответ

8

Используйте std::replace делать тяжелую работу:

#include <cstdlib> 
#include <string> 
#include <algorithm> 

double toDouble(std::string s){ 
    std::replace(s.begin(), s.end(), ',', '.'); 
    return std::atof(s.c_str()); 
} 

Если вам нужно справиться с тысячами сепараторах было бы быть гораздо сложнее.

3

Просто найдите десятичной запятой ',' и преобразовать его в '.', а затем использовать atof из <cstdlib>:

#include <cstdlib> 
#include <cstdio> 
#include <string> 

double toDouble(std::string s){ 
    // do not use a reference, since we're going to modify this string 
    // If you do not care about ',' or '.' in your string use a 
    // reference instead. 
    size_t found = s.find(","); 
    if(found != std::string::npos) 
     s[found]='.'; // Change ',' to '.' 
    return std::atof(s.c_str()); 
} 

int main(){ 
    std::string aStr("0.012"); 
    std::string bStr("0,012"); 

    double aDbl = toDouble(aStr); 
    double bDbl = toDouble(bStr); 

    std::printf("%lf %lf\n",aDbl,bDbl); 
    return 0;  
} 

Если вы используете C строку вместо std::string использования strchr от <cstring> изменить исходную строку (не забудьте изменить его или работать с копией локали, если вам понадобится оригинальная версия).

+0

Будьте осторожны с любым из двух символов: используется как разделитель тысяч, хотя! В зависимости от вашего ввода вы можете конвертировать '100.546,89' в' 100.546.89', что не является юридическим номером. Не забудьте проверить это – Nick

+1

@ Ник: Я согласен, однако OP заявил, что «Иногда они используют десятичные точки, а иногда и десятичные запятые, но * никогда тысячи разделителей *», поэтому эта проблема не должна возникать. – Zeta

0

Если вы хотите, чтобы сделать это, как часть нормального показанию std::istream вы бы создать пользовательские std::num_get<...> огранку, поместите его в std::locale объект, и установить, что в ваш поток, используя imbue() (или установив std::locale в качестве глобальный язык перед созданием потока).

+0

Могу ли я создать настраиваемый фасет std :: num_get <...> без написания собственного анализатора с плавающей запятой с нуля? – user763305

+0

Ну, да и нет. Интересная часть синтаксического анализа с плавающей запятой преобразует строку в «double». Это, например, 'strtod()' может делать. Тем не менее, вы будете помещать символы для этого вместе. Это немного раздражает, но не так сложно. –

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