Итак, стандартная заметка, пожалуйста, не беспокойтесь о производительности, если она еще не профилирована:)
Я не уверен насчет ручного цикла и проверки точки. Два выпуска
- В зависимости от локали, точка на самом деле может быть и "," (здесь, в Германии, это так:)
- Как уже отмечалось, существует проблема с числами вроде 1e7
Ранее у меня была версия с использованием sscanf здесь. Но измерение производительности показало, что sscanf значительно медленнее для больших наборов данных. Поэтому сначала я покажу более быстрое решение (ну, это также намного проще. У меня было несколько ошибок в версии sscanf, пока я не заработал, в то время как версия strto [ld] работала с первой попытки):
enum {
REAL,
INTEGER,
NEITHER_NOR
};
int what(char const* strg){
char *endp;
strtol(strg, &endp, 10);
if(*strg && !*endp)
return INTEGER;
strtod(strg, &endp);
if(*strg && !*endp)
return REAL;
return NEITHER_NOR;
}
Просто для удовольствия, вот версия с использованием sscanf:
int what(char const* strg) {
// test for int
{
int d; // converted value
int n = 0; // number of chars read
int rd = std::sscanf(strg, "%d %n", &d, &n);
if(!strg[n] && rd == 1) {
return INTEGER;
}
}
// test for double
{
double v; // converted value
int n = 0; // number of chars read
int rd = std::sscanf(strg, "%lf %n", &v, &n);
if(!strg[n] && rd == 1) {
return REAL;
}
}
return NEITHER_NOR;
}
Я думаю, это должно сработать. Повеселись.
Тест был выполнен путем преобразования тестовых строк (маленьких) случайным образом 10000000 раз в цикле:
- 6,6 с для
sscanf
- 1,7 с для
strto[dl]
- 0,5 с для
manual looping
до "."
Чистый выигрыш для strto[ld]
, учитывая, что он будет правильно разбирать числа, я буду хвалить его как победителя над ручным зацикливанием. В любом случае, разница в 1,2 с / 10000000 = 0,00000012 примерно для одной конверсии не так уж велика.