www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - string mixup problem with stdin.byLine

reply torea <tetorea gmail.com> writes:
Hi all,

I'm still at beginner level in D and trying to make a simple note 
program in the terminal.
I've been struggling with a simple problem for the last 2 hours 
so I could use some help!

What I want to do is:
if I write #m, I record the following lines in a specific string 
member of a class, if I write #r, I record the following lines in 
another string member.
Here is the problematic part of my code :

bool stop = false;
auto enr = new Enreg();	// class Enreg{ public: string motsCles; 
string resume; }
enr.motsCles = "";
bool mode_motsCles = false;
bool mode_resume = false;
foreach( line; stdin.byLine ) {
	writeln( enr.motsCles );  // modified when I pressed #r <enter>
	string cleanLine = strip( cast(string)line );
	string[] words = split( cleanLine );	// la phrase est separee en 
mots

	switch( words[0] ){
		case "##":
			stop = true;
			break;
		case "#m":
			mode_motsCles = true;
			mode_resume = false;
			enr.motsCles = "";
			break;
		case "#r":
			mode_resume = true;
			mode_motsCles = false;
			enr.resume = "";
			break;
		default: break;
	}
	if( stop ) break;
	
	if( cleanLine[0] == '#' ) continue;
	if( mode_motsCles ){
		enr.motsCles = cleanLine;
	}else if( mode_resume ){
		enr.resume ~= cleanLine ~"\\n";
	}
	writeln( enr.motsCles );
}

when I press :
   #m <enter>
   things;stuffs; <enter>
at the end of my foreach, i have enr.motsCles initialized 
correctly with "things;stuffs;"
If I continue with :
   #r <enter>
enr.motsCles is modified at the very beginning of the loop and 
contain "#r\nings;stuffs;"

Anyone has an idea about what's going bad with my code?
Aug 07 2016
parent reply Dave Akers <dave dazoe.net> writes:
I do believe your problem is with the line...
On Monday, 8 August 2016 at 02:44:20 UTC, torea wrote:
 	string cleanLine = strip( cast(string)line );
It's casting a char[] to and immutable(char)[], causing the mutable buffer from byLine to be used as a string. what you want is... string cleanLine = strip( to!string(line) ); which should make a copy of the mutable buffer. I still a beginner at D but I think that will fix your problem. -Dave
Aug 07 2016
parent reply torea <tetorea gmail.com> writes:
On Monday, 8 August 2016 at 05:17:24 UTC, Dave Akers wrote:
 I do believe your problem is with the line...
 On Monday, 8 August 2016 at 02:44:20 UTC, torea wrote:
 	string cleanLine = strip( cast(string)line );
It's casting a char[] to and immutable(char)[], causing the mutable buffer from byLine to be used as a string. what you want is... string cleanLine = strip( to!string(line) ); which should make a copy of the mutable buffer. I still a beginner at D but I think that will fix your problem. -Dave
Problem fixed!! Thank you very much for the solution and the explanation!
Aug 08 2016
next sibling parent reply Seb <seb wilzba.ch> writes:
On Monday, 8 August 2016 at 07:09:55 UTC, torea wrote:
 On Monday, 8 August 2016 at 05:17:24 UTC, Dave Akers wrote:
 I do believe your problem is with the line...
 On Monday, 8 August 2016 at 02:44:20 UTC, torea wrote:
 	string cleanLine = strip( cast(string)line );
It's casting a char[] to and immutable(char)[], causing the mutable buffer from byLine to be used as a string. what you want is... string cleanLine = strip( to!string(line) ); which should make a copy of the mutable buffer. I still a beginner at D but I think that will fix your problem. -Dave
Problem fixed!! Thank you very much for the solution and the explanation!
You should always carefully read the description and Notes ;-)
 Note:
 Each front will not persist after popFront is called, so the 
 caller must copy its contents (e.g. by calling to!string) when 
 retention is needed. If the caller needs to retain a copy of 
 every line, use the byLineCopy function instead.
http://dlang.org/phobos/std_stdio.html#.File.byLine Unfortunately you are not the first one who bumped into this problem and this non intuitive behavior of byLine is heavily disputed.
Aug 08 2016
parent torea <tetorea gmail.com> writes:
On Monday, 8 August 2016 at 12:29:51 UTC, Seb wrote:
 You should always carefully read the description and Notes ;-)

 Note:
 Each front will not persist after popFront is called, so the 
 caller must copy its contents (e.g. by calling to!string) when 
 retention is needed. If the caller needs to retain a copy of 
 every line, use the byLineCopy function instead.
http://dlang.org/phobos/std_stdio.html#.File.byLine Unfortunately you are not the first one who bumped into this problem and this non intuitive behavior of byLine is heavily disputed.
Duh... I've read the documentation but managed to jump over these explanations... reading carefully would have saved me some pain! Hopefully I'll be more careful next time.
Aug 10 2016
prev sibling parent reply Meta <jared771 gmail.com> writes:
On Monday, 8 August 2016 at 07:09:55 UTC, torea wrote:
 On Monday, 8 August 2016 at 05:17:24 UTC, Dave Akers wrote:
 I do believe your problem is with the line...
 On Monday, 8 August 2016 at 02:44:20 UTC, torea wrote:
 	string cleanLine = strip( cast(string)line );
It's casting a char[] to and immutable(char)[], causing the mutable buffer from byLine to be used as a string. what you want is... string cleanLine = strip( to!string(line) ); which should make a copy of the mutable buffer. I still a beginner at D but I think that will fix your problem. -Dave
Problem fixed!! Thank you very much for the solution and the explanation!
Alternatively you can use std.stdio.byLineCopy and don't need to add the `to!string`. If you are calling to!string on ever line there will probably be no performance difference, but if you are not, such as only calling to!string on every *second* line or something like that, you should stick with byLine and calling to!string when needed.
Aug 08 2016
parent torea <tetorea gmail.com> writes:
On Monday, 8 August 2016 at 16:30:39 UTC, Meta wrote:
 Alternatively you can use std.stdio.byLineCopy and don't need 
 to add the `to!string`. If you are calling to!string on ever 
 line there will probably be no performance difference, but if 
 you are not, such as only calling to!string on every *second* 
 line or something like that, you should stick with byLine and 
 calling to!string when needed.
Thanks for the additional tip!
Aug 10 2016