Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1

Обертка над boost::lexical_cast для работы с unsigned типами

31.01.2016, 15:29. Показов 4595. Ответов 23

Студворк — интернет-сервис помощи студентам
Пару дней назад выяснилось, что boost::lexical_cast
не удовлетворяет нескольким требованиям в моей программе.
boost::lexical_cast отказывается обрабатывать и выбрасывает исключение,
если имеются пробелы в начале или в конце входной строки.
Также для unsigned типов, отрицательные значения обрабатываются нормально, т.е., например,
boost::lexical_cast<unsigned int>("-1") даст вполне валидное значение.
Для моих целей эти два факта были неприемлемы.
Собственно, Ticket #5494 как раз об этом,
и там был представлен такой велосипед:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_unsigned.hpp>
 
template <bool is_unsigned>
struct unsigned_checker
{
    template<typename String_type>
    static inline void do_check(const String_type & str) { }
};
 
template <>
struct unsigned_checker<true>
{
    template<typename String_type>
    static inline void do_check(const String_type & str)
    {
        if( str[0] == '-' ) boost::throw_exception( boost::bad_lexical_cast() );
    }
};
 
template<typename Target, typename Source>
inline Target forced_lexical_cast(const Source &arg)
{
    unsigned_checker< boost::is_unsigned<Target>::value >::do_check(arg);
    return boost::lexical_cast<Target>( arg );
}
Но для моих целей он также не подходит, т.к. кидает исключение и для строки "-0",
а ведь "-0", как и "+0" - вполне валидные значения.
Поэтому был написан велосипед:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
namespace detail
{
    struct string_cast_impl
    {
        template<typename TargetType>
        static
        std::enable_if_t<std::is_unsigned<TargetType>::value, TargetType>
        cast(const std::string& source)
        {
            if (!source.empty() && source[0] == '-'){
                TargetType result = boost::lexical_cast<TargetType>(source) ;
                return (result!=0) ? throw boost::bad_lexical_cast(),TargetType(0) : result  ;
            }
            return boost::lexical_cast<TargetType>(source);
        }
 
 
 
        template<typename TargetType>
        static
        std::enable_if_t<!std::is_unsigned<TargetType>::value, TargetType>
        cast(const std::string& source)
        {
            return boost::lexical_cast<TargetType>(source) ;
        }
    };
}//end of detail
 
 
 
template<typename TargetType, typename StringType>
std::decay_t<TargetType> string_cast(StringType&& source)
{
    using DecayType = std::decay_t<TargetType> ;
    std::string str(std::forward<StringType>(source)) ;
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
}
Решил выложить, вдруг кому пригодится, или будут дополнения/исправления.

Использование:
C++
1
2
3
4
5
int main(int argc, char ** argv)
{
    std::cout << string_cast<int>("-100") << std::endl ;
    std::cout << string_cast<unsigned int>("-100") << std::endl ;
}

P.S. Спасибо пользователям Kastaneda и hoggy за правки и дополнения.

Добавлено через 31 минуту
Вариант под C++11:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
namespace detail
{
    struct string_cast_impl
    {
        template<typename TargetType>
        static
        typename std::enable_if<std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const std::string& source)
        {
            if (!source.empty() && source[0] == '-'){
                TargetType result = boost::lexical_cast<TargetType>(source) ;
                return (result!=0) ? throw boost::bad_lexical_cast(),TargetType(0) : result  ;
            }
            return boost::lexical_cast<TargetType>(source);
        }
 
 
 
        template<typename TargetType>
        static
        typename std::enable_if<!std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const std::string& source)
        {
            return boost::lexical_cast<TargetType>(source) ;
        }
    };
}//end of detail
 
 
 
template<typename TargetType, typename StringType>
typename std::decay<TargetType>::type string_cast(StringType&& source)
{
    using DecayType = typename std::decay<TargetType>::type ;
    std::string str(std::forward<StringType>(source)) ;
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
}
4
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.01.2016, 15:29
Ответы с готовыми решениями:

Обертка над boost::asio
Вот класс обертки: class NetworkManager{ std::string CIP,IP; unsigned short CPort,Port; static boost::asio::io_service io;...

Namespace boost не содержит члена lexical_cast
.... #include &quot;boost\lexical_cast.hpp&quot; int main() { ..... m.insert(std::pair&lt;int, std::string&gt;(i,...

Обертка над C библиотекой
Всем здравствуйте. Есть dll написанная на C и заголовочные файлы. Хочу написать обертку на C++/CLI, чтобы в дальнейшем использовать в C#....

23
31.01.2016, 16:32

Не по теме:

*утащил в свою коллекцию семплов*

0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
31.01.2016, 16:35  [ТС]
hoggy, стоит ли переделать еще под C++03?
Естественно, без перемещения.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 16:38
Цитата Сообщение от Croessmah Посмотреть сообщение
стоит ли переделать еще под C++03?
эм, 16 год на дворе.
по-мойму, 03 уже не актуально
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
31.01.2016, 16:41  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
по-мойму, 03 уже не актуально
Поэтому переделал только под 11-ый стандарт.
Тоже думаю, что уже не актуально.
Кому актуально - переделают, покажут )))
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 20:42
Цитата Сообщение от Croessmah Посмотреть сообщение
там std::string, или то, что умеет само кастится к std::string.
Хотя, переделать под std::wstring будет легко

http://rextester.com/RUFT62725
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// =========================================================================================================
// =========================================================================================================
 
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
 
namespace detail
{
    struct string_cast_impl
    {
        template<typename TargetType, typename Str> static
        typename std::enable_if<std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const Str& source)
        {
            if (!source.empty() && source[0] == '-'){
                TargetType result = boost::lexical_cast<TargetType>(source) ;
                return (result!=0) ? throw boost::bad_lexical_cast(),TargetType(0) : result  ;
            }
            return boost::lexical_cast<TargetType>(source);
        }
 
 
        template<typename TargetType, typename Str> static
        typename std::enable_if<!std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const Str& source)
        {
            return boost::lexical_cast<TargetType>(source) ;
        }
    };
}//end of detail
 
 
 
template<typename TargetType, typename StringType>
typename std::decay<TargetType>::type string_cast(StringType&& source)
{
    using CharT = 
        typename std::remove_const<
            typename std::remove_reference<decltype(source[0])>::type
        >::type;
    
    using DecayType = typename std::decay<TargetType>::type ;
    
    //std::string str(std::forward<StringType>(source)) ;
    
    std::basic_string<CharT> str(std::forward<StringType>(source)) ;
    
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
    
}
 
// =========================================================================================================
// =========================================================================================================
 
 
 
#include <iostream>
 
int main()
{
    std::cout << "Hello, world!\n";
    
    try{
        
        std::cout << string_cast<int>("-100") 
            << std::endl ;
        
        
        std::wcout << string_cast<unsigned>(L"100") 
            << std::endl ;
    
    
        //std::cout << string_cast<unsigned int>("-100") 
          //  << std::endl ;
        
        std::wcout << string_cast<unsigned int>(L"-100") 
            << std::endl ;
        
    }
    catch(const boost::bad_lexical_cast& e)
    {
        std::cout << e.what() << std::endl;
    }
}
1
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
31.01.2016, 21:07  [ТС]
hoggy, Я хотел сделать универсальный шаблон,
но решил оставить с кастом к std::string,
т.к. изначально оно для Glib::ustring делалось.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 21:12
Цитата Сообщение от Croessmah Посмотреть сообщение
Я хотел сделать универсальный шаблон,
но решил оставить с кастом к std::string,
т.к. изначально оно для Glib::ustring делалось.
так ведь оверинжениринга практически нет.
и функциональность не страдает)
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
01.02.2016, 03:33  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
и функциональность не страдает)
Ну вот универсальный код для Glib::ustring не прокатит

О, как!
Немного переделал Ваш и добавил свой.
detail не менял.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
namespace detail
{
    struct string_cast_impl
    {
        template<typename TargetType, typename Str> static
        typename std::enable_if<std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const Str& source)
        {
            if (!source.empty() && source[0] == '-'){
                TargetType result = boost::lexical_cast<TargetType>(source) ;
                return (result!=0) ? throw boost::bad_lexical_cast(),TargetType(0) : result  ;
            }
            return boost::lexical_cast<TargetType>(source);
        }
 
 
        template<typename TargetType, typename Str> static
        typename std::enable_if<!std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const Str& source)
        {
            return boost::lexical_cast<TargetType>(source) ;
        }
    };
}//end of detail
 
 
template<typename TargetType, typename StringType>
std::enable_if_t<
    !std::is_same<
        std::decay_t<StringType>,
        Glib::ustring
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using CharT =
        typename std::remove_const<
            typename std::remove_reference<decltype(source[0])>::type
        >::type;
 
    using DecayType = typename std::decay<TargetType>::type ;
 
    //std::string str(std::forward<StringType>(source)) ;
 
    std::basic_string<CharT> str(std::forward<StringType>(source)) ;
 
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
 
}
 
 
template<typename TargetType, typename StringType>
std::enable_if_t<
    std::is_same<
        std::decay_t<StringType>,
        Glib::ustring
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using DecayType = typename std::decay<TargetType>::type ;
    std::string str(std::forward<StringType>(source)) ;
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
}
Добавлено через 7 минут
Блин, ошибся немного. Забыл вырубить шаблон ustring

upd: поменял код
1
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
01.02.2016, 03:33  [ТС]
С учетом дополнений из темы Применение is_same для списка типов

Немного доработал код.
Добавил два макроса:
C++
1
2
3
4
5
6
//temporary macros
#define TYPE_LIST_CV(type) type, const type, volatile type, volatile const type
 
#define IGNORING_TYPES              \
    TYPE_LIST_CV(char*),            \
    TYPE_LIST_CV(std::vector<char>)
TYPE_LIST_CV - добавляет к типу квалификаторы
IGNORING_TYPES - список типов, которые должны игнорироваться основным шаблоном

Немного переработал основной шаблон string_cast, для учета указанных игнорируемых типов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename TargetType, typename StringType>
std::enable_if_t<
    !is_one_same<
        std::decay_t<StringType>,
        IGNORING_TYPES
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using CharT = std::decay_t<decltype(source[0])> ;
 
    using DecayType = typename std::decay<TargetType>::type ;
 
    std::basic_string<CharT> str(std::forward<StringType>(source)) ;
 
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
 
}
Теперь, чтобы добавить "особую" версию string_cast для какого-либо типа,
необходимо добавить тип в список игнорируемых
(если требуется игнорировать типы со всеми квалификаторами,
то можно использовать TYPE_LIST_CV), и также
добавить string_cast с этой "особой" реализацией,
добавив в is_one_same соответствующий тип.
Например, вот реализация:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/*
 * main.cpp
 *
 *  Created on: 29 янв. 2016 г.
 *      author: Croessmah
 */
 
#include <iostream>
#include <vector>
 
 
 
#include <type_traits>
 
 
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
 
 
// =========================================================================================================
// ================================================is_same_list=============================================
// =========================================================================================================
 
 
#include <type_traits>
 
namespace detail
{
 
    template<
        template<class T> class LogicTemplate,
        typename SameType
    >
 
    constexpr bool
    is_same_list_impl()
    {
        return !LogicTemplate<bool>()(true,false) ;
    }
 
 
    template<
    template<class T> class LogicTemplate,
        typename SameType,
        typename FirstType,
        typename ... Args
    >
    constexpr bool
    is_same_list_impl()
    {
        return
                LogicTemplate<bool>()(std::is_same<SameType, FirstType>::value,
                    is_same_list_impl<LogicTemplate, SameType, Args...>()
                ) ;
    }
 
 
 
}//end of detail
 
 
 
 
namespace compile_time
{
    template<class T>
    struct logical_and : public std::binary_function<T,T,bool>
    {
        constexpr bool operator()(const T& first, const T& second) { return first && second ; }
    };
 
 
    template<class T>
    struct logical_or : public std::binary_function<T,T,bool>
    {
        constexpr bool operator()(const T& first, const T& second) { return first || second ; }
    };
}//end of compile_time
 
 
 
 
template<typename SameType, typename ... Args>
struct is_all_same
{
    static constexpr bool value =
            detail::is_same_list_impl<
                compile_time::logical_and,
                SameType, Args...
            >() ;
};
 
 
template<typename SameType, typename ... Args>
struct is_one_same
{
    static constexpr bool value =
            detail::is_same_list_impl<
                compile_time::logical_or,
                SameType, Args...
            >() ;
};
 
 
 
 
 
// =========================================================================================================
// =========================================================================================================
// =========================================================================================================
 
 
// =========================================================================================================
// ================================================string_cast==============================================
// =========================================================================================================
 
 
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
 
 
namespace detail
{
    struct string_cast_impl
    {
        template<typename TargetType, typename StringType> static
        typename std::enable_if<std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const StringType& source)
        {
            if (!source.empty() && source[0] == '-'){
                TargetType result = boost::lexical_cast<TargetType>(source) ;
                return (result!=0) ? throw boost::bad_lexical_cast(),TargetType(0) : result  ;
            }
            return boost::lexical_cast<TargetType>(source);
        }
 
 
        template<typename TargetType, typename StringType> static
        typename std::enable_if<!std::is_unsigned<TargetType>::value, TargetType>::type
        cast(const StringType& source)
        {
            return boost::lexical_cast<TargetType>(source) ;
        }
    };
 
 
}//end of detail
 
 
 
 
//temporary macros
#define TYPE_LIST_CV(type) type, const type, volatile type, volatile const type
 
#define IGNORING_TYPES              \
    TYPE_LIST_CV(char*),            \
    TYPE_LIST_CV(std::vector<char>)
 
 
//Включаем шаблон для всех типов, кроме IGNORING_TYPES
template<typename TargetType, typename StringType>
std::enable_if_t<
    !is_one_same<
        std::decay_t<StringType>,
        IGNORING_TYPES
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using CharT = std::decay_t<decltype(source[0])> ;
 
    using DecayType = typename std::decay<TargetType>::type ;
 
    std::basic_string<CharT> str(std::forward<StringType>(source)) ;
 
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
 
}
 
 
 
 
//Включаем шаблон для типов TYPE_LIST_CV(char*)
template<typename TargetType, typename StringType>
std::enable_if_t<
    is_one_same<
        std::decay_t<StringType>,
        TYPE_LIST_CV(char*)
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using DecayType = typename std::decay<TargetType>::type ;
    std::string str(std::forward<StringType>(source)) ;
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
}
 
 
 
//Включаем шаблон для типов TYPE_LIST_CV(std::vector<char>)
template<typename TargetType, typename StringType>
std::enable_if_t<
    is_one_same<
        std::decay_t<StringType>,
        TYPE_LIST_CV(std::vector<char>)
    >::value,
    std::decay_t<TargetType>
>
string_cast(StringType&& source)
{
    using DecayType = typename std::decay<TargetType>::type ;
    std::string str(source.begin(), source.end()) ;
    boost::trim(str) ;
    return detail::string_cast_impl::cast<DecayType>(str) ;
}
 
 
 
 
#undef IGNORING_TYPES
#undef TYPE_LIST_CV
 
// =========================================================================================================
// =========================================================================================================
// =========================================================================================================
 
 
 
 
int main(int argc, char ** argv)
{
    std::string str1 ("10") ;
    const char * str2 = "-0" ;
    std::vector<char> vec {'+', '4','0'} ;
    std::cout << string_cast<int>(str1) << std::endl ;
    std::cout << string_cast<unsigned int>(str2) << std::endl ;
    std::cout << string_cast<int>(vec) << std::endl ;
}
http://rextester.com/TZQPR61455

причем, типов, включающих одну такую "специализацию" может быть несколько, например,
C++
1
2
3
4
5
6
7
8
std::enable_if_t<
    is_one_same<
        std::decay_t<StringType>,
        TYPE_LIST_CV(Glib::ustring),
        TYPE_LIST_CV(char*)
    >::value,
    std::decay_t<TargetType>
>
"включит" шаблон для типов TYPE_LIST_CV(Glib::ustring) и TYPE_LIST_CV(char*)
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.02.2016, 18:57

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
эм, 16 год на дворе.
по-мойму, 03 уже не актуально
Да, а С++ до сих пор нет нормальных функций для преобразования ходовых типов с учетом всех возможных вариантов, к примеру локали.



Добавлено через 7 минут
Что касается сути, то не проще ли использовать сначала регулярку потом каст, если регулярка прошла ?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.02.2016, 19:01
Цитата Сообщение от Croessmah Посмотреть сообщение
С учетом дополнений из темы Применение is_same для списка типов
я так и не понял, что вы пытаетесь построить?

Добавлено через 2 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Да, а С++ до сих пор нет нормальных функций для преобразования ходовых типов с учетом всех возможных вариантов, к примеру локали.

Не по теме:

хз, что значит:
"учетом всех возможных вариантов, к примеру локали"

0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.02.2016, 19:07
Цитата Сообщение от hoggy Посмотреть сообщение
хз, что значит:
"учетом всех возможных вариантов, к примеру локали"
Ну к примеру 1.5 и 1,6 ? как кастануть с учетом десятичного разделителя? Опять же часто бывает нужно работать с датой и временем.
0
01.02.2016, 20:51

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Ну к примеру 1.5 и 1,6 ? как кастануть с учетом десятичного разделителя? Опять же часто бывает нужно работать с датой и временем.
с датой проще.
можно указывать регулярки для кастов туда/сюда.

с циферками наверное что-то подобное должно быть.

просто это с локалью напрямую никак не связанно.
локали отвечают за национальные символы.
и это - глобальный головняк.
а не только плюсовый.

что до плюсов, то местные локали/фасеты/прочий калл - эпический фейл.
вылечить который можно лишь полным пересмотром
всей той части архитектуры стандартной библиотеки,
которая отвечает за работу со строками.
полагаться на плюсовую локаль нельзя категорически.



0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.02.2016, 21:16
Цитата Сообщение от hoggy Посмотреть сообщение
просто это с локалью напрямую никак не связанно.
локали отвечают за национальные символы.
и это - глобальный головняк.
а не только плюсовый.
Я делаю обычно это в С++Builder так
C++
1
2
3
    TFormatSettings FormatSettings;
    FormatSettings.DecimalSeparator= L',';
    StrToFloat("1,5",FormatSettings);
Кроме того есть еще ф-ция с возвратом значения без выброса исключения TryStrToFloat();
Т.е. сравнительно просто.

http://docwiki.embarcadero.com... atSettings
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.02.2016, 07:19
Цитата Сообщение от hoggy Посмотреть сообщение
можно указывать регулярки для кастов туда/сюда.
boost:: ptime умеет форматировать даты по строкам типа "%mm-%dd-%yyyy". У меня тип для даты используется совершенно левый, поэтому есть свой велосипед перегоняющий boost:: ptime в мой тип.
Есть такой мап, который по языку системы возвращает шаблон даты
C++
1
2
3
4
5
6
7
8
9
        static std::map<std::string, std::string> date_formats = {
            { "en", "%m/%d/%Y" },
            { "es", "%m/%d/%Y" }, // TODO: check it!
            { "pt", "%d/%m/%Y" },
            { "ru", "%d.%m.%Y" },
            { "ja", "%Y/%m/%d" },
            { "de", "%Y-%m-%d" },
            { "fil", "%B %d, %Y" }
        };
Имхо - проще и удобней, чем регулярки.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
02.02.2016, 08:48
Цитата Сообщение от Kastaneda Посмотреть сообщение
Имхо - проще и удобней, чем регулярки.
вообще то, записи вида:
Цитата Сообщение от Kastaneda Посмотреть сообщение
"%m/%d/%Y"
это и есть регулярки.

Защита файла-сборки lib
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.02.2016, 08:52
hoggy, условно говоря да, но это не тот regex, к которому мы все привыкли.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.02.2016, 11:05
Цитата Сообщение от Kastaneda Посмотреть сообщение
Есть такой мап, который по языку системы возвращает шаблон даты
А как язык и формат данных даты связаны?
Никак... фэйл...
Точно так же как формат даты и десятичный разделитель.

Просто иногда нужно отображать в том формате в каком система, а обрабатывать в другом например если данные берутся с сайта.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.02.2016, 11:11
Цитата Сообщение от Avazart Посмотреть сообщение
Никак... фэйл..
??? От языка пользователя зависит формат даты, времени, плавающая точка и т.д.

Добавлено через 3 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Просто иногда нужно отображать в том формате в каком система, а обрабатывать в другом например если данные берутся с сайта.
У меня веб-приложение, юзеру нужно показать дату в его формате, бразуер в HTTP запросе посылает язык пользователя, по языку определяется в каком виде ему показывать дату. Если всем показывать в одном формате, то русский и американец поймет эту запись 3/2/2016 совершенно по-разному.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.02.2016, 11:11
Помогаю со студенческими работами здесь

Обертка над Си библиотекой
Добрый день, имеется библиотека написанная на Си (API для работы с оборудованием), хочу обернуть ее в код C#. Вот код написанный на...

Обертка над INotifyPropertyChanged
Я пытаюсь написать (если это возможно) обертку над INotifyPropertyChanged. Просто во первых при его реализации в классах приходится писать...

Обёртка над WinAPI
В архиве обычная обёртка над формой на WinApi, (ничего лишнего только класс формы); Чтобы создать форму в main.cpp объявлен класс MyWnd...

Обёртка над WinApi платно
Среда - Code::Blocks_16.01 Я написал обёртку над окном WinApi которая реализует событейную модель. Обёртка работает, написал даже...

Обертка над массивом double[]
Здравствуйте, подскажите пожалуйста с решением задания. Само задание: Нужно организовать различные виды доступа к одним и тем же...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru