CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Symbol dziesiętny

Symbol dziesiętny

dział ogólny

Symbol dziesiętny

Nowy postprzez oneiro » niedziela, 17 czerwca 2012, 23:28

Witam,

Programuję w dość starym programie - C++ Builder v6 (z 2002 roku).

Problem jest taki, że mam ustawione w (win xp) - Panel Sterownia -> Opcje Regionalne i Językowe -> Przycisk "Dostosuj" -> Symbol Dziesiętny na znak "." czyli kropkę.
Program napisane przez mnie działa u mnie dobrze, ale jak tylko przeniosę go na komputer, w którym symbol dziesiętny jest "," czyli przecinek, to już nie (error w stylu: "." kropka, nie jest częścią liczy, bo symbol dziesiętny jest "," przecinek)

Czy dałby się jakoś zrobić, aby nie zależnie od symbolu dziesiętnego w systemie Windows (xp/vista/7) mój program działał dobrze u mnie i innych osób?

Pozdrawiam, Krzysiek
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » poniedziałek, 18 czerwca 2012, 05:01

Odpowiedziałem już na podobny problem w tym wątku: http://www.programowanie.cal.pl/forum/viewtopic.php?f=2&t=1408&p=10305&hilit=#p10305. Możesz w ten sposób wymusić używanie przez program wybranego separatora niezależnie od ustawień systemowych. Gdybyś podał konkretny przykład, to ja podałbym konkretną odpowiedź, ale sam też na podstawie podanego wyżej postu powinieneś sobie poradzić z funkcją Format.

Gdybyś chciał sprawdzić jakiego separatora używa system, to można to zrobić tak:

KOD cpp:     UKRYJ  
 char Info[255];
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, Info, sizeof(Info));
 Label1->Caption = (String)Info;
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez polymorphism » poniedziałek, 18 czerwca 2012, 12:12

... lub w C++ way:
KOD cpp:     UKRYJ  
#include <locale>
...

char point = use_facet<numpunct<char> >(locale("")).decimal_point();


hmm... VCL way(?):
KOD cpp:     UKRYJ  
System::WideChar point = TFormatSettings::Create().DecimalSeparator;
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » poniedziałek, 18 czerwca 2012, 19:56

Chyba rozumiem o co Tobie chodzi. Chcesz, żeby program konwertował tekst pobrany np. z Edit na liczbę bez błędów niezależnie od tego jakiego separatora dziesiętnego użyje użytkownik, czyli np. użytkownik użyje kropki a w systemie zdefiniowany jest przecinek. Najlepszym rozwiązaniem w tej sytuacji byłoby poinformowanie użytkownika, żeby użył właściwego separatora, np tak:

KOD cpp:     UKRYJ  
 TFormatSettings fs;
 GetLocaleFormatSettings(0, fs);

 if( !Edit1->Text.LastDelimiter( fs.DecimalSeparator ) )
 {
   ShowMessage("Użyto niewłaściwego separatora dziesiętnego. Użyj jako separatora znaku: ' " + fs.DecimalSeparator + " '!");
  return;
 }
Co jednak, jeżeli dane zostały zapisane z separatorem np. kropki na jednym komputerze i są otwierane na innym komputerze, na którym separatorem jest przecinek?! W takiej sytuacji użytkownika czeka masa błędów.
Wymyśliłem więc coś takiego:

KOD cpp:     UKRYJ  
 float liczba;

 TFormatSettings fs;
 GetLocaleFormatSettings(0, fs);

 String sep[] = {".", ","};

 for(int x = 0; x < ARRAYSIZE(sep); x++)
 {
  if( Edit1->Text.LastDelimiter( sep[x] ) && sep[x] != fs.DecimalSeparator )
  {
   Edit1->Text = StringReplace(Edit1->Text, sep[x], fs.DecimalSeparator, TReplaceFlags() << rfReplaceAll);
   break;
  }
 }

 liczba = Edit1->Text.ToDouble();


Chętnie poznam lepsze rozwiązanie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez oneiro » poniedziałek, 18 czerwca 2012, 22:38

Dzięki za odpowiedź, będę walczył, ale jeszcze jedno pytanie.

Mam 4 formy i związku z tym 4 pliki cpp (unt1 -unit4), pól tekstowych całą masa z wartościami liczbowymi (konwertowanymi na double), jak najlepiej (tj najmniejszym nakładem sił) przerobić cały program?
Ostatecznie przerobię całość ręcznie.

Rozwiązanie ostanie,od Barona wydaje się najlepsze (gdyż program będzie uruchamiany na systemach z różnym separatorem, osobiście korzystam z kropki, ale większość z przecinka).


A co takim czymś?
Kod: Zaznacz cały
double a=12345.6789


Uruchamia to osoba, u którego separator będzie przecinkiem - też się wywali?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez polymorphism » poniedziałek, 18 czerwca 2012, 22:52

Nie, ponieważ w C/C++ separatorem dziesiętnym jest kropka, niezależnie od ustawień regionalnych.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » wtorek, 19 czerwca 2012, 04:57

polymorphism napisał(a):Nie, ponieważ w C/C++ separatorem dziesiętnym jest kropka, niezależnie od ustawień regionalnych.


To dotyczy tylko sytuacji w której wprowadzana jest liczba zmiennopozycyjna jeszcze w kodzie.

oneiro napisał(a):am 4 formy i związku z tym 4 pliki cpp (unt1 -unit4), pól tekstowych całą masa z wartościami liczbowymi (konwertowanymi na double), jak najlepiej (tj najmniejszym nakładem sił) przerobić cały program?


Przepisać od nowa. Nie ma żadnych pomocnych skrótów. Skoro tych pól jest tak dużo, to czy nie lepszym rozwiązaniem byłoby użyć tabeli np. TStringGrid zamiast pół TEdit?!
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez polymorphism » wtorek, 19 czerwca 2012, 11:00

To dotyczy tylko sytuacji w której wprowadzana jest liczba zmiennopozycyjna jeszcze w kodzie.

No tak, przecież o to pytał.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » wtorek, 19 czerwca 2012, 16:05

Ja tylko tak... dla jasności... 8-)
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez oneiro » wtorek, 19 czerwca 2012, 22:35

Czy nie lepiej TStringGrid - powiem tak, program ciągle ewoluuje, koncepcja pierwotna zmieniła się o 180 deg i ciągle się zmienia. Ogóle program jest prosty, liczy całki, podstawia do wzorów, rysuje przekroje belek i wrzuca dane do programu typu MES/FSM, tam następuje dalsza obróbka danych i z powrotem do programu pierwotnego. Taka prosta optymalizacja.

Jakby nie było dzięki za pomoc, pozdrawiam, Krzysiek

EDIT:
pupa, dodałem SysUtils.hpp, ale wywala "undefined symbol TFormatSettings" trochę poszukałem i znałem na Waszym forum GetLocaleInfo, muszę poczytać co i jak z tym się je, gdyż mam BC v6....

EDIT2 - GetLocaleInfo daty się tyczy - może jakiś inne rozwiązanie znacie....
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » środa, 20 czerwca 2012, 04:54

Rozwiązanie bez TFormatSetting podał ci polymorphism:

KOD cpp:     UKRYJ  
#include <locale>

char point = use_facet<numpunct<char> >(locale("")).decimal_point();


różnica jest taka, że separator dziesiętny jest zwracany do zmiennej typu char.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez polymorphism » środa, 20 czerwca 2012, 10:25

pupa, dodałem SysUtils.hpp, ale wywala "undefined symbol TFormatSettings"

Może trzeba jawnie określić przestrzeń nazw (C++ Builder pod tym względem był niekonsekwentny):
KOD cpp:     UKRYJ  
System::WideChar point = SysUtils::TFormatSettings::Create().DecimalSeparator;

zresztą to samo z biblioteką standardową:
KOD cpp:     UKRYJ  
char point = std::use_facet<std::numpunct<char> >(std::locale("")).decimal_point();


(...) różnica jest taka, że separator dziesiętny jest zwracany do zmiennej typu char.

Może być wchar_t:
KOD cpp:     UKRYJ  
wchar_t point = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).decimal_point();

Generalnie w obu przypadkach kod znaku będzie taki sam, ponieważ kropka i przecinek wchodzą w skład podstawowego zestawu znaków ASCII (<128), którego kody są takie same w unikodzie.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez oneiro » środa, 20 czerwca 2012, 20:33

Rzeczywiście, przeoczyłem to rozwiązanie.

Ale ciągle jest coś nie tak.

Chciałem, aby zmienna piont tylu char była globalna, dlatego też w formie1.cpp dałem kod od polymorphusa zaraz za nagłówkami, a przed pierowszą funkcją, a w pliku unit1.h dałem w publicznej strefie TForm1 "char piont".

Skompilowało się ładnie, ale podczas uruchomienia mam błąd (wykasuje debug assmeblera):

---------------------------
Information
---------------------------
Project G:\Art_2\Program_Art3\Project2.exe faulted with message: 'access violation at 0x004bbe42: read of address 0x00000004'. Process Stopped. Use Step or Run to continue.
---------------------------
OK
---------------------------



Jeśli kod dam wewnątrz funkcji, działa ładnie. Chcę mieć jedną globalną zmienną, a nie trzydzieści lokalnych.
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez Cyfrowy Baron » środa, 20 czerwca 2012, 20:56

oneiro napisał(a):dałem kod od polymorphusa zaraz za nagłówkami, a przed pierowszą funkcją


Źle! Pobierz wartość do zmiennej w jakimś zdarzeniu, a nie poza nim.

oneiro napisał(a):w pliku unit1.h dałem w publicznej strefie TForm1 "char piont".


Może być w public jeżeli ma być dostępne na innych formach, a jeżeli ma być dostępne tylko na tej formie to wystarczy w private.

Sposób podany przez polymorphism zadziała również ze zmienną typu AnsiString, użyj więc tego typu to potem będzie ci łatwiej nią operować:

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:
        AnsiString point;


Jeżeli separator chcesz pobrać zaraz po uruchomieniu programu to zrób to w konstruktorze klasy formularza lub w zdarzeniu OnCreate dla tego formularza:

Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
#include "Unit1.h"
#include <locale>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 point = (AnsiString)std::use_facet<std::numpunct<char> >(std::locale("")).decimal_point();
}




Zamiast tego co podał polymorphism możesz użyć funkcji GetLocalInfo z flagą LOCALE_SDECIMAL.

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:        // User declarations
        char cDecimal[2];


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
#include "Unit1.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, cDecimal, sizeof(cDecimal));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
 float liczba;

 String sep[] = {".", ","};

 String decimal = (AnsiString)cDecimal;

 for(int x = 0; x < ARRAYSIZE(sep); x++)
 {
  if( Edit1->Text.LastDelimiter( sep[x] ) && sep[x] != decimal )
  {
   Edit1->Text = StringReplace(Edit1->Text, sep[x], decimal, TReplaceFlags() << rfReplaceAll);
   break;
  }
 }

 liczba = Edit1->Text.ToDouble();
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Symbol dziesiętny

Nowy postprzez oneiro » środa, 20 czerwca 2012, 21:12

Cyfrowy Baron napisał(a):
oneiro napisał(a):dałem kod od polymorphusa zaraz za nagłówkami, a przed pierowszą funkcją


Źle! Pobierz wartość do zmiennej w jakimś zdarzeniu, a nie poza nim.



Dlaczego, mam całą masę zminny tak ustawionych (tj w tym miejscu) np.:

int liczba = 10;
char znak='-';

Co do zmiennej to musi być widoczna w innych formularzach, dlatego jest w public.

DZIAŁA :D wielkie dzięki, skorzystałem z rozwiązania z dodaniem do akcji tworzenia formularza.

Pozdrawiam, Krzysiek
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 46 gości