AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 27.04.2009, 16:55   #1  
valentino is offline
valentino
Участник
Аватар для valentino
 
33 / 11 (1) +
Регистрация: 14.02.2007
Разделитель тысячных
Привет всем!
Возникла проблема преобразования из текстового представления числа в само число, т.е. из "123 456.78" в 123456.78.
При использовании str2num(), any2real() получаем число 123 (ожидалось 123456.78).
Исследование показало следующее:
1. Попытка удалить пробелы из текстового представления числа (разделитель тысячных) ни к чему не приводит, т.к. там на самом деле стоит символ с кодом 160. Этот символ (пробел с кодом 160) берется из региональных настроек для Российского стандарта панели управления. Это стандартно для любого виндоуса.
2. Текстовое представлене числа изначально в Аксапте формируется с помощью функции strfmt("%1", число). При этом код символа разделителя тысячных = 32 (обычный пробел).
3. Текстовое представлене с помощью num2str() дает тот же результат (код символа разделителя тысячных = 32).

Таким образом вопрос сводится к следующему:
почему при преобразовании из числа в строку в качестве разделителя тысячных Аксапта вставляет пробел (код = 32), а не символ из панели управления (код = 160)?

Тестовый джоб:
X++:
static void Test_ConvertStr2num(Args _args)
{
    amount      a, b;
    int         asciiCode;
    str         s, separator, thousandsSeparator;
    boolean     result;
    ;
    thousandsSeparator = WinApi::getUserLocaleThousandSeparator_RU();
    asciiCode = char2num(thousandsSeparator, 1);    // 160
    result    = thousandsSeparator == " ";          // false
    a = 123456.78;
    s = num2str(a, 10, 2, -1, -1);                  // "123 456.78"
    separator = substr(s, 4, 1);                    // вытащить разделитель
    asciiCode = char2num(separator, 1);             // 32
    result = thousandsSeparator == separator;       // false
    result = separator == " ";                      // true
    s = strfmt("%1", a);                            // "123 456.78"
    b = any2real(s);                                // 123
    b = str2num(s);                                 // 123
    separator = substr(s, 4, 1);                    // вытащить разделитель
    asciiCode = char2num(separator, 1);             // 32
    s = strrem(s, thousandsSeparator);              // ничего не происходит
    b = str2num(s);                                 // 123
    b = any2real(s);                                // 123
    b = b;
}
Старый 27.04.2009, 17:25   #2  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
у вас какая версия аксапты?
в функции num2str в последним параметром можно указать символ разделитель для тысячных, например: num2str(num, 1,1,1,0); - последняя цифра ноль, говорит о том что разделителя вовсе не будет... может изначально присваивать так?
потом можно просто перевести число обратно из строки...
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 27.04.2009, 17:38   #3  
valentino is offline
valentino
Участник
Аватар для valentino
 
33 / 11 (1) +
Регистрация: 14.02.2007
Цитата:
Сообщение от lev Посмотреть сообщение
у вас какая версия аксапты?
в функции num2str в последним параметром можно указать символ разделитель для тысячных, например: num2str(num, 1,1,1,0); - последняя цифра ноль, говорит о том что разделителя вовсе не будет... может изначально присваивать так?
потом можно просто перевести число обратно из строки...
AX 4.0, 4.0.2501 (SP1, FP2)

Да, указать-то можно свой разделитель (при переводе из числа в строку), но я отталкиваюсь от того механизма который уже существует в Аксапте и его менять пока не очень хочется. Речь идет о семействе отчетов RLedgerSheet* которые отображают формочку с ListView, а в нем отображаются цифры преобразованные в строки.
Старый 27.04.2009, 17:52   #4  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
если я правильно понял то необходимо из строки, в которой тысячные отделяются пробелами, получить число...
могу предложить такой вариант, может он и не изящный, но отработал нормально:
X++:
static void testStrNum(Args _args)
{
    real    num = 123456.78;
    real    numRes;

    str     numResS;
    str     getNum; // промежуточное строковое значение

    int     i;
    str     sW;
    ;

    numResS = num2str(num, 1,1,1,3);
    for(i=1;i<= strLen(numResS);i++)
    {
        sW = subStr(numResS, i, 1);

        if (sW != " ")
            getNum += sW;
    }

    numRes = str2num(getNum);

    info(strFmt('%1', numRes));
}
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 27.04.2009, 18:19   #5  
valentino is offline
valentino
Участник
Аватар для valentino
 
33 / 11 (1) +
Регистрация: 14.02.2007
Да, этот частный вариант работает.
Но было бы неправильно прописать в коде что разделитель тысячных пробел, по хорошему его надо считать из панели управления. И тогда ваш вариант ( if (sW != thousandSeparator) ) не сработает, т.к. код символа разделителя из панели управления = 160, а в переменной numResS код символа разделителя = 32.
Старый 29.04.2009, 12:18   #6  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от lev Посмотреть сообщение
могу предложить такой вариант, может он и не изящный, но отработал нормально
Можно от цикла избавиться:
X++:
static void testStrNum(Args _args)
{
    real    num = 123456.78;
    real    numRes;

    str     numResS;
    str     getNum; // промежуточное строковое значение

    //int     i;
    str     sW;
    ;

    numResS = num2str(num, 1,1,1,3);
    /*
    for(i=1;i<= strLen(numResS);i++)
    {
        sW = subStr(numResS, i, 1);

        if (sW != " ")
            getNum += sW;
    }
    */
    getNum = strKeep(numResS, '0123456789.');

    numRes = str2num(getNum);

    info(strFmt('%1', numRes));
}
За это сообщение автора поблагодарили: valentino (1).
Старый 29.04.2009, 12:36   #7  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от Hyper Посмотреть сообщение
Можно от цикла избавиться:
X++:
static void testStrNum(Args _args)
{
...
    getNum = strKeep(numResS, '0123456789.');
...
}
отделять копейки может не только точка поэтому и написал цикл, малоли что там может быть, а вот то что пробел не нужен, это мы знаем точно.
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 29.04.2009, 12:52   #8  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Цитата:
Сообщение от lev Посмотреть сообщение
поэтому и написал цикл, малоли что там может быть, а вот то что пробел не нужен, это мы знаем точно.
Цикл все равно не нужен - есть strRem
Старый 29.04.2009, 12:59   #9  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от Hyper Посмотреть сообщение
Цикл все равно не нужен - есть strRem
strRem функция хорошая не спорю, но я исходил изначально от того, что нам не известно что в этой функции будет вторым параметром.
Если же нам известно, тогда strRem подмышку и вперед
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Старый 27.04.2009, 18:20   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Excel: не грузятся копейки
Старый 28.04.2009, 15:05   #11  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от valentino Посмотреть сообщение
Таким образом вопрос сводится к следующему:
почему при преобразовании из числа в строку в качестве разделителя тысячных Аксапта вставляет пробел (код = 32), а не символ из панели управления (код = 160)?
На таким образом поставленный вопрос может быть только один ответ: потому что!

Система работает так, как она запрограммирована. Раз система работает вот так, значит таким образом она и была запрограммирована.

Если вы хотите получить другой результат, то, попробуйте внятно сформулировать, какого результата вы ожидаете и почему (с какой целью). В зависимости от формулировки станет понятно, надо ли вообще что-либо делать, а если надо, то каким образом.

Например, меня вполне устраивает в качестве разделителя тысяч пробел. Менять его на символ из панели управления не вижу смысла. Почему это не устраивает вас? В чем проблема-то?
Старый 29.04.2009, 11:28   #12  
valentino is offline
valentino
Участник
Аватар для valentino
 
33 / 11 (1) +
Регистрация: 14.02.2007
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Например, меня вполне устраивает в качестве разделителя тысяч пробел. Менять его на символ из панели управления не вижу смысла. Почему это не устраивает вас? В чем проблема-то?
Может я недостаточно четко сформулировал вначале, суть сводится к следующему:
при стандартных региональных настройках в панели управления, преобразование из числа в строку а затем из строки в число работает некорректно:
X++:
s = num2str(123456.78, 10, 2, -1, -1);    // s ="123 456.78"  (с пробелом, код которого = 32)
num = str2num(s);    // num = 123, в то время как ожидалось 123456.78  !!!
а попытка удалить из текстового представления тысячный разделитель (это может быть не только пробел) ни к чему не приводит, т.к. в данный момент в региональных настройках символ тысячного разделителя - это пробел с кодом 160! (см. первый джоб в начале темы)
Старый 29.04.2009, 12:28   #13  
in.dc is offline
in.dc
Участник
 
29 / 53 (2) ++++
Регистрация: 09.04.2009
strrem vs strkeep
Цитата:
Сообщение от valentino
X++:
s = strrem(s, thousandsSeparator);              // ничего не происходит
Цитата:
Сообщение от valentino Посмотреть сообщение
X++:
s = num2str(123456.78, 10, 2, -1, -1);    // s ="123 456.78"  (с пробелом, код которого = 32)
num = str2num(s);    // num = 123, в то время как ожидалось 123456.78  !!!
а попытка удалить из текстового представления тысячный разделитель (это может быть не только пробел) ни к чему не приводит, т.к. в данный момент в региональных настройках символ тысячного разделителя - это пробел с кодом 160! (см. первый джоб в начале темы)
А если рассмотреть вопрос с удалением символа 'разделителя тысяч' с другой позиции: т.е. не пытаться удалить (strrem) конкретный символ, а оставить в строке (содержащией числа) только допустимые с точки зрения Ax числовые символы (strkeep)?

X++:
static void jobRemoveThousandsSeparator(Args _args)
{
    #define.Numerics( ',.+-0123456789e' )
    str     s = num2str( 123456.78, 10, 2, -1, -1 ) ;
    real    num = str2num( strkeep( s, #Numerics ) ) ;
    ;

    info( strfmt( "%1", num ) ) ;
}
UPD: Oops, немного опоздал.
Изображения
 
__________________
Dynamics AX 4.0 SP2

Последний раз редактировалось in.dc; 29.04.2009 в 12:34. Причина: вариант с strkeep чуть раньше упомянул Hyper
За это сообщение автора поблагодарили: valentino (1).
Старый 29.04.2009, 19:09   #14  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от valentino Посмотреть сообщение
Может я недостаточно четко сформулировал вначале, суть сводится к следующему:
при стандартных региональных настройках в панели управления, преобразование из числа в строку а затем из строки в число работает некорректно:
X++:
s = num2str(123456.78, 10, 2, -1, -1);    // s ="123 456.78"  (с пробелом, код которого = 32)
num = str2num(s);    // num = 123, в то время как ожидалось 123456.78  !!!
а попытка удалить из текстового представления тысячный разделитель (это может быть не только пробел) ни к чему не приводит, т.к. в данный момент в региональных настройках символ тысячного разделителя - это пробел с кодом 160! (см. первый джоб в начале темы)
Хорошо. А сама задача-то в чем заключается? С какой целью надо "ходить по кругу"?

Вы описали бессмысленную, с моей точки зрения, задачу. Преобразовать число в строку, а затем из полученной строки снова сделать число. Зачем? Почему нельзя было взять исходной число без этих преобразований?

Есть правила перевода числа в строку. Есть правила перевода строки в число. Эти правила вовсе не обязаны быть взаимно-однозначны. Могут, но не обязательно.

Попробуйте сформулировать, хотя бы для самого себя, какова конечная цель?

Вы хотите, чтобы алгоритмы преобразования число-строка и строка-число были взаимно-однозначны? По каким правилам? Почему правила должны быть именно такими?

Или вам надо преобразовать вполне конкретную символьную строку (сформированную по определенным правилам) в число?

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

Код:
// Конвертация символьной строки в число

// Данный метод не анализирует возможность того, что один из разделителей может являться частью другого
// Например, разделитель целой и дробной части - это две точки подряд, а разделитель троек цифр - одна точка
// Последствия использования подобных разделителей в данном методе могут быть парадоксальными (не ожидАемыми)


//    Примеры вызова
/*
    print global::rtg_str2num("123.45");                // 123.45
    print global::rtg_str2num("1 234 567.89");          // 1234567.89
    print global::rtg_str2num("1 234 567.89e-2");       // 12345.6789
    print global::rtg_str2num("1 234 567,89",",");      // 1234567.89
    print global::rtg_str2num("123,5","","",",");       // 123e5 = 12 300 000
    print global::rtg_str2num("123.4,1","","",",");     // 123.4e1 = 1234
    print global::rtg_str2num("123e4.1","e","",".");    // 123.4e1 = 1234
    print global::rtg_str2num("123e4","e","",".");      // 123.4
    pause;
    return;

*/

#define.point(".")
#define.separator(" ")
#define.base("e")

public static real rtg_str2num( str _string,                    // собственно строка, которую надо перевести "123 456.78"
                                str _point      = #point,       // разделитель целой и дробной части
                                str _separator  = #separator,   // разделитель троек цифр
                                str _base       = #base         // Основание. Разделитель мантиссы и порядка числа, если оно представлено в форме "123e-2"
                                )
{

    ;

    // Как правило, параметр не указывают, если хотят указать значение параметра, следующего за ним,
    // а значение пропущенного параметра предполагается считать значением по умолчанию
    if (! _point)
    {
        _point = #point;
    }
    if (! _separator)
    {
        _separator = #separator;
    }
    if (! _base)
    {
        _base = #base;
    }

    // Ситуация, когда разные разделители имеют одно и то же значение рассматривается как ошибка,
    // поскольку становится невозможно выделить нужные части строки
    if (_point == _separator)
    {
        throw error(strFmt("Разделитель целой и дробной части \"%1\" не может быть равен разделителю троек цифр \"%2\"",_point, _separator));
    }

    if (_point == _base)
    {
        throw error(strFmt("Разделитель целой и дробной части \"%1\" не может быть равен разделителю мантиссы и порядка числа \"%2\"",_point, _base));
    }

    if (_separator == _base)
    {
        throw error(strFmt("Разделитель троек цифр \"%1\" не может быть равен разделителю мантиссы и порядка числа \"%2\"",_separator, _base));
    }


    // Удаляю ведущие и концевые пробелы
    // Вообще все пробелы удалять нельзя, поскольку какой-либо символ разделитель может содержать или быть пробелом
    // Хотя, в принципе, эту операция можно вообще не делать, поскольку функции str2num() эти пробелы не мешают
    _string = global::strLRTrim(_string);

    // Удаляю символы разделители троек цифр
    if (_separator)
    {
        if (strLen(_separator) == 1)
        {
            _string = strRem(_string, _separator);
        }
        else
        {
            // Здесь strRem() использовать нельзя, поскольку необходимо удалить именно
            // определенную последовательность символов, а не отдельные символы
            _string = global::strReplace(_string, _separator, "");
        }
    }

    // Если необходимо сделать две последовательные замены одного набора символов на другой,
    // то необходимо убедтиться в том, что вторая замена не "затрет" результат первой
    // т.е. в результате первой замены не должны появиться символы, которые заменит вторая замена
    switch (true)
    {
    case ((_base != #base) && (_point != #point) && (_point == #base) && (_base == #point)) :
        // Здесь нужна промежуточная замена на символы, которые не равны ни _point, ни _base
        // Подойдет _separator, поскольку это значение уже было проверено на данное равенство
        // и последовательность символов _separator была удалена из строки
        _string = global::strReplace(_string, _base, _separator);
        _string = global::strReplace(_string, _point, #point);
        _string = global::strReplace(_string, _separator, #base);
        break;
    case ((_base != #base) && (_point != #point) && (_point == #base)) :
        _string = global::strReplace(_string, _point, #point);
        _string = global::strReplace(_string, _base,  #base);
        break;
    case ((_base != #base) && (_point != #point) && (_base == #point)) :
        _string = global::strReplace(_string, _base,  #base);
        _string = global::strReplace(_string, _point, #point);
        break;
    default :
        if (_point != #point)
        {
            _string = global::strReplace(_string, _point, #point);
        }
        if (_base != #base)
        {
            _string = global::strReplace(_string, _base,  #base);
        }
        break;
    }


    return str2num(_string);

}
PS: использовать теги X++ не получилось, поскольку они съедают строки-комментарии в начале кода
Старый 30.04.2009, 09:28   #15  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Попробую еще раз.

МОЕ ПОНИМАНИЕ ПРОБЛЕМЫ:
Цитата:
Сообщение от valentino Посмотреть сообщение
Возникла проблема преобразования из текстового представления числа в само число, т.е. из "123 456.78" в 123456.78.
...
Текстовое представлене числа изначально в Аксапте формируется с помощью функции strfmt("%1", число).
МОЕ РЕШЕНИЕ ПРОБЛЕМЫ:
Цитата:
Сообщение от Gustav Посмотреть сообщение
Функция strFmt возвращает в виде строки ... real-число - с двумя десятичными знаками ... можно оставить в строке только 10 цифровых символов и знак "минус". Далее полученную строку конвертнуть обратно в число ... "обманув" ... и разделитель тысяч, и десятичную точку (запятую):
... и окончательный вариант "обмана" выглядит так (без предыдущего, возможно кого-то пугающего, деления на 100):
X++:
static void Job173(Args _args)
{
    real a = 123456.78;
    str  strNumberAfterStrFmt = strFmt('%1', a);
    real b;
    boolean c;
    ;

    b = str2Num(
        strFmt ( '%1e-2',
        strKeep( strNumberAfterStrFmt, '-0123456789')));

    c = a == b;
    box::info(strFmt('%1\n\n%2\n\n%3',
        strFmt('Исходное число: %1', a),
        strFmt('Восстановленное число из строки: %1', b),
        strFmt('Исходное число равно числу из строки?: %1', c)));
}
P.S.
В процессе эксперимента обратил внимание на то, что региональные настройки Аксапта считывает при старте приложения и далее в текущей сессии их не меняет (!) даже при изменении региональных настроек в панели управления. Такое поведение Аксапты отличается, например, от поведения Excel, где при смене локали c Russian на English (United States) наглядно видно, как в ячейке тут же меняются разделители тысяч с пробелов на запятые.

Последний раз редактировалось Gustav; 30.04.2009 в 09:42.
За это сообщение автора поблагодарили: aidsua (1).
Старый 29.04.2009, 13:33   #16  
Hyper is offline
Hyper
Участник
Соотечественники
 
163 / 29 (1) +++
Регистрация: 09.10.2003
Ой да, отвлекся от первоначальной задачи.
Старый 29.04.2009, 13:39   #17  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Функция strFmt возвращает в виде строки: int-число - без десятичных знаков, real-число - с двумя десятичными знаками (и без всяких научных e-форматов). Если быть уверенным, что речь идет именно о real (а наверняка речь идёт о деньгах, а они всегда real), то можно оставить в строке только 10 цифровых символов и знак "минус". Далее полученную строку конвертнуть обратно в число и разделить на 100, "обманув" таким образом и разделитель тысяч, и десятичную точку (запятую):
X++:
static void Job173(Args _args)
{
    AmountMst   a = -10.000012345678987e+12;
    str         s = strKeep(strFmt('%1', a), '-0123456789');
    real        b = str2num(s) / 100; // ну или * 0.01
    ;
    box::info(strFmt('%1', b));
}
P.S.
Если исходное число целое, то его можно по ходу без напряжения превратить в real, сложив с 0. или умножив на 1. (точки важны!) или разделить на 1 (можно без точки):
X++:
int a = 1000000;

strFmt('%1', a + 0.) // или
strFmt('%1', a * 1.) // или
strFmt('%1', a / 1 ) // хоть по теории это и самый долгий вариант, 
                     // зато без точки :)

Последний раз редактировалось Gustav; 30.04.2009 в 12:53.
Старый 29.04.2009, 16:29   #18  
valentino is offline
valentino
Участник
Аватар для valentino
 
33 / 11 (1) +
Регистрация: 14.02.2007
Спасибо Hyper, in.dc, lev.
Вариант решения с strKeep() вполне приемлемый, с учетом замечания по десятичной точке от lev.
Старый 29.04.2009, 16:52   #19  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от valentino Посмотреть сообщение
с учетом замечания по десятичной точке от lev.
Цитата:
Сообщение от lev Посмотреть сообщение
отделять копейки может не только точка
Как насчет того, что разделителем тысяч может быть и запятая?
Старый 29.04.2009, 17:02   #20  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
Как насчет того, что разделителем тысяч может быть и запятая?
Этот пост к чему? я же написал что разделитель может быть НЕ только точка
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
Теги
разделитель тысячных, axapta

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Разделитель страницы в MS WORD FiGr DAX: Программирование 3 14.05.2007 15:24
Разделитель десятичных знаков в отчетах dirigente DAX: Функционал 0 20.11.2003 12:28

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 16:23.