AnsiString and += operator - c++builder

this very little code fragment is heavily confusing me, although I'm only trying to concatenate to strings.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString HelloWorld = "Hello ";
HelloWorld += "World";
TStringList *sl1 = new TStringList();
sl1->Add("Hello");
sl1->Strings[0] += " World";
TStringList *sl2 = new TStringList();
sl2->Add("Hello");
sl2->Strings[0] = sl2->Strings[0] + " World";
Memo1->Lines->Add( HelloWorld ); // prints "Hello World"
Memo1->Lines->Add( sl1->Strings[0] ); // prints "Hello" =====> WHY?
Memo1->Lines->Add( sl2->Strings[0] ); // prints "Hello World"
}
Is the operator += not working on TStringList items?
What would be the proper way to do so?

Because when you use Strings[0] you are actually accessing a Property, and not the actual string. As such, when you use
sl1->Strings[0] += " World";
what is really happening is that you are invoking the read method for the property Strings, which is then resulting a string. On that resulting string, you are concatenating something else.
This is not changing the property's inner string at all.
In this case, just for the sake of understanding how it works, you could think that reading
sl1->Strings[0]
is the same as calling a function that returns a string (and in fact, it is! Because when you read a property it is running it's read method).

Related

How to use UnicodeString.sprintf() mixed with std::string arguments?

I have to add a feature to a project made in C++ with RAD Studio, and I can't seem to wrap my head around all of the different string types.
This compiles:
std::string batchID = "abc";
UnicodeString msg = UnicodeString().sprintf(L"Batch# %s", batchID.c_str());
But the variables contain these values:
[batchID] _Mypair { { { "abc\0\"\0\0€¼ÇwG\x01\0\0", "", "abc\0\"\0\0€¼ÇwG\x01\0\0" }, 3, 15 } }
[msg] Data :02787394 L"Batch# 扡c\"耀잼瞁Ň
Somewhere else in the code, the format string is %ls and it works! In fact, I copied these two lines from elsewhere that works, but this is what I get. Why? How to fix this?
Why are there 20 different string types all incompatible from one another!
What you are getting in msg is commonly known as "Mojibake", which is caused by interpreting string data in the wrong encoding.
UnicodeString is exclusively a UTF-16 encoded string type on all platforms. Internally, the UnicodeString::sprintf() method is using the vsnwprintf() function, where the undecorated %s placeholder expects a C-style null-terminated UTF-16 character string (ie, wchar_t* on Windows, and char16_t* on Posix), but you are giving it an 8bit char* string instead.
To print a char* string using UnicodeString::sprintf(), you need to use the %hs placeholder (not %ls) instead (see Format Specifiers in C/C++), eg:
std::string batchID = "abc";
UnicodeString msg = UnicodeString().sprintf(_D("Batch# %hs"), batchID.c_str());
An alternative solution is to use the UnicodeString::Format() method instead, which accepts both 8bit and 16bit string types in its %s placeholder, eg:
std::string batchID = "abc";
UnicodeString msg = UnicodeString::Format(_D("Batch# %s"), ARRAYOFCONST(( batchID.c_str() )) );
Alternatively, UnicodeString can be constructed from a char* string, so you can prepare the msg content using just char data, and then construct a final UnicodeString at the end, eg:
std::string batchID = "abc";
std::ostringstream oss;
oss << "Batch# " << batchID;
UnicodeString msg = oss.str().c_str();
std::string batchID = "abc";
UnicodeString msg = ("Batch# " + batchID).c_str();
Or, using the {fmt} library (until C++Builder adds support for C++20's std::format()):
std::string batchID = "abc";
UnicodeString msg = fmt::format("Batch# {}", batch).c_str();
Otherwise, just convert the std::string by itself to UnicodeString and concatenate it, eg:
std::string batchID = "abc";
UnicodeString msg = _D("Batch# ") + UnicodeString(batchID.c_str());

How to remove last element from a list in dart?

I'm a beginner in dart.
void main() {
var abf = '+37.4054-122.0999/';
var abf2;
abf2 = abf.replaceAll("+"," ");
var abf1 = abf2.split(RegExp('(?=[+-])'));
print (abf1[0]);
print (abf1[1]);
}
The above code splits abf into two values for me
I want to remove the ending '/'. I tried many split methods using other variables but it's not removing the '/' even though its removing the '+'.
It's not really clear what you're trying to do with the split.
But if you're looking the remove the / this should work:
String number = '+37.4054-122.0999/';
number = number.replaceAll("/"," ");
You can create substring from this while you like to remove last element.
String abf = '+37.4054-122.0999/';
final result = abf.substring(0, abf.length - 1);
print(result);
Dart's List class has a built-in removeLast method. Maybe you can try to split the string and then removing the last element:
String str = "str";
String newStr = str.split(''). removeLast().join('');

How to set DecimalSeparator for a float in C++ Builder

I'm using C++ Builder and my locale is European, so I have a comma as a decimal separator.
I need to convert a double to a decimal point value with a DOT as separator.
I can't find an answer anywhere.
DecimalSeparator is a global variable, simply set it to the desired character before formatting the double, eg:
#include <SysUtils.hpp>
System::String FormatWithDot(double value)
{
System::Char old = Sysutils::DecimalSeparator;
Sysutils::DecimalSeparator = _D('.');
System::String s = Sysutils::FloatToStr(value);
Sysutils::DecimalSeparator = old;
return s;
}
System::String s = FormatWithDot(123.45);
Or, if you need to do this in multiple threads, use the thread-safe version, TFormatSettings::DecimalSeparator:
#include <SysUtils.hpp>
System::String FormatWithDot(double value)
{
Sysutils::TFormatSettings fmt = Sysutils::TFormatSettings::Create();
fmt.DecimalSeparator = _D('.');
return Sysutils::FloatToStr(value, fmt);
}
System::String s = FormatWithDot(123.45);
Just note that DecimalSeparator only applies to Delphi-based RTL functions like FloatToStr(), Format(), etc. It does not apply to C++-based functions like std::(s)printf(), std::to_string(), std::ostream::operator<<, etc. For those, you need to use C++ locales instead.
I solved it in the wee hours of the morning myself. You can use:
TFormatSettings fmt = TFormatSettings::Create();
fmt.DecimalSeparator = '.';
and then format a double like that:
FloatToStr(price, fmt);
I hope it helps someone. I was going crazy.
I know this this is a very old thread, but I was facing this problem today. In my case, my solution is this:
String DotFormatted(long double value, int numberOfDecimals=2) {
String result = Format("%." + IntToStr(numberOfDecimals) + "f", ARRAYOFCONST((value)));
result = StringReplace( result, ",", ".", TReplaceFlags() << rfReplaceAll);
return result;
}
It's equivalent to another one I had in a different language. For me, it's useful because of the numberOfDecimals argument.

Why str.FirstChar() does not return the first char?

UnicodeString us = "12345";
Label1->Caption= us.FirstChar();
The caption will show "12345" instead of "1".
Why is that?
The help page for FirstChar is empty:
Embarcadero Technologies does not currently have any additional
information. Please help us document this topic by using the
Discussion page!
The declaration is this:
const WideChar* FirstChar() const;
const WideChar* LastChar() const;
WideChar* FirstChar();
WideChar* LastChar();
The UnicodeString::FirstChar() method returns a pointer to the first character (just as the UnicodeString::LastChar() returns a pointer to the last character).
The data being pointed to is null-terminated. So the statement Label1->Caption = us.FirstChar(); is the same as if you had written Label1->Caption = L"12345"; instead. The TLabel::Caption property is also a UnicodeString, which has a constructor that accepts a null-terminated WideChar* pointer as input. That is why you see the result you are getting.
If you want just the first character by itself, use UnicodeString::operator[] instead:
Label1->Caption = us[1]; // UnicodeString is 1-indexed!
Or, using FirstChar(), simply dereference the pointer:
Label1->Caption = *(us.FirstChar());
Note that if the UnicodeString::IsEmpty() method returns true, both approaches will fail. operator[] will throw an ERangeError exception. FirstChar() will return a NULL pointer, which is undefined behavior to dereference. So watch out for that, eg:
if (!us.IsEmpty())
Label1->Caption = us[1];
else
Label1->Caption = _D("");
if (!us.IsEmpty())
Label1->Caption = *(us.FirstChar());
else
Label1->Caption = _D("");
A safer option would be to use the UnicodeString::SubString() method instead, which will return an empty string if the requested substring is out of range:
Label1->Caption = us.SubString(1, 1); // also 1-indexed!
Alternatively, you can use the RTL's System::Strutils::LeftStr() function instead:
#include <System.StrUtils.hpp>
Label1->Caption = LeftStr(us, 1);

How do I compare two characters in Dart?

I want to compare two characters. Something like this:
if ('a' > 'b')
However, the above code is comparing two strings.
How do I do this in Dart?
Dart doesn't have a 'char' or 'character' type. You can get the UTF-16 character code from any point in a string, and compare that.
Use codeUnitAt to get the actual character code from a string.
if ('a'.codeUnitAt(0) > 'b'.codeUnitAt(0))
See the codeUnitAt docs: https://api.dartlang.org/docs/channels/stable/latest/dart_core/String.html#codeUnitAt
String in Dart implements the Comparable interface. You can use compareTo to compare them.
String a = 'a';
String b = 'b';
String c = 'a';
print('value: ${a.compareTo(b)}'); // prints "value: -1"
print('value: ${a.compareTo(c)}'); // prints "value: 0"
print('value: ${b.compareTo(a)}'); // prints "value: 1"

Resources