forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   Велик для форматирования строк (http://forum.boolean.name/showthread.php?t=19692)

mr.DIMAS 13.02.2015 21:53

Велик для форматирования строк
 
Это
Код:

char buffer[512];
sprintf( "%d %f %s", 12, 12.4, "ololo" );

Сильно подвержено ошибкам типа пропуска параметра, или передачи параметра не того типа что ожидается. У меня был трудно уловимый баг когда я вместо string.c_str() передавал просто string, сеанс отладки был просто "чудесен".

Решение:
Код:

class StringBuilder {
protected:
    std::stringstream mStream;
public:
    explicit StringBuilder( const char * str ) {
        stringstream::sync_with_stdio(false);
        mStream << str;
    }
    explicit StringBuilder(  ) {
        stringstream::sync_with_stdio(false);
    }
    template<class T>
    StringBuilder & operator<< (const T& arg) {
        mStream << arg;
        return *this;
    }
    operator string() const {
        return mStream.str();
    }
    const char * ToCStr() {
        return mStream.str().c_str();
    }
};

Позволяет форматировать строки так:
Код:

StringBuilder( "DIPs: " ) << ruDIPs() << "\nTCs: " << ruTextureUsedPerFrame() << "\nFPS: " << fpsCounter.fps;
Можете закидать меня какашками, и говорить что << это быдлокод и прочее "ко-ко-ко" и вообще очень медленно. Так вот профайлер говорит обратное, юзабельность тоже.

Samodelkin 13.02.2015 22:53

Ответ: Велик для форматирования строк
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293229)
Это
Код:

char buffer[512];
sprintf( "%d %f %s", 12, 12.4, "ololo" );

Сильно подвержено ошибкам типа пропуска параметра, или передачи параметра не того типа что ожидается. У меня был трудно уловимый баг когда я вместо string.c_str() передавал просто string, сеанс отладки был просто "чудесен".

Решение:
Код:

class StringBuilder {
protected:
    std::stringstream mStream;
public:
    explicit StringBuilder( const char * str ) {
        stringstream::sync_with_stdio(false);
        mStream << str;
    }
    explicit StringBuilder(  ) {
        stringstream::sync_with_stdio(false);
    }
    template<class T>
    StringBuilder & operator<< (const T& arg) {
        mStream << arg;
        return *this;
    }
    operator string() const {
        return mStream.str();
    }
    const char * ToCStr() {
        return mStream.str().c_str();
    }
};

Позволяет форматировать строки так:
Код:

StringBuilder( "DIPs: " ) << ruDIPs() << "\nTCs: " << ruTextureUsedPerFrame() << "\nFPS: " << fpsCounter.fps;
Можете закидать меня какашками, и говорить что << это быдлокод и прочее "ко-ко-ко" и вообще очень медленно. Так вот профайлер говорит обратное, юзабельность тоже.

На самом деле стандарт С++ описывает только поведение и формат функционала стандартной бибилиотеки, но реализация лежит на разработчике этой библиотеки. Таким образом в разных компиляторах или даже разных их версиях скорость может быть разной, однако можно однозначно сказать что обычно потоки С++ удобней библиотек С (в некоторых случаях наоборот).
Так что если в данном случае профайлер показывает больше скорости, это не значит что в других случаях будет также.
Ещё можно предположить что выделять сразу 512 байт видимо много, ещё лучше подобрать длину строк или использовать расшаренную память (как обычно делается внутри строк и потоков С++) то можно повысить скорость.
Сам я обычно использую std::stringstream и не оборачиваю его в какой-то класс.
Нужно иметь ввиду что ::sync_with_stdio статический и влияет на все потоки сразу -- его можно вызвать один раз, за пределами класса, как следствие и необходимость класса отпадает.
А вообще в выводе строк главное удобство, это же не рендер строк, а только их компоновка, я не думаю что оно требует таких умственных затрат (я имею ввиду что-то более сложное чем чистый stringstream).

mr.DIMAS 13.02.2015 22:57

Ответ: Велик для форматирования строк
 
Подобный велик помогает убрать такое говно:
Код:

stringstream data;
data<< "foo" << 123 << "bar" ;
doSomething( data.str() );

Заместо него будет
Код:

doSomething( StringBuilder( "foo" ) << 123 << "bar" );
Так что класс нужен.

Samodelkin 13.02.2015 23:14

Ответ: Велик для форматирования строк
 
Можно создать макрос, или создать статический метод вместо класса -- тогда не будет оверхеда на создание/удаление класса.
Можно создать логгер, который существует всё время, а внутри него stringstream, тоже существующий всё время. А добавлять данные так:
logger.getStream() << "ololo" << value1 << someClass;
doSomething( logger.getString() );

MiXaeL 14.02.2015 19:08

Ответ: Велик для форматирования строк
 
Цитата:

Сообщение от mr.DIMAS (Сообщение 293234)
Подобный велик помогает убрать такое говно:
Код:

stringstream data;
data<< "foo" << 123 << "bar" ;
doSomething( data.str() );

Заместо него будет
Код:

doSomething( StringBuilder( "foo" ) << 123 << "bar" );
Так что класс нужен.

Немного не понял. А что мешает делать:
Код:

doSomething( stringstream("foo")  << 123 << "bar" );
Ну т.е. не менее уродливо, но без лишнего класса.
Против класса ничего не имею, просто аргумент не очень.

mr.DIMAS 14.02.2015 22:26

Ответ: Велик для форматирования строк
 
Ну как минимум то что нужно делать вот так если в doSomething передается строка:
Код:

doSomething( (stringstream("foo")  << 123 << "bar").str() );


Часовой пояс GMT +4, время: 07:09.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot