CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - va_list z UnicodeString

va_list z UnicodeString

dział ogólny

va_list z UnicodeString

Nowy postprzez Mironas » sobota, 28 grudnia 2013, 18:32

Dwie takie same funkcje wykorzystujące va_list różniące się tylko sposobem kodowania tekstu (AnsiString/UnicodeString).
Pierwsza funkcja (AnsiString) działa poprawnie:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  AnsiString wynik = PolaczAnsi("Ala ma: %s %s", "kota", "psa");
  ShowMessage(wynik);
}
//---------------------------------------------------------------------------
AnsiString TForm1::PolaczAnsi(AnsiString format, ...)
{
  AnsiString s;
  va_list list;
  va_start(list, format);
  s.vprintf(format.c_str(), list);
  va_end(list);
  return s;
}
 


Druga (UnicodeString) w zwracanym tekście zamiast kota i psa zwraca krzaczki:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  UnicodeString wynik = PolaczUnicode("Ala ma: %s %s", "kota", "psa");
  ShowMessage(wynik);
}
//---------------------------------------------------------------------------
UnicodeString TForm1::PolaczUnicode(UnicodeString format, ...)
{
  UnicodeString s;
  va_list list;
  va_start(list, format);
  s.vprintf(format.c_str(), list);
  va_end(list);
  return s;
}
 


Jak to poprawnie obsłużyć dla UnicodeString?

PS
Tak wiem - w powyższym przypadku zamiast pisać własną funkcje PolaczXXX mógłby użyć np wynik.printf(...). Ale to tylko maksymalnie uproszczony przykład. W rzeczywistości ta funkcja robi więcej rzeczy.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: va_list z UnicodeString

Nowy postprzez polymorphism » sobota, 28 grudnia 2013, 22:12

KOD cpp:     UKRYJ  
PolaczUnicode(..., "kota", "psa");

Dostajesz krzaki, bo funkcji podajesz łańcuchy ansi a nie unikodowe. To rozwiązanie jest kiepskie (rodem z C), o czym sam się przekonałeś. Użyj strumieni C++.
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Mironas
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2157
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 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox

Re: va_list z UnicodeString

Nowy postprzez Cyfrowy Baron » niedziela, 29 grudnia 2013, 10:38

Powinno być:

KOD cpp:     UKRYJ  
UnicodeString wynik = PolaczUnicode( L"Ala ma: %s %s", L"kota", L"psa");


Ale wiesz, że z tego wielokropka lepiej jest nie korzystać, bo wyniki mogą być różne nawet jeżeli przekażesz do funkcji te same wartości? Jeżeli przekażesz do funkcji argumenty innego typu niż się spodziewa, to zinterpretuje je po swojemu a kompilator będzie milczał. Taka sytuacja właśnie u ciebie wystąpiła, funkcja oczekiwała UnicodeString (wystarczy pisać String bo to typ domyślny w XE i nowszych), a ty przekazałeś jej AnsiString.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Mironas
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
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 7Firefox

Re: va_list z UnicodeString

Nowy postprzez polymorphism » niedziela, 29 grudnia 2013, 10:54

funkcja oczekiwała UnicodeString (...), a ty przekazałeś jej AnsiString.

Błąd. On nie przekazał jej AnsiStringa, tylko zwykły c-string.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2157
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 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: va_list z UnicodeString

Nowy postprzez Cyfrowy Baron » niedziela, 29 grudnia 2013, 14:20

Tak czy owak przekazał argument innego typu niż funkcja oczekiwała.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
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 7Firefox

Re: va_list z UnicodeString

Nowy postprzez Mironas » poniedziałek, 30 grudnia 2013, 11:41

polymorphism napisał(a):Użyj strumieni C++.


Cyfrowy Baron napisał(a):Ale wiesz, że z tego wielokropka lepiej jest nie korzystać, [...]


A można poprosić o namiary na inne rozwiązanie?
Zaznaczam, że chodzi mi o funkcję do której przekazuję nieokreśloną listę parametrów różnego typu. Z pomyleniem typu zmiennych nie ma problemu (już ;)). Funkcja z wielokropkiem do tej pory (BCB6) sprawiała mi się idealnie. Pod XE jak poprawiłem parametry na L"xxx" też jest już ok.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: va_list z UnicodeString

Nowy postprzez Cyfrowy Baron » poniedziałek, 30 grudnia 2013, 15:14

Może coś takiego:

KOD cpp:     UKRYJ  
String PolaczUnicode(String sText, TVarRec vr[])
{
  String sValue;

  sValue = sText.Format(sText, vr, sizeof(vr));

  return sValue;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 TVarRec vr[] = {"kota", "psa"};

 String wynik = PolaczUnicode( "Ala ma: %s i %s", vr );

 Edit1->Text = wynik;
}


Zauważ, że mimo iż używam typu UnicodeString (w XE i nowszych String oznacza UnicodeString nie AnsiString) nie użyłem znaku L. Nie muszę się martwić o konwersję, gdyż funkcja zadziała prawidłowo zarówno z UnicodeString jak i AnsiString. Oczywiście w przypadku zmiennej AnsiString nie można używać w łańcuchu znaków Unicode.

polimorphism pisząc o strumieniu c++ miał oczywiście coś innego na myśli, ale niech ci to sam wyjaśni.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Mironas
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4719
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 7Firefox

Re: va_list z UnicodeString

Nowy postprzez polymorphism » poniedziałek, 30 grudnia 2013, 21:15

A cóż tu wyjaśniać? Niech użyje strumienia ostringstream \ wostringstream do składania łańcuchów (po to w końcu on jest, żeby nie trzeba było bawić się niebezpiecznymi funkcjami formatującymi lub mechanizmami z C).

Można też pobawić się z szablonami, jeśli chce się mieć funkcję w takiej formie jak teraz, z lepszą kontrolą typów.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2157
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 19
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows 7Firefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

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 13 gości

cron