Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
1

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

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

Author24 — интернет-сервис помощи студентам
Пару дней назад выяснилось, что 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.01.2016, 15:29
Ответы с готовыми решениями:

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

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

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

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

23
hoggy
31.01.2016, 16:32
  #2

Не по теме:

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

0
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
31.01.2016, 16:35  [ТС] 3
hoggy, стоит ли переделать еще под C++03?
Естественно, без перемещения.
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 16:38 4
Цитата Сообщение от Croessmah Посмотреть сообщение
стоит ли переделать еще под C++03?
эм, 16 год на дворе.
по-мойму, 03 уже не актуально
0
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
31.01.2016, 16:41  [ТС] 5
Цитата Сообщение от hoggy Посмотреть сообщение
по-мойму, 03 уже не актуально
Поэтому переделал только под 11-ый стандарт.
Тоже думаю, что уже не актуально.
Кому актуально - переделают, покажут )))
1
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 20:42 6
Цитата Сообщение от 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
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
31.01.2016, 21:07  [ТС] 7
hoggy, Я хотел сделать универсальный шаблон,
но решил оставить с кастом к std::string,
т.к. изначально оно для Glib::ustring делалось.
0
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.01.2016, 21:12 8
Цитата Сообщение от Croessmah Посмотреть сообщение
Я хотел сделать универсальный шаблон,
но решил оставить с кастом к std::string,
т.к. изначально оно для Glib::ustring делалось.
так ведь оверинжениринга практически нет.
и функциональность не страдает)
0
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
01.02.2016, 03:33  [ТС] 9
Цитата Сообщение от 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
Неэпический
18105 / 10692 / 2062
Регистрация: 27.09.2012
Сообщений: 26,918
Записей в блоге: 1
01.02.2016, 03:33  [ТС] 10
С учетом дополнений из темы Применение 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
Эксперт С++
8482 / 6149 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.02.2016, 18:57 11

Не по теме:

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



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

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

Не по теме:

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

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

Не по теме:

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

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

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

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



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

http://docwiki.embarcadero.com... atSettings
0
5232 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
02.02.2016, 07:19 16
Цитата Сообщение от 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
Эксперт С++
8972 / 4318 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
02.02.2016, 08:48 17
Цитата Сообщение от Kastaneda Посмотреть сообщение
Имхо - проще и удобней, чем регулярки.
вообще то, записи вида:
Цитата Сообщение от Kastaneda Посмотреть сообщение
"%m/%d/%Y"
это и есть регулярки.

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

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

Добавлено через 3 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Просто иногда нужно отображать в том формате в каком система, а обрабатывать в другом например если данные берутся с сайта.
У меня веб-приложение, юзеру нужно показать дату в его формате, бразуер в HTTP запросе посылает язык пользователя, по языку определяется в каком виде ему показывать дату. Если всем показывать в одном формате, то русский и американец поймет эту запись 3/2/2016 совершенно по-разному.
0
02.02.2016, 11:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.02.2016, 11:11
Помогаю со студенческими работами здесь

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru