Здравствуйте, all!
"Он не хочет умирать медленно и мучительно, он хочет — быстро и мучительно!"
Очень быстрый, но злой способ: конечный автомат на таблицах (7 состояний * 256 чар)
(char, state) --> newstate
Менее злой и быстрый: КА на проверках.
Грамматика числа выглядит так:
<floatnum> ::=
(start) [ <sign> ]
(startint) <digit>
(integral) [{ <digit> }]
[ <dot>
(fractional) [{ <digit> }]
]
[ <exp>
(startexp) [ <sign> ]
(startpower) <digit>
(power) [{ <digit> }]
]
(end)
<sign> ::= + | -
<digit> ::= 0 .. 9
<dot> ::= .
<exp> ::= E | e
(в круглых скобках указаны названия состояний; см. код ниже)
Вот, например:
bool test(const char* str)
{
enum STATE { s_start, s_startint, s_int, s_frac, s_startexp, s_startpower, s_power,
s_total, s_error = -1, s_success = -2 };
STATE state = s_start;
while(state != s_error)
{
char chr = *(str++);
if(chr == 0) // end of string
{
static const STATE next_eos[s_total] = {
s_error, s_error, // incomplete mantissa
s_success, s_success // complete mantissa
s_error, s_error, // incomplete exp part
s_success, // complete exp part
};
state = next_eos[state];
return state == s_success;
}
if(chr == '+' || chr == '-') // sign
{
static const STATE next_sign[s_total] = {
s_startint,
s_error, s_error, s_error, // repeated sign within mantissa
s_startpower,
s_error, s_error, // repeated sign within exp
};
state = next_sign[state];
continue;
}
if(chr == '.') // fraction point
{
static const STATE next_dot[s_total] = {
s_error, s_error, // at least 1 digit should be in an integer part of mantissa
s_frac,
s_error, s_error, s_error, // unexpected positions of a dot
};
state = next_dot[state];
continue;
}
if(chr == 'e' || chr == 'E') // exp mark
{
static const STATE next_exp[s_total] = {
s_error, s_error, // incomplete mantissa
s_startexp, s_startexp,
s_error, s_error, s_error, // repeated exp mark
};
state = next_exp[state];
continue;
}
if(chr >= '0' && chr <= '9')
{
const STATE next_digit[s_total] = {
s_int, s_int, s_int, // begin/continue integral part
s_frac, // begin/continue fractional part
s_power, s_power, s_power, // begin/continue exp part
};
state = next_digit[s_total];
continue;
}
// all other chars
state = s_error;
return false;
}
return state == s_success;
}
А на таблицах сие выглядит так
enum STATE { s_start, s_startint, s_int, s_frac, s_startexp, s_startpower, s_power,
s_total, s_error, s_success };
static const next_eos[s_total], next_dot[s_total], ... ; // см. выше
static const next_error[s_total] = { s_error, s_error, s_error, s_error, s_error, s_error, s_error };
static STATE* next[256];
void initnext()
{
int i;
for(i = 0; i < 256; i++) next[i] = next_error;
next[0] = next_eos;
next['.'] = next_dot;
// и т.д.
}
void test(const char* str)
{
STATE state = s_start;
while(state >= 0)
state = next[(unsigned char)(*(str++))][state];
return state == s_success;
}
Здравствуйте Holms, Вы писали:
H>является ли строка числом (целым, вещественным не имеет значения)?
Имхо для ускорения имеет смысл не писать одну "универсальную" функцию для проверки всех чисел.
На целое десятичное проверяеться как:
if (NULL == strpbrk (szString, "-+0123456789"))
{
// Не число !
//
}
Соттветственно для hex-ов "-+0123456789" меняется на "0123456789abcdefABCDEF", для действительных на "-+0123456789.eE", а дальше -- как душе угодно.
Здравствуйте TSS, Вы писали:
TSS>Здравствуйте Holms, Вы писали:
H>>является ли строка числом (целым, вещественным не имеет значения)?
TSS>Имхо для ускорения имеет смысл не писать одну "универсальную" функцию для проверки всех чисел.
TSS>На целое десятичное проверяеться как:
TSS>TSS> if (NULL == strpbrk (szString, "-+0123456789"))
TSS> {
TSS> // Не число !
TSS> //
TSS> }
TSS>
TSS>Соттветственно для hex-ов "-+0123456789" меняется на "0123456789abcdefABCDEF", для действительных на "-+0123456789.eE", а дальше -- как душе угодно.
Прогони пример посмотришь что получиться
int main(int argc, char* argv[])
{
char *line = "123dsf,dfsdfz";
if (NULL == strpbrk(line , "+-1234567890")) {
printf("The string %s is not number", line);
}else{
printf("The string %s is number",line);
}
getch();
return 0;
}
Здравствуйте Holms, Вы писали:
H>является ли строка числом (целым, вещественным не имеет значения)?
Народ, вы чего? вы б еще машину Тьюринга вспомнили.
По сути:
Если число целое (без знака):
очень быстро — делаешь logical OR (|) всех символов. Потом проверяешь или
if (result >= 0x30 && result <= 0x39)
можно проверять и в цикле, где делаешь OR. Но непонятно что быстрее будет ( на коротких строках)
Первое, что пришло в голову
...Complex problems have simple, easy-to-understand wrong answers...
(Grossman's Misquote of H.L.Mencken)
Здравствуйте fAX, Вы писали:
H>>является ли строка числом (целым, вещественным не имеет значения)?
fAX>Народ, вы чего? вы б еще машину Тьюринга вспомнили.
fAX>По сути:
fAX>Если число целое (без знака):
fAX>очень быстро — делаешь logical OR (|) всех символов. Потом проверяешь или
fAX>fAX>if (result >= 0x30 && result <= 0x39)
fAX>
fAX>можно проверять и в цикле, где делаешь OR. Но непонятно что быстрее будет ( на коротких строках)
fAX>Первое, что пришло в голову
Ага, счаз!
"69" == 0x36 | 0x39 == 0x3F == "?"
"!0" == 0x21 | 0x30 == 0x31 == "1" == "!\x010" == 0x21 | 0x10
"123 4 5 6" == "123456" (" " --> 0x20)
Так что, все же, конечные автоматы...
Здравствуйте Кодт, Вы писали:
К>Ага, счаз!
К>К>"69" == 0x36 | 0x39 == 0x3F == "?"
К>"!0" == 0x21 | 0x30 == 0x31 == "1" == "!\x010" == 0x21 | 0x10
da, etot kamen` v ogorod prinimaju
К>"123 4 5 6" == "123456" (" " --> 0x20)
a tut vy, baten`ka pogorjachilis`.
К>
К>Так что, все же, конечные автоматы...
A kakaja byla ideja ...

Pust` budut avtomaty...
...Complex problems have simple, easy-to-understand wrong answers...
(Grossman's Misquote of H.L.Mencken)
...Complex problems have simple, easy-to-understand wrong answers...
(Grossman's Misquote of H.L.Mencken)