www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using "strcpy" to assign value to dynamic char array

reply pascal111 <judas.the.messiah.111 gmail.com> writes:
I know that I can use the next syntax to assign new value to char 
dynamic array, and the new value isn't in same length of the 
current value of the array:

{

char[] s="xyz".dup;

s="Hello World!".dup;

writeln(s);
}

Result:

Hello World!

=====================

But what if I want to use "strcpy" function to assign that new 
value to the array that the problem is that the array won't take 
more than its first initializing value length:

{

char[] s="xyz".dup;

strcpy(&s[0], "Hello World!");

writeln(s);

}

Result:

Hel
Nov 01 2021
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/1/21 3:56 PM, pascal111 wrote:

 But what if I want to use "strcpy" function to assign that new value to 
 the array that the problem is that the array won't take more than its 
 first initializing value length:
 
 {
 
 char[] s="xyz".dup;
 
 strcpy(&s[0], "Hello World!");
 
 writeln(s);
 
 }
 
 Result:
 
 Hel
 
Don't do this, you just corrupted memory! You wrote 13 bytes into a memory location that contains 3. Use `.dup`, it does the equivalent of `strcpy`. Can you share why you want to use `strcpy` here? -Steve
Nov 01 2021
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 1 November 2021 at 20:15:14 UTC, Steven Schveighoffer 
wrote:
 On 11/1/21 3:56 PM, pascal111 wrote:

 But what if I want to use "strcpy" function to assign that new 
 value to the array that the problem is that the array won't 
 take more than its first initializing value length:
 
 {
 
 char[] s="xyz".dup;
 
 strcpy(&s[0], "Hello World!");
 
 writeln(s);
 
 }
 
 Result:
 
 Hel
 
Don't do this, you just corrupted memory! You wrote 13 bytes into a memory location that contains 3. Use `.dup`, it does the equivalent of `strcpy`. Can you share why you want to use `strcpy` here? -Steve
Yes, I'm practicing doing things in low level style like standard C.
Nov 01 2021
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/1/21 1:49 PM, pascal111 wrote:

 Yes, I'm practicing doing things in low level style like standard C.
All you needed extra was to let the slice know about the new length: import std.stdio; import core.stdc.string; void main() { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); s = s.ptr[0..12]; // <-- Here writeln(s); } Now, the result is "correct" without dup: Hello World! The program is as incorrect as its C equivalent would be. ;) Ali
Nov 01 2021
next sibling parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 1 November 2021 at 21:01:31 UTC, Ali Çehreli wrote:
 On 11/1/21 1:49 PM, pascal111 wrote:

 Yes, I'm practicing doing things in low level style like
standard C. All you needed extra was to let the slice know about the new length: import std.stdio; import core.stdc.string; void main() { char[] s="xyz".dup; strcpy(&s[0], "Hello World!"); s = s.ptr[0..12]; // <-- Here writeln(s); } Now, the result is "correct" without dup: Hello World! The program is as incorrect as its C equivalent would be. ;) Ali
This can serve the style I want. It uses OOP style like C++ by putting a pointer as a property, but pointers themselves are low level.
Nov 01 2021
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/1/21 2:28 PM, pascal111 wrote:

 This can serve the style I want.
I am feeling funny right now and showing incorrect code. It's impossible to fit "Hello World!" in "xyz". As Steve said, don't do that. :)
 It uses OOP style like C++ by putting a
 pointer as a property,
D's slices are the equivalent of the following struct (showing for int): struct __Slice__ { size_t length; int * ptr; } So, .ptr is simply a member variable. (Assigning to .length does some magic like allocating more memory in some cases; otherwise it is a member variable as well.)
 but pointers themselves are low level.
arr.ptr is as low as it gets: It is a pointer. Ali
Nov 01 2021
parent pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 1 November 2021 at 21:37:59 UTC, Ali Çehreli wrote:
 On 11/1/21 2:28 PM, pascal111 wrote:

 This can serve the style I want.
I am feeling funny right now and showing incorrect code. It's impossible to fit "Hello World!" in "xyz". As Steve said, don't do that. :)
 It uses OOP style like C++ by putting a
 pointer as a property,
D's slices are the equivalent of the following struct (showing for int): struct __Slice__ { size_t length; int * ptr; } So, .ptr is simply a member variable. (Assigning to .length does some magic like allocating more memory in some cases; otherwise it is a member variable as well.)
 but pointers themselves are low level.
arr.ptr is as low as it gets: It is a pointer. Ali
Anyway, I'm a beginner and any information is useful to me.
Nov 01 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/1/21 2:01 PM, Ali =C3=87ehreli wrote:

 The program is as incorrect as its C equivalent would be. ;)
I wrote a cool function to make it easy to disregard memory safety: import std.stdio; auto assumedLength(S)(ref S slice) { struct LengthSetter { void opAssign(size_t length) { // Nooo! :) *cast(size_t*)(&slice) =3D length; } } return LengthSetter(); } void main() { auto arr =3D [ 1, 2, 3 ]; arr.assumedLength =3D 10; writeln(arr); } Joking aside, I liked the nested struct and its opAssign to mimic=20 internal `arr.length =3D 42` syntax. (I know it involves a potentially=20 expensive delegate but still...) Ali
Nov 01 2021
next sibling parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:
 On 11/1/21 2:01 PM, Ali Çehreli wrote:

 The program is as incorrect as its C equivalent would be. ;)
I wrote a cool function to make it easy to disregard memory safety: import std.stdio; auto assumedLength(S)(ref S slice) { struct LengthSetter { void opAssign(size_t length) { // Nooo! :) *cast(size_t*)(&slice) = length; } } return LengthSetter(); } void main() { auto arr = [ 1, 2, 3 ]; arr.assumedLength = 10; writeln(arr); } Joking aside, I liked the nested struct and its opAssign to mimic internal `arr.length = 42` syntax. (I know it involves a potentially expensive delegate but still...) Ali
This function seems smart and flexible and higher than my current level, I'll study it.
Nov 01 2021
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/1/21 9:03 PM, pascal111 wrote:
 On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:
 Joking aside
...
 
 This function seems smart and flexible and higher than my current level, 
 I'll study it.
Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
Nov 02 2021
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Wednesday, 3 November 2021 at 02:38:56 UTC, Steven 
Schveighoffer wrote:
 On 11/1/21 9:03 PM, pascal111 wrote:
 On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:
 Joking aside
...
 
 This function seems smart and flexible and higher than my 
 current level, I'll study it.
Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
I started to change my mind about doing things in low level of classic C, I started to think get benefits of new features of D.
Nov 03 2021
parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 3 November 2021 at 10:38:45 UTC, pascal111 wrote:
 On Wednesday, 3 November 2021 at 02:38:56 UTC, Steven 
 Schveighoffer wrote:
 On 11/1/21 9:03 PM, pascal111 wrote:
 [...]
 [...]
...
 [...]
Please please, do NOT study this code. It is bad all around. Ali should know better ;) He is joking with the code posted, it should not be used in any real code ever. Not only is it corrupting memory, it may not work as expected in all cases (and will randomly fail). Please learn first how memory works before writing the low-level bits of arrays! As a beginner, I suggest studying what a buffer overrun is, and why it is bad. -Steve
I started to change my mind about doing things in low level of classic C, I started to think get benefits of new features of D.
Good, you will be much happier ☀️
Nov 03 2021
prev sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Monday, 1 November 2021 at 21:32:21 UTC, Ali Çehreli wrote:
 Joking aside, I liked the nested struct and its opAssign to 
 mimic internal `arr.length = 42` syntax. (I know it involves a 
 potentially expensive delegate but still...)
The nested struct is not needed. UFCS works for setters, too: ```D void assumedLength(S)(ref S slice, size_t length) { if(slice.length >= length) slice.length = length; else assert(false, "Let's not corrupt memory today."); } void main() { auto arr = [ 1, 2, 3 ]; arr.assumedLength = 2; writeln(arr); } ```
Nov 02 2021
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/2/21 9:06 PM, tsbockman wrote:

 UFCS works for setters, too:
Oh yeah! Pretty cool. :) Ali
Nov 03 2021
prev sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Monday, 1 November 2021 at 19:56:13 UTC, pascal111 wrote:
 But what if I want to use "strcpy" function to assign that new 
 value to the array that the problem is that the array won't 
 take more than its first initializing value length:

 {

 char[] s="xyz".dup;

 strcpy(&s[0], "Hello World!");

 writeln(s);

 }

 Result:

 Hel
Easy win: use normal operations with static arrays instead of strcpy: ```d unittest { char[3] s = "xyz"; s = "Hello World"; // Error: index [11] exceeds array of length 3 } ``` Now you'll get errors (in range-checked builds) instead of silent bad behavior. With a larger buffer, short assigns (only with string literals) zero the rest of the buffer: ```d unittest { char[15] s = "xyz"; s = "Hello World"; // this is OK assert(s == "Hello World\0\0\0\0"); } unittest { char[15] s = "Hello World"; s = "xyz"; // so is this assert(s[0 .. 5] == "xyz\0\0"); } ``` But more realistically you'll be getting strings from somewhere and can assign a specific region using the length of those strings: ```d unittest { // pretend these are user inputs string ex1 = "Hello World"; string ex2 = "xyz"; char[15] s; s[0 .. ex1.length] = ex1; assert(s == "Hello World\xFF\xFF\xFF\xFF"); s[0 .. ex2.length] = ex2; assert(s[0 .. ex1.length] == "xyzlo World"); } ``` This is all obviously much more of a hassle than normal D string-handling, but if you're going to apply C levels of care with memory and string handling, you can do that in D while still avoiding C levels of bugs. ```d unittest { import std.algorithm : min; import core.stdc.string : strlen; char[6] buf; string output; foreach (input; ["ok", "Way too long!"]) { auto len = min(buf.length-1, input.length); buf[0 .. len] = input[0 .. len]; buf[len] = '\0'; output ~= buf[0 .. len+1]; } assert(output == "ok\0Way t\0"); assert(output[0 .. strlen(&output[0])] == "ok"); } ```
Nov 03 2021
parent pascal111 <judas.the.messiah.111 gmail.com> writes:
On Thursday, 4 November 2021 at 01:29:57 UTC, jfondren wrote:
 On Monday, 1 November 2021 at 19:56:13 UTC, pascal111 wrote:
 But what if I want to use "strcpy" function to assign that new 
 value to the array that the problem is that the array won't 
 take more than its first initializing value length:

 {
. . .
     assert(output == "ok\0Way t\0");
     assert(output[0 .. strlen(&output[0])] == "ok");
 }
 ```
I appreciate your vary explanation.
Nov 04 2021