www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Obsecure problem 1

reply pascal111 <judas.the.messiah.111 gmail.com> writes:
I've typed a code to enjoy with my library "dcollect", and found 
non-understandable error:

module main;

import std.stdio;
import dcollect;
import std.string;
import std.conv;


int main(string[] args)
{

         string sentence_x,
         sent_result, token2;
         string[] sentence_tokens;

         writeln(strstring(5,"*")," No tail \"s\" 
",strstring(5,"*"));
         writeln;

         write("Compose a line: ");
         sentence_x=strip(readln());

         sentence_tokens=sentence_x.d_strtok(" ,;.:!?\"'");

         foreach(token; sentence_tokens){
             token2=token.strrtrim;
             if(token2[token2.length-1]=='s')
                 token2=strdel(token2, token2.length-1,1);
                 sent_result~=token2~" ";}

         sent_result.writeln;

     	return 0;
     }


dcollect library:
https://github.com/pascal111-fra/D/blob/main/dcollect.d

I changed some data types of some functions parameters to "ulong":

string strdel(const string ch, ulong x, ulong l )
{

         string l_ch=ch.strleft(x);
         string r_ch=ch.strright(ch.length-(x+l));

         return (l_ch~=r_ch);

}

string strleft(const string ch, ulong n)
{

         string ch_sub;

         ch_sub=ch[0..n];

         return ch_sub;

}

/************************************/

string strreverse(const string ch)
{

         string ch_rev;

         for(ulong i=ch.length-1; i>=0; i--)
             ch_rev~=ch[i];


         return ch_rev;


}

/*********************************************/

string strright(const string ch, ulong n)
{

         string ch_sub1,
         ch_sub2;

         ch_sub1=strreverse(ch);

         ch_sub2=strleft(ch_sub1, n);

         ch_sub1=strreverse(ch_sub2);

         return ch_sub1;

}

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

Running screen says:

https://i.postimg.cc/G3YyCmbF/Screenshot-from-2022-07-30-23-23-59.png
Jul 30 2022
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
It is a pretty straight forward.

You tried to access memory out of bounds of the slice.

https://github.com/pascal111-fra/D/blob/main/dcollect.d#L34

That for loop is problematic in a number of ways.

You should not use int, or uint to index into memory, only size_t should 
be used. It is an alias to either uint or ulong based upon the size of a 
pointer.

```d
for(size_t i = ch.length - 1; i >= 0; i--)
```

Would be the corrected line.

However, it is still not correct, what happens when ch.length is zero? 
It'll wrap around and become a very large number. That is most likely 
what happened here.

To do this safely in D, use the foreach_reverse statement instead. There 
are very few reasons to use for loops in D.

https://dlang.org/spec/statement.html#foreach-range-statement

Adjusted:

```d
foreach_reverse(i; 0 .. ch.length)
```

However this is not efficient as you are reallocating constantly.

```d
char[] ch_rev;
ch_rev.length = ch.length;

size_t offset;
foreach_reverse(c; ch)
	ch_rev[offset++] = c;
```
Jul 30 2022
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Saturday, 30 July 2022 at 21:48:35 UTC, rikki cattermole wrote:
 It is a pretty straight forward.

 You tried to access memory out of bounds of the slice.

 https://github.com/pascal111-fra/D/blob/main/dcollect.d#L34

 That for loop is problematic in a number of ways.

 You should not use int, or uint to index into memory, only 
 size_t should be used. It is an alias to either uint or ulong 
 based upon the size of a pointer.

 ```d
 for(size_t i = ch.length - 1; i >= 0; i--)
 ```

 Would be the corrected line.

 However, it is still not correct, what happens when ch.length 
 is zero? It'll wrap around and become a very large number. That 
 is most likely what happened here.

 To do this safely in D, use the foreach_reverse statement 
 instead. There are very few reasons to use for loops in D.

 https://dlang.org/spec/statement.html#foreach-range-statement

 Adjusted:

 ```d
 foreach_reverse(i; 0 .. ch.length)
 ```

 However this is not efficient as you are reallocating 
 constantly.

 ```d
 char[] ch_rev;
 ch_rev.length = ch.length;

 size_t offset;
 foreach_reverse(c; ch)
 	ch_rev[offset++] = c;
 ```
Your suggestion works. It seems a problem with that "for" loop, but I don't know exactly from where it got a 0 or subtracted of 0. I changed data types of some parameters and for loops, and changed that for loop as you suggested: https://github.com/pascal111-fra/D/blob/main/dcollect.d The program works fine now: https://i.postimg.cc/3wkgXmVs/Screenshot-from-2022-07-31-00-04-23.png
Jul 30 2022
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Saturday, 30 July 2022 at 22:17:10 UTC, pascal111 wrote:
 The program works fine now:

 https://i.postimg.cc/3wkgXmVs/Screenshot-from-2022-07-31-00-04-23.png
I have a suggestion for you. Use modern possibilities instead of applying functions used in the past to the present. For example, in a world with UTF, ordinary string reversing can result in erroneous results. Also, please don't use pictures, use Markdown instead... SDB 79
Jul 30 2022
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Saturday, 30 July 2022 at 22:45:14 UTC, Salih Dincer wrote:
 On Saturday, 30 July 2022 at 22:17:10 UTC, pascal111 wrote:
 The program works fine now:

 https://i.postimg.cc/3wkgXmVs/Screenshot-from-2022-07-31-00-04-23.png
I have a suggestion for you. Use modern possibilities instead of applying functions used in the past to the present. For example, in a world with UTF, ordinary string reversing can result in erroneous results.
I'm trying, really, to understand modern D features, but I'm from old school, C pure programming and BASIC language, and such languages and styles. D as it's obvious to all of us is a multi-paradigm language and has so advanced features, even its references, I can't understand 'em well, it's 100% new modern language, but every time I'll learn a new feature of it for that I can't surround all of its techniques at once.
 Also, please don't use pictures, use Markdown instead...
Provide me a free solution better than code::blocks with available gdc compiler I found.
 SDB 79
Jul 30 2022
next sibling parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
Another version of the program:

https://github.com/pascal111-fra/D/blob/main/proj04.d
Jul 30 2022
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Sunday, 31 July 2022 at 00:58:47 UTC, pascal111 wrote:
 Another version of the program:

 https://github.com/pascal111-fra/D/blob/main/proj04.d
I have a few more suggestions for you; Among them the first is on the following sample: ```d auto sentence_x = "she has six oxen"; auto noNeedTrim = sentence_x.d_strtok(" "); foreach(token; noNeedTrim) { //token = token.strrtrim; if(token.canFind("s")) { assert(token.length == 3); } else token.writeln; // oxen } ``` But if it's because of typos, it's ok. Lets continue... Why are you using const for strings? After all, they are protected by immutable. Moreover, since you do not use refs, copies are taken in every function and also you have created extra copy for results. ```d enum str = "five hundred twelve"; auto test = str.strltirim; assert(test == "five hundred twelve"); string strltrim(const string ch) { string ch_cpy=ch; while(ch_cpy.strleft(1)==" ") ch_cpy=ch_cpy.strdel(0,1); return ch_cpy; } ``` There are also nicer ways to delete spaces in a text. Have you ever tried using the default arguments and auto? ```d //string[] d_strtok(const string ch, const string delim) auto d_strtok(string ch, string delim = " ")//*/ { import std.functional : not; // [bonus] string[] tokens = ch. splitter!(c => delim.canFind(c)). filter!(not!empty).array; return tokens; } ``` Functions may optionally define default arguments. This avoids the tedious work of declaring redundant overloads. **[bonus]** And using selective imports where necessary is also a nice feature of D. SDB 79
Jul 31 2022
next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Sunday, 31 July 2022 at 07:43:06 UTC, Salih Dincer wrote:
 Why are you using const for strings? After all, they are 
 protected by immutable. Moreover, since you do not use refs, 
 copies are taken in every function and also you have created 
 extra copy for results.
Note sure if I'm misunderstanding, but: D does not copy strings on value passing, because they're inherently reference types. You can think of a string (or any array) as a `struct { size_t length; T* ptr; }` combined with a bunch of syntax magic.
Jul 31 2022
parent Salih Dincer <salihdb hotmail.com> writes:
On Sunday, 31 July 2022 at 14:52:03 UTC, FeepingCreature wrote:
 Note sure if I'm misunderstanding, but: D does not copy strings 
 on value passing, because they're inherently reference types.

 You can think of a string (or any array) as a `struct { size_t 
 length; T* ptr; }` combined with a bunch of syntax magic.
You got it right, but I didn't explain it right. I think you are right. How could I forget! String is actually a struct, embedded in the language. For example, it has members like .dub, .ptr, capacity and .length (get/set). Of course we should get a copy with .dub to avoid side effects. But now that I've tested it, I haven't seen a problem with split() and sort() . Okay, yes sort() can have side effects, for example nums is affected by this. I also had to use to!(dchar[]) because of the UTF: ```d auto sortStr(string E)(string str) { import std.algorithm, std.conv; return str.to!(dchar[]).sort!E; } auto splitStr(string E)(string str) { import std.string; return str.split!string(E); } auto sortArray(T)(T[] arr) { import std.algorithm; return arr.sort; } void main() { import std.stdio : writeln; string test = "alphabet"; auto nums = [ 1, 9, 4, 0, 3 ]; test.sortStr!"a > b".writeln; assert(test == "alphabet"); test.splitStr!"a".writeln; assert(test == "alphabet"); test.sortStr!"a < b".writeln; assert(test == "alphabet"); nums.sortArray.writeln; assert(nums == [0, 1, 3, 4, 9]); } /* Prints: tplhebaa ["", "lph", "bet"] aabehlpt [0, 1, 3, 4, 9] */ ``` In conclusion, one has to be careful, but D is a reliable language. SDB 79
Jul 31 2022
prev sibling parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Sunday, 31 July 2022 at 07:43:06 UTC, Salih Dincer wrote:
 On Sunday, 31 July 2022 at 00:58:47 UTC, pascal111 wrote:
 Another version of the program:

 https://github.com/pascal111-fra/D/blob/main/proj04.d
I have a few more suggestions for you; Among them the first is on the following sample: ```d auto sentence_x = "she has six oxen"; auto noNeedTrim = sentence_x.d_strtok(" "); foreach(token; noNeedTrim) { //token = token.strrtrim; if(token.canFind("s")) { assert(token.length == 3); } else token.writeln; // oxen } ```
I don't know how "assert" works, if you explained it I'll be able to get the idea of your suggestion to apply the appropriate changes on my code.
 But if it's because of typos, it's ok. Lets continue...
I think "typos" are mistakes of typing? I'm not sure.
 Why are you using const for strings? After all, they are 
 protected by immutable. Moreover, since you do not use refs, 
 copies are taken in every function and also you have created 
 extra copy for results.

 ```d
 enum str = "five hundred twelve";
 auto test = str.strltirim;
 assert(test == "five hundred twelve");

 string strltrim(const string ch)
 {
     string ch_cpy=ch;

     while(ch_cpy.strleft(1)==" ")
         ch_cpy=ch_cpy.strdel(0,1);

     return ch_cpy;
 }

 ```

 There are also nicer ways to delete spaces in a text. Have you 
 ever tried using the default arguments and auto?

 ```d

 //string[] d_strtok(const string ch, const string delim)
 auto d_strtok(string ch, string delim = " ")//*/
 {
     import std.functional : not; // [bonus]
     string[] tokens = ch.
     splitter!(c => delim.canFind(c)).
     filter!(not!empty).array;

     return tokens;
 }
 ```

 Functions may optionally define default arguments. This avoids 
 the tedious work of declaring redundant overloads.

 I think you are right, I'll add a default argument in 
 "d_strtok".

 **[bonus]** And using selective imports where necessary is also 
 a nice feature of D.
Beginners are reading my library, so I have some limitations to provide 'em understood code, so if I'll apply a new D syntax, I'll explain it in a video before providing the beginners the code with the new syntax.
 SDB 79
Jul 31 2022
parent reply Salih Dincer <salihdb hotmail.com> writes:
On Sunday, 31 July 2022 at 15:01:21 UTC, pascal111 wrote:
 
 I don't know how "assert" works, if you explained it I'll be 
 able to get the idea of your suggestion to apply the 
 appropriate changes on my code.
**// This code runs forever:** ```d string str; assert(str is null); str = "test"; assert(str !is null); assert(str.length >= 1); str = ""; assert(str !is null); assert(str.length == 0); int count; assert(count == 0); // true assert(true); while(true) { // endless loop } ``` **// This code runs in a little bit:** ```d count = 100; //assert(count); /* or: assert(count > 1); //*/ while(--count) { } assert(count); // false and assert error ```
 But if it's because of typos, it's ok. Lets continue...
I think "typos" are mistakes of typing? I'm not sure.
Yes, typos == "mistakes of typing" for example: ```d void main() { import std.string : split; auto test = "I hav e a car s"; auto result = split!string(test, " "); // ["I", "hav", "e", "a", "car", "", "s"] auto tilly = result[2]; // extra character auto solecism = result[3]; // car is plural auto doubled = result[5]; // doubled separetor import std.stdio : writeln; writeln(tilly, solecism, doubled); } ``` SDB 79
Jul 31 2022
parent pascal111 <judas.the.messiah.111 gmail.com> writes:
On Sunday, 31 July 2022 at 17:03:59 UTC, Salih Dincer wrote:
 On Sunday, 31 July 2022 at 15:01:21 UTC, pascal111 wrote:
 
 I don't know how "assert" works, if you explained it I'll be 
 able to get the idea of your suggestion to apply the 
 appropriate changes on my code.
**// This code runs forever:** ```d string str; assert(str is null); str = "test"; assert(str !is null); assert(str.length >= 1); str = ""; assert(str !is null); assert(str.length == 0); int count; assert(count == 0); // true assert(true); while(true) { // endless loop } ``` **// This code runs in a little bit:** ```d count = 100; //assert(count); /* or: assert(count > 1); //*/ while(--count) { } assert(count); // false and assert error ```
You got the attention by the good understanding of D grammar. I think I got the idea of "assert".
 SDB 79
Jul 31 2022
prev sibling parent frame <frame86 live.com> writes:
On Saturday, 30 July 2022 at 23:40:44 UTC, pascal111 wrote:

 Provide me a free solution better than code::blocks with 
 available gdc compiler I found.

 SDB 79
I don't know if's "better" but there is Visual Studio Code and IntelliJ IDEA for example. Yeah ctrl+v doesn't work on XTERM, the middle mouse button should. I found this in the wild:
 is super weird but in xterm you can copy just by selecting the 
 text, the text is going to get copied to xwindows clipboard not 
 to gnome one so ctrl+v or menus are not going to work for 
 pasting you need to use the middle button of the mouse and in 
 some windows shift+insert uses to work too.

 so: select the text in the terminal keep it open go to any text 
 editor or the browser and press the middle button to paste

 if you are on a mac you can simulate the middle button pressing 
 the touchpad with 3 fingers and if you have a 2 buttons mouse 
 you can simulate the middle one pressing both at the same time.

 A probably more sane option would be to configure codeblocks to 
 use gnome-terminal instead of xterm, in settings -> environment 
 -> general settings you can change it but it seems to close as 
 soon as you try to launch the app
If that doesn't work you have to try another keyboard layout or such configuration or bind the function to another key if your middle mouse button is not present or is not recognized properly.
Jul 30 2022
prev sibling parent reply frame <frame86 live.com> writes:
On Saturday, 30 July 2022 at 21:24:50 UTC, pascal111 wrote:
 I've typed a code to enjoy with my library "dcollect", and 
 found non-understandable error:
...
 Running screen says:

 https://i.postimg.cc/G3YyCmbF/Screenshot-from-2022-07-30-23-23-59.png
Why you don't copy the output instead? A range violation is the safe error (if bound checking enabled) that is thrown if you access an index of a range or array that is out of bounds. You may try to access an index that is larger than elements in the array.
Jul 30 2022
parent reply pascal111 <judas.the.messiah.111 gmail.com> writes:
On Saturday, 30 July 2022 at 21:52:42 UTC, frame wrote:
 On Saturday, 30 July 2022 at 21:24:50 UTC, pascal111 wrote:
 I've typed a code to enjoy with my library "dcollect", and 
 found non-understandable error:
...
 Running screen says:

 https://i.postimg.cc/G3YyCmbF/Screenshot-from-2022-07-30-23-23-59.png
Why you don't copy the output instead?
Because copying the running window contents is not allowed, I couldn't do it in Code::Blocks.
 A range violation is the safe error (if bound checking enabled) 
 that is thrown if you access an index of a range or array that 
 is out of bounds. You may try to access an index that is larger 
 than elements in the array.
I think you are right.
Jul 30 2022
parent reply frame <frame86 live.com> writes:
On Saturday, 30 July 2022 at 22:13:55 UTC, pascal111 wrote:

 Because copying the running window contents is not allowed, I 
 couldn't do it in Code::Blocks.
Not allowed? o.O Did you try to select the text and insert it via middle mouse button in another window? Those terminals usually copy the text by selection automatically.
Jul 30 2022
parent pascal111 <judas.the.messiah.111 gmail.com> writes:
On Saturday, 30 July 2022 at 22:28:52 UTC, frame wrote:
 On Saturday, 30 July 2022 at 22:13:55 UTC, pascal111 wrote:

 Because copying the running window contents is not allowed, I 
 couldn't do it in Code::Blocks.
Not allowed? o.O Did you try to select the text and insert it via middle mouse button in another window? Those terminals usually copy the text by selection automatically.
I tried what you said, and also ctrl+c doesn't work, nothing works, I can't copy the contents of this terminal.Now you have two choices, 1) I continue using pictures 2) I stop that and be unable to describe what's happening in the running time.
Jul 30 2022