On Monday, 13 December 2021 at 22:43:14 UTC, forkit wrote:
>[...]
//char* w = cast(char*)str; // nope. a pointer to a string constant is
// (supposed to be) immutable, so expect undefined behaviour.
note:
>//char* w = cast(char*)str.toStringz; // also ok
this is also undefined behavior (toStringz returns an immutable(char)* which you cast away)
>char* w = strdup(cast(char*)str); // ok
this is a C library function - this is risky if your string is not a string literal (may copy too much or segfault) - I would recommend not using this. This will only work properly when you have string literals (strings that are created using ""
in code, no other strings like those that are for example read from user input, from files or dynamically created)
//char* w = cast(char*)str.dup; // also ok
//char* w = str.dup.ptr; // also ok
[...]
the last two here are equivalent, I personally prefer the last one. I think these are the idiomatic way how to duplicate a string into writable memory and get the pointer to it.
The best way would be not doing this at all - when you manipulate strings/arrays in D you can do so by just assigning the elements like this:
immutable(char)[] replaceChar(char[] str, char ch1, char ch2)
{
for (ulong i = 0; i < len; i++)
{
if (str[i] == ch1)
{
writefln("Found %c at str[%d]", ch1, i); // fine
str[i] = ch2;
}
}
return str.idup;
}
then when you call it:
replaceChar(str.dup, ';', 'X');
or the function more idiomatically:
string replaceChar(scope char[] str, char ch1, char ch2)
{
// ref makes the `c` variable an l-value / assignable and modifies the character when assigned
foreach (i, ref c; str)
{
if (c == ch1)
{
writefln("Found %s at str[%s]", c, i);
c = ch2;
}
}
return str.idup; // you could also not .idup and return char[] and let the caller .idup it when needed
}
You only really need to work with pointers when you interface with a C library that needs them.