Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Вопрос об оптимальности (парсинг строки вида “R142C1543:R18999C24568”)

#алгоритм #cpp


В итерационной процедуре (С++) из строки wchar_t вида "R142C1543:R18999C24568" необходимо
"выкусить" числовые данные:
long RS=142
   long RE=18999
   long CS=1543
   long CE=24568

Учитывая, что это надо сделать максимально эффективно, какие варианты вы можете предложить!?
(причём количество разрядов чисел постоянно меняется)    


Ответы

Ответ 1



Гляньте в сторону swscanf Можно было бы написать небольшой парсер для данной строки, чтобы не использовать сторонние библиотеки, однако загвоздка в типе wchar_t судя по википедии его размер сильно зависит от компилятора. Но если удастся все-таки за что-то зацепиться можно было бы написать небольшую функцию, по типу этой (сейчас она сделана для char): int main () { wchar_t * input = (wchar_t *)L"R142C1543:R18999C24568"; struct { long RS; long CS; long RE; long CE; } result = {0, 0, 0, 0}; long * current = (long *)&result; while (*++input) { switch (*input) { case L':' : input++; case L'C' : current++; break; default : *current = *current*10 + (*input - L'0'); } } printf("RS = %ld\n", result.RS); printf("CS = %ld\n", result.CS); printf("RE = %ld\n", result.RE); printf("CE = %ld\n", result.CE); } P.S. немного модифицировал код, чтобы работало с wchar_t, спасибо за подсказку @avp. P.S.S. L-ки перед символами ':', 'C', '0' вроде не обязательно ставить (по крайне мере работает как с ними так и без них), но я на всякий пожарный поставил.

Ответ 2



// C++ STYLE !!! using namespace std; ... string x("R142C1543:R18999C24568"); replace(x.begin(), x.end(), 'R', ' '); // удалим все лишние символы :-) replace(x.begin(), x.end(), 'C', ' '); replace(x.begin(), x.end(), ':', ' '); // более оптимальным является использование replace_if с lambda // это уменьшает кол-во проходов по строчке для замены с ТРЕХ до ОДНОГО /* replace_if(x.begin(), x.end(), [] (const char ch) -> bool {return (!isdigit (ch)); }, ' '); // можно и без лямбды // replace_if (x.begin(), x.end(), not1(ptr_fun(isdigit)), ' '); */ stringstream y(x); long RS; long CS; long RE; long CE; y>>RS>>CS>>RE>>CE; // считаем числа за раз. Если ошиблись - запишет 0. // итого - по строчке минимум пройдемся два раза - для замены, для считывания. Код НЕ ПРОВЕРЯЛ. Плюсы плюсатого кода: Код короткий и самоочевидный (ну, разве кроме лямбды). Можно легко прикрутить блоки обработки ошибок try-catch и никаких segfault'ов При наличии хорошего компилятора - код может соптимизироваться в нечто не сильно хуже, чем изначально простой вариант С кода.

Комментариев нет:

Отправить комментарий