Re[4]: Preobrozovanie char
От: Шахтер Интернет  
Дата: 19.03.04 01:41
Оценка: 59 (9) +3 :))) :))) :))
Здравствуйте, alexkro, Вы писали:

A>Здравствуйте, Кодт, Вы писали:


К>>Здравствуйте, Alxndr, Вы писали:


A>>>Смотри в сторону boost::lexical_cast


К>>Будьте проще, и люди потянутся.

К>>
К>>char buf[32]; // вроде должно хватить
К>>sprintf(buf, "%g", 1.23); // %g - выбирать наиболее подходящую запись: 0.123e+0001 или 1.23
К>>


A>Что может быть проще:

A>
A>string str = boost::lexical_cast<string>( 1.23 );
A>

A>А если с буферами тягаться, то недолго и гемор ввиде security holes получить.

Да уж куда проще -- ездить из Москвы в Питер через Вашингтон.

Пересадка первая. lexical_cast -> detail::lexical_stream

    template<typename Target, typename Source>
    Target lexical_cast(Source arg)
    {
        detail::lexical_stream<Target, Source> interpreter;
        Target result;

        if(!(interpreter << arg && interpreter >> result))
            throw_exception(bad_lexical_cast(typeid(Target), typeid(Source)));
        return result;
    }


Пересадка вторая. detail::lexical_stream -> std::stringstream

            bool operator<<(const Source &input)
            {
                return !(stream << input).fail();
            }
            template<typename InputStreamable>
            bool operator>>(InputStreamable &output)
            {
                return !is_pointer<InputStreamable>::value &&
                       stream >> output &&
                       (stream >> std::ws).eof();
            }
            bool operator>>(std::string &output)
            {
                #if defined(BOOST_NO_STRINGSTREAM)
                stream << '\0';
                #endif
                output = stream.str();
                return true;
            }
            #ifndef DISABLE_WIDE_CHAR_SUPPORT
            bool operator>>(std::wstring &output)
            {
                output = stream.str();
                return true;
            }
            #endif
        private:
            typedef typename widest_char<
                typename stream_char<Target>::type,
                typename stream_char<Source>::type>::type char_type;

            #if defined(BOOST_NO_STRINGSTREAM)
            std::strstream stream;
            #elif defined(BOOST_NO_STD_LOCALE)
            std::stringstream stream;
            #else
            std::basic_stringstream<char_type> stream;
            #endif


Пересадка третья. std::ostream -> std::num_put

        typedef num_put<_Elem, _Iter> _Nput;
                
        _Myt& operator<<(double _Val)
                {       // insert a double
                ios_base::iostate _State = ios_base::goodbit;
                const sentry _Ok(*this);

                if (_Ok)
                        {       // state okay, use facet to insert
                        const _Nput& _Nput_fac = _USE(ios_base::getloc(), _Nput);

                        _TRY_IO_BEGIN
                        if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                                _Myios::fill(), _Val).failed())
                                _State |= ios_base::badbit;
                        _CATCH_IO_END
                        }

                _Myios::setstate(_State);
                return (*this);
                }


Пересадка четвертая. std::num_put -> sprintf

        _OutIt put(_OutIt _Dest,
                ios_base& _Iosbase, _Elem _Fill, double _Val) const
                {       // put formatted double to _Dest
                return (do_put(_Dest, _Iosbase, _Fill, _Val));
                }
                                
        _VIRTUAL _OutIt do_put(_OutIt _Dest,
                ios_base& _Iosbase, _Elem _Fill, double _Val) const
                {       // put formatted double to _Dest
                char _Buf[_MAX_EXP_DIG + _MAX_SIG_DIG + 64], _Fmt[8];
                streamsize _Precision = _Iosbase.precision() <= 0
                        && !(_Iosbase.flags() & ios_base::fixed)
                                ? 6 : _Iosbase.precision();     // desired precision
                int _Significance = _MAX_SIG_DIG < _Precision
                        ? _MAX_SIG_DIG : (int)_Precision;       // actual sprintf precision
                _Precision -= _Significance;
                size_t _Beforepoint = 0;        // zeros to add before decimal point
                size_t _Afterpoint = 0; // zeros to add after decimal point

                if ((_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed)
                        {       // scale silly fixed-point value
                        bool _Signed = _Val < 0;
                        if (_Signed)
                                _Val = -_Val;

                        for (; 1e35 <= _Val && _Beforepoint < 5000; _Beforepoint += 10)
                                _Val /= 1e10;   // drop 10 zeros before decimal point

                        if (0 < _Val)
                                for (; 10 <= _Precision && _Val <= 1e-35
                                        && _Afterpoint < 5000; _Afterpoint += 10)
                                        {       // drop 10 zeros after decimal point
                                        _Val *= 1e10;
                                        _Precision -= 10;
                                        }

                        if (_Signed)
                                _Val = -_Val;
                        }

                return (_Fput(_Dest, _Iosbase, _Fill, _Buf,
                        _Beforepoint, _Afterpoint, _Precision,
                                ::sprintf(_Buf, _Ffmt(_Fmt, 0, _Iosbase.flags()),
                                        _Significance, _Val))); // convert and put
                }


Обратите внимание, как изящно, на лету формируется строка формата для передачи в sprintf.
Маршрут ещё не закончен. В его конце вы наёдёте _fcvt, _gcvt или что-то подобное. А в самых потрохах -- кусок на ассемблере, который и делает реальную работу.

И последнее:

Не надо путать программирование и идиотию. Авторы boost а, во всяком случае этой его части, программистами названы быть не могут. Ими вообще должны заниматься специальные люди в былых халатах.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.