Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C++ Безопасный аналог функции sscanf (не С) 
:(
    Опции темы
Alexeis
Дата 11.1.2010, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



  Хочется сочетания простота + изящество + скорость + функциональность + безопасность.

Пример строки "param1=10, param2=2.0, param3=вася , ..."

Чтобы зря мозг не парить. Вопрос прогулил.
Что нашел.
1) stringstream - просто, быстро, безопасно, но не нифига не изящно и не функционально.
Если извлечь как строку первый кусок, то это будет "param1=10," т.е. совсем не то что нужно. Значит нужно подключать find , потом перемещать позицию, потом вычислять длину текста "param1=" для того чтобы добавить к найденной позиции. Просто ужасно. 
2) буст токинайзер. Ставлю разделитель знак "=", в результате получаю целую толпу токиенов. Среди них выделить нужные мне задача нетривиальная + не эффективность, поскольку создаются куча строковых переменных в куче из которых потом нужно получать значение. Само строковое представление токинов мне до лампочки. Итого  функциональность + безопасность, остального нет. 
3) буст regexp. встречал код разбивающий выражение на список токенов (list<>). 
  Скорость еще ниже, еще больше "мусора", но результат лучше + чем токинайзер, но опять же конвертация типов ручная.

Что имеем с sscanf - простота + изящество + скорость + функциональность.
4+, нет только безопасности.

Неужели до сих пор нет приличного решения? Стока всего накрутили с бустами и STL ми, и тем не менее ничего красивее С так и не сделали?

Кто что использует? Не хочется в новый проект закладывать небезопасный код.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
comcon1
Дата 11.1.2010, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 11.6.2005
Где: Москва ДАС-МГУ

Репутация: 12
Всего: 17



boost::regexp для разбора + boost::lexical_cast для конвертации

можно сделать хороший обработчик на базе boost::spirit с конвертацией и всеми делами, потому что сам спирит тяжел, но время компиляции - ###

я использую первое для разбора мелочей, второе - для разбора файлов.


--------------------
PM MAIL   Вверх
Alexeis
Дата 11.1.2010, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(comcon1 @  11.1.2010,  21:42 Найти цитируемый пост)
boost::spirit

Интересно, но мой моск не осилил
Код

//  Парсер разделённых запятой чисел
bool parse_numbers(const char* str, vector<double>& v)
{
   return parse(str,
       //  начало грамматики
       (
           real_p[push_back_a(v)] >> *(',' >> real_p[push_back_a(v)])
       )
       ,
       //  конец грамматики
       space_p).full;
}


Разыменовать одиночную круглую скобку с рядом стоящей строкой  Непростой синтаксис smile 

Это сообщение отредактировал(а) Alexeis - 11.1.2010, 23:18


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
djamshud
Дата 11.1.2010, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 8
Всего: 39



>"param1=10, param2=2.0, param3=вася , ..."

В данном примере написать распарсивалку в пять-десять строк - секундное дело. Будет дьявольски эффективно и безопасно. Когда мне лень писать пять строк, просто пользуюсь функцией для разбива строки на массив подстрок (аля пхпшный explode). Менее эффективно, безопасно, элементарно в использовании.


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
mes
Дата 11.1.2010, 23:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alexeis @  11.1.2010,  21:54 Найти цитируемый пост)
Разыменовать одиночную круглую скобку с рядом стоящей строкой  

вообще то скобка не одиночная, а парная
а * это не разъименователь, а перегруженный оператор.

Добавлено через 3 минуты и 19 секунд
Вы зря ленитесь спросить у гугля, зачастую это намного эффективней чем вопрос на форуме..
вот что дал гугл на первой же странице :
http://blog.alno.name/2008/09/parsers-in-c...h-boost-spirit/
http://www.boost.org/doc/libs/1_32_0/libs/...c_concepts.html

Добавлено через 6 минут и 21 секунду
 smile вопрос то задавал оказывается админ.. не похоже чтоб он не знал об эффективности гугла..  smile  


--------------------
PM MAIL WWW   Вверх
Alexeis
Дата 11.1.2010, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(djamshud @  11.1.2010,  21:58 Найти цитируемый пост)
В данном примере написать распарсивалку в пять-десять строк - секундное дело. Будет дьявольски эффективно и безопасно. 

  Но не изящно и не функционально. Когда стандартные вещи решаются стандартно это даже документировать не нужно. Ручной разбор негибок и не стоек к изменениям. Имеет плохую повторяемость в сходной ситуации.

Добавлено через 5 минут и 14 секунд
Цитата(mes @  11.1.2010,  22:20 Найти цитируемый пост)
вообще то скобка не одиночная, а парная
а * это не разъименователь, а перегруженный оператор.

  Уже понял. Выглядит просто пугающе smile .

Цитата(mes @  11.1.2010,  22:20 Найти цитируемый пост)
Вы зря ленитесь спросить у гугля, зачастую это намного эффективней чем вопрос на форуме..

  Обычно так и делаю, но удачного решения так и не нагуглил smile .


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
djamshud
Дата 11.1.2010, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 8
Всего: 39



Alexeis, не спорю. Но задача (на моей практике) редкая, да и комментарий
Код

/* NOTE
 * Следующие непонятные десять строк распарсивают строку
 * a=b[,[a=b]]. Во избежание недоразумений не трогайте ее
 * или сразу переписывайте полностью - быстрее выйдет.
 */


отлично это дело документирует).

Это сообщение отредактировал(а) djamshud - 11.1.2010, 23:37


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
Alexeis
Дата 11.1.2010, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



mes, ссылка http://blog.alno.name/2008/09/parsers-in-c...h-boost-spirit/ в мемориз

Функционал отличный. Думаю, что для разбора простого синтаксиса идеальный вариант. Остается проверить производительность.

Немного смущает коммент
Цитата

Нет, нет и еще раз нет.

Boost::spirit - это совершенно ужасная библиотека с точки зрения разработчика. Пользуйтесь нормальными генераторами парсеров а не этой жуткой вещью.

Решил заюзать boost::spirit в реальном проекте, парсится подмножество SQL. Компиляция жутко долгая, несколько минут!!! в режиме debug! Lexer прикрутить не смог - примеры из документации не работают! Пришлось правила для приминитвных типов писать. Процесс отладки УЖАСНЫЙ!!! Любая ошибка в грамматике = 5 страниц невообразимых ошибок с темпейтами. Error handler так и не заработал. В общем потратил несколько дней, уже давно бы все работало на AntLR. 


Нужно будет еще рассмотреть вариант с AntLR. А так весьма неплохо.



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Dov
Дата 12.1.2010, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

Репутация: 15
Всего: 88



Цитата(Alexeis @  11.1.2010,  21:28 Найти цитируемый пост)
Что имеем с sscanf - простота + изящество + скорость + функциональность.4+, нет только безопасности.

юзай sscanf_s.
Последняя s это и есть безопасность..   smile 



--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
Alexeis
Дата 12.1.2010, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



 smile 

Dov, обычно это _s защита от переполнения буфера, но никак не защита от того что я поменяю одну букву в формате и параметры более не будут соответствовать формату, что может привести к чему угодно. 
  Приведу пример. В sscanf вместо указателя передается не инициализированная стековая переменная (типичная ошибка), значение переменной осталось от вызова другой функции где на этом месте был указатель на объект в куче. В результате значение адреса валидно, но функция sscanf неявным образом портит содержимое чужого объекта, не вызывая при этом AV. Реально мы видим странное поведение программы.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bsa
Дата 12.1.2010, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



для парсинга (относительно) сложных конструкций использую boost::spirit. Да, компилируется долго, зато, когда набил руку, то парсер пишется быстро и в достаточно простых случаях - без серьезных ошибок. Читать ошибки, конечно, то еще удовольствие...  smile Может с приходом C++0x что-то изменится...
В твоем бы случае я бы использовал (да и использую) std::istringstream, std::transform, самописный класс Variant (хотя, возможно, boost::variant тебе подойдет) и функтор, который, собственно, разделяет левую и правую части от знака присваивания.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0572 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.