none
Разделитель целой и дробной части в приложениях C# RRS feed

  • Вопрос

  • Здравствуйте! Столкнулся с проблемой запуска разработанного приложения (.NET 4.0) на ПК с разными настройками.

    Опытным путем было выявлено, что ошибки работы программы связаны с выбором разделителя в настройках Windows.

    Наверняка это уже давно известная проблема, но в чем собственно дело?

    Как избежать этого при разработке приложения? Как унифицировать код, что бы программа работала корректно на различных ПК. Спасибо.

Ответы

  • почитайте здесь, может поможет

    http://msdn.microsoft.com/en-us/library/dd183783(v=VS.90).aspx

    и здесь, как раз о разделителе

    http://msdn.microsoft.com/ru-ru/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx


  • Полагаю, у вас нигде не задаётся культура приложения. Это нужно сделать либо глобально, либо в каждом методе, где возможны разные формы ввода/вывода (типа метода ToString) указывать требуемую культуру. Смотрите CultureInfo.

    Используйте анализатор кода в старших версиях Visual Studio или, если используете Express версию - бесплатный FxCop. Он выдаст вам все места, где возможны проблемы с культурой и форматами. Смотрите IFormatProvider.

    • Помечено в качестве ответа Abolmasov Dmitry 31 мая 2012 г. 8:28
  • Не надо руками выставлять культуру при запуске. Это поведение .NET по умолчанию. Если культура не выставляется - значит кто-то специально написал код для этого. Найдите его, и спросите зачем он это сделал :) Т.е. "не работать" может всего в нескольких случаях:

    1. В программе уже есть код, в котором вручную вписана культура, но не во всех местах. Поэтому разделители используются разные.

    2. Где-то в коде числа разбираются вручную (или разбираются из строки вручную, а строку конвертируются через ToString c системной культурой).

    Какого вида у вас "ошибки"? Исключения, ошибки рассчетов, неправильно разбираемый ввод от пользователей? Локализуйте конкретное место в отладчике, и чините его.

    • Помечено в качестве ответа Abolmasov Dmitry 31 мая 2012 г. 8:29
    Модератор

Все ответы

  • Можно переформулировав, а то пока не очень понятно.
    Модератор
  • Попробую: В настройках Windows есть пункт, где можно выбрать знак разделителя целой и дробной части числа (в W7: панель управления > язык и региональные стандарты > форматы > дополнительные параметры...). Так вот, в зависимости от того, разделителем является точка или запятая, изменяется поведения программы, которую я писал в VS2010 на C#. Если в Windows разделитель выбран - запятая, то все работает нормально. Если точка - программа работает с ошибками... 
  • модифицируйте программу, добавив точку также к разделителям (то есть в программе "или точка, или запятая")
  • модифицируйте программу, добавив точку также к разделителям (то есть в программе "или точка, или запятая")
    Я не очень опытный пользователь, не могли бы вы конкретно указать, где и как это сделать?
  • отправьте код на мой email


  • отправьте код на мой email

    tfyodor@yandex.ru

    К сожалению, не могу этого сделать, это немаленький программный комплекс, интеллектуальная собственность и т.д.
  • Может можно обойтись каким-нибудь простеньким примером?

    А по аналогии я сделаю все у себя...

  • почитайте здесь, может поможет

    http://msdn.microsoft.com/en-us/library/dd183783(v=VS.90).aspx

    и здесь, как раз о разделителе

    http://msdn.microsoft.com/ru-ru/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx


  • Полагаю, у вас нигде не задаётся культура приложения. Это нужно сделать либо глобально, либо в каждом методе, где возможны разные формы ввода/вывода (типа метода ToString) указывать требуемую культуру. Смотрите CultureInfo.

    Используйте анализатор кода в старших версиях Visual Studio или, если используете Express версию - бесплатный FxCop. Он выдаст вам все места, где возможны проблемы с культурой и форматами. Смотрите IFormatProvider.

    • Помечено в качестве ответа Abolmasov Dmitry 31 мая 2012 г. 8:28
  • Спасибо за советы, попробую все вышеперечисленное. Пока в качестве ответа помечать ничего не буду, подожду еще возможных решений...
  • Насколько я понял, вам вне зависимости от настроек ОС нужно использовать везде точку вместо запятой. Тогда при старте приложения в текущем потоке выставляйте культуру.

    myCulture = new CultureInfo("en-US") { /* Тут можно доопределить специфику культуры */ };

    Thread.CurrentThread.CurrentCulture = myCulture; Thread.CurrentThread.CurrentUICulture = myCulture;

    В случае, если у вас идет парсинг значений в отдельных потоках, в них тоже придется передавать текущую культуру.

    Отвечающий
  • Насколько я понял, вам вне зависимости от настроек ОС нужно использовать везде точку вместо запятой. Тогда при старте приложения в текущем потоке выставляйте культуру.

    myCulture = new CultureInfo("en-US") { /* Тут можно доопределить специфику культуры */ };

    Thread.CurrentThread.CurrentCulture = myCulture; Thread.CurrentThread.CurrentUICulture = myCulture;

    В случае, если у вас идет парсинг значений в отдельных потоках, в них тоже придется передавать текущую культуру.

    Не совсем, как раз в зависимости от настроек ОС, я и должен изменить видимо культуру. Как я понимаю, я должен определить программно, какой тип разделителя используется в Windows, и от этого изменять что-то в своей программе, что бы программа работала корректно. 
  • Нет, как раз если вы укажите в программе культуру самостоятельно, то настройки Windows будут игнорироваться. А по умолчанию культура из настроек Windows и берется и для разных локалей - будут разные разделители целой и дробной части, также могут быть разделители между тысячами и т.п.


    Для связи [mail]

  • Нет, как раз если вы укажите в программе культуру самостоятельно, то настройки Windows будут игнорироваться. А по умолчанию культура из настроек Windows и берется и для разных локалей - будут разные разделители целой и дробной части, также могут быть разделители между тысячами и т.п.


    Для связи [mail]

    Я имею на одном ПК RU W7, на этом ПК я поменял разделитель по умолчанию с , на .

    Программа этого изменения автоматом не увидела и работала некорректно.

    Я думаю, мне надо при запуске приложения считывать настройки Windows и в связи с этим, программно изменять культуру самого приложения...


  • Проблема, как найти эту самую настройку (разделитель по умолчанию) и что изменять в программе...
  • Дядя Фёдор вам уже приводил ссылку на NumberDecimalSeparator.
  • Не надо руками выставлять культуру при запуске. Это поведение .NET по умолчанию. Если культура не выставляется - значит кто-то специально написал код для этого. Найдите его, и спросите зачем он это сделал :) Т.е. "не работать" может всего в нескольких случаях:

    1. В программе уже есть код, в котором вручную вписана культура, но не во всех местах. Поэтому разделители используются разные.

    2. Где-то в коде числа разбираются вручную (или разбираются из строки вручную, а строку конвертируются через ToString c системной культурой).

    Какого вида у вас "ошибки"? Исключения, ошибки рассчетов, неправильно разбираемый ввод от пользователей? Локализуйте конкретное место в отладчике, и чините его.

    • Помечено в качестве ответа Abolmasov Dmitry 31 мая 2012 г. 8:29
    Модератор
  • Не надо руками выставлять культуру при запуске. Это поведение .NET по умолчанию. Если культура не выставляется - значит кто-то специально написал код для этого. Найдите его, и спросите зачем он это сделал :) Т.е. "не работать" может всего в нескольких случаях:

    1. В программе уже есть код, в котором вручную вписана культура, но не во всех местах. Поэтому разделители используются разные.

    2. Где-то в коде числа разбираются вручную (или разбираются из строки вручную, а строку конвертируются через ToString c системной культурой).

    Какого вида у вас "ошибки"? Исключения, ошибки рассчетов, неправильно разбираемый ввод от пользователей? Локализуйте конкретное место в отладчике, и чините его.

    Да, у меня много преобразований из строки в числа и обратно, так же используя ToString.

    Ошибки вида: не верное отображение числовых данных в datagridview, иногда просто пропадают столбцы из таблицы... 

  • Ой, а тут можно писать, да? Отвечать, да?! Крууууто.

    Нам в универе подсказали когда-то классный хак на эту тему. Уж не знаю, насколько гуру будут бить за такой костыль ногами... Мне он понравился - я вообще люблю костыли.)

    Смысл: перед любым чтением числа из строки мы заменяем все точки и запятые на DecimalSeparator. It works!!!

           string useCorrectSeparator(string str)
            {
                return str.Replace(",", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator).Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
            }

    А после этого любой перевод строки в число будет выглядеть так:

    double hz = Convert.ToDouble(useCorrectSeparator(textBox42.Text));

    З. Ы. Ась? Быстродействие? Не, не слышал. Я лабы сдаю.)

    З. З. Ы. культура = штамм

    • Изменено Alex'89 29 мая 2012 г. 18:57
  • Нам в универе подсказали когда-то классный хак на эту тему.

    Универ закрыть, преподавателей разогнать, студентов в армию.

    Уж не знаю, насколько гуру будут бить за такой костыль ногами... Мне он понравился - я вообще люблю костыли.)

    Ну да, я бы отпинал за такой код. Чтоб понадобились реальные костыли.

    Смысл: перед любым чтением числа из строки мы заменяем все точки и запятые на DecimalSeparator. It works!!!

           string useCorrectSeparator(string str)
            {
                return str.Replace(",", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator).Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
            }

    Советую всё-таки почитать про культуру, про глобализацию-локализацию приложений.

    Например, в некоторых странах группы символов разделяют каким-нибудь знаком (типа 123,456.78 - у нас в России это будет 123456,78). И во что превратит это число ваш код?

    З. Ы. Ась? Быстродействие? Не, не слышал. Я лабы сдаю.)

    Надеюсь, с таким мировоззрением вы не станете программистом.

    P.S. Хочется крови...

  • P.S. Хочется крови...

    Вах!) Всю ночь теперь будут кошмары сниться...)

    Универ закрывать не надо. Преподаватели тоже не виноваты - это было учебное приложение, и нужно было простое решение.

    Я исходил из того, что человек, может быть, только для российских пользователей пишет. Или только для своей фирмы, где стопроцентно нет систем на уругвайском языке. Какой тогда смысл заморачиваться?

    P. S. А в армию я и так иду через месяц. По поводу программирования - что же, я тоже надеюсь, что обойдется. Терпеть его ненавижу.)

  • >> Я исходил из того, что человек, может быть, только для российских пользователей пишет. Или только для своей фирмы, где стопроцентно нет систем на уругвайском языке. Какой тогда смысл заморачиваться?

    Раз человек уже встретил разные разделители дробной части - значит, он уже встретил пользователей уже минимум с двумя разными локалями.

    Смысл заморачиваться в том, что нормальный фикс займет ровно столько же времени, сколько костыль с Replace. 99% времени - найти места, куда фикс вставить. 

    Модератор