www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - sscanf() and string "reads" via %s?

reply AEon <aeon2001 lycos.de> writes:
Does anyone know how to make this work properly? The int's are fine, but 
I can't seem to get the fragger/fragged vars to work properly:

<code>
int min, sec, pl1, pl2, mod;
char[] fragger, fragged;

char[] logline = " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA";
printf("    Logline: \"%.*s\"\n", logline);

sscanf( logline, "%d:%d Kill: %d %d %d: %s killed %s by MOD_PLASMA",
	&min,&sec,&pl1,&pl2,&mod,&fragger,&fragged );

printf("    Min %d, Sec: %d, Pl1 %d, Pl2: %d, Mod: %2d, Fragger '%.*s', 
Fragged '%.*s' \n",
	min,sec,pl1,pl2,mod,fragger,fragged);
</code>

Yields:

     Logline: " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA"
     Min 59, Sec: 58, Pl1 0, Pl2: 3, Mod:  8, Fragger 'Error: Access 
Violation

AEon
Mar 31 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 01 Apr 2005 06:37:22 +0200, AEon <aeon2001 lycos.de> wrote:
 Does anyone know how to make this work properly? The int's are fine, but  
 I can't seem to get the fragger/fragged vars to work properly:

 <code>
 int min, sec, pl1, pl2, mod;
 char[] fragger, fragged;

 char[] logline = " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA";
 printf("    Logline: \"%.*s\"\n", logline);

 sscanf( logline, "%d:%d Kill: %d %d %d: %s killed %s by MOD_PLASMA",
 	&min,&sec,&pl1,&pl2,&mod,&fragger,&fragged );

 printf("    Min %d, Sec: %d, Pl1 %d, Pl2: %d, Mod: %2d, Fragger '%.*s',  
 Fragged '%.*s' \n",
 	min,sec,pl1,pl2,mod,fragger,fragged);
 </code>

 Yields:

      Logline: " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA"
      Min 59, Sec: 58, Pl1 0, Pl2: 3, Mod:  8, Fragger 'Error: Access  
 Violation

Remember, sscanf is a C function, it expects a C "char*" not a D "char[]". Try: import std.c.stdio; void main() { int min, sec, pl1, pl2, mod; char[] fragger, fragged; char[] logline = " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA"; printf(" Logline: \"%.*s\"\n", logline); //guess at length required fragger.length = 100; fragged.length = 100; sscanf( logline, "%d:%d Kill: %d %d %d: %s killed %s by MOD_PLASMA", &min,&sec,&pl1,&pl2,&mod,fragger.ptr,fragged.ptr ); printf(" Min %d, Sec: %d, Pl1 %d, Pl2: %d, Mod: %2d, Fragger '%.*s', Fragged '%.*s' \n", min,sec,pl1,pl2,mod,fragger,fragged); } Regan
Mar 31 2005
next sibling parent AEon <aeon2001 lycos.de> writes:
Regan Heath wrote:

     sscanf( logline, "%d:%d Kill: %d %d %d: %s killed %s by MOD_PLASMA",
     &min,&sec,&pl1,&pl2,&mod,fragger.ptr,fragged.ptr );

Thanx... sigh, I had skimmed the metion of .ptr, but had completely forgotten how the naming for C strings works. Works wonderfully... Ironically with the above I can save tons of coding I did to manually take the log lines appart. Live and learn or so... :) AEon
Mar 31 2005
prev sibling parent reply AEon <aeon2001 lycos.de> writes:
Regan Heath wrote:
 import std.c.stdio;
 
 void main()
 {
     int min, sec, pl1, pl2, mod;
     char[] fragger, fragged;
 
     char[] logline = " 59:58 Kill: 0 3 8: pezen killed AEon by MOD_PLASMA";
     printf("    Logline: \"%.*s\"\n", logline);
 
     //guess at length required
     fragger.length = 100;
     fragged.length = 100;
     
     sscanf( logline, "%d:%d Kill: %d %d %d: %s killed %s by MOD_PLASMA",
     &min,&sec,&pl1,&pl2,&mod,fragger.ptr,fragged.ptr );
 
     printf("    Min %d, Sec: %d, Pl1 %d, Pl2: %d, Mod: %2d, Fragger 
 '%.*s',  Fragged '%.*s' \n",
     min,sec,pl1,pl2,mod,fragger,fragged);
 }

As mentioned in the other post, the above you suggested works wonderfully, but then I wanted to use the sscanf template to print to reconstruct the orgininal log line (primarily to test the sscanf scans): char[] line = " 59:58 Kill: 0 3 8: pezen killed AEon by ROCKET_SPLASH"; char[] post = " by MOD_ROCKET_SPLASH"; char[] fragger, fragged; fragger.length = line.length; // Important! Safe case! fragged.length = line.length; // Generate proper frag line template on the fly // e.g. "%d:%d Kill: %d %d %d: %s killed %s by MOD_ROCKET_SPLASH" char[] templ = "%d:%d Kill: %d %d %d: %s killed %s"~post; sscanf( line, templ, &min,&sec,&pl1,&pl2,&mod, fragger.ptr,fragged.ptr ); // (1) fragger = format("%s",fragger).dup; fragged = format("%s",fragged).dup; // (2) writefln(" %s", format(templ, min,sec,pl1,pl2,mod, fragger,fragged) ); printf(" Min %d, Sec: %d, Pl1 %d, Pl2: %d, Mod: %2d, Fragger '%.*s', Fragged '%.*s' Template '%.*s'\n", min, sec, pl1, pl2, mod, fragger, fragged, templ); The sscanf works. But when I tried to use the templ in a printf like: printf(templ, min,sec,pl1,pl2,mod, fragger,fragged ); it did not work. I then tried (2) writefln(" %s", format(templ, min,sec,pl1,pl2,mod, fragger,fragged) ); using format. That almost works perfectly. Only that fragger and fragged have trailing \0 filling up the strings upto the length line.length. So the question is how do I turn the C strings fragger/fragged back to proper char[]? I tried something like (1) but that failed. I find it very strange that the C strings seem to behave like normal D strings printf(" ... %.*s", fragger), and in other cases like C strings.
Apr 01 2005
next sibling parent reply AEon <aeon2001 lycos.de> writes:
Even when trying to fix the fragger.ptr to a non-zero terminating string 
manually, the below fails.

char[] fr;	// = format("%s",fragger).dup;
char[] fd;	// = format("%s",fragged).dup;
foreach( int i, char Ch; fragger )
	if( Ch == '\0' )
         {
		fr = fragger[0..i];
		fr.length = i;
	}					
				
foreach( int i, char Ch; fragged )
         if( Ch == '\0' )
	{
		fd = fragged[0..i];
		fd.length = i;
  	}
		
writefln("    %s", format(templ, min,sec,pl1,pl2,mod, fr,fd) );

fr and fd, keep all the trailing \0...hmpf.

AEon
Apr 01 2005
parent AEon <aeon2001 lycos.de> writes:
AEon wrote:
 Even when trying to fix the fragger.ptr to a non-zero terminating string 
 manually, the below fails.
 
 char[] fr;    // = format("%s",fragger).dup;
 char[] fd;    // = format("%s",fragged).dup;
 foreach( int i, char Ch; fragger )
     if( Ch == '\0' )
         {
         fr = fragger[0..i];
         fr.length = i;
     }                   
                
 foreach( int i, char Ch; fragged )
         if( Ch == '\0' )
     {
         fd = fragged[0..i];
         fd.length = i;
      }
        
 writefln("    %s", format(templ, min,sec,pl1,pl2,mod, fr,fd) );
 
 fr and fd, keep all the trailing \0...hmpf.

Finally, this at least seems to work: char[] fr; // = format("%s",fragger).dup; char[] fd; // = format("%s",fragged).dup; foreach( int i, char Ch; fragger ) if( Ch != '\0' ) fr ~= Ch; foreach( int i, char Ch; fragged ) if( Ch != '\0' ) fd ~= Ch; writefln(" %s", format(templ, min,sec,pl1,pl2,mod, fr,fd) ); But I doubt this is the way one handles C strings. AEon
Apr 01 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 So the question is how do I turn the C strings fragger/fragged back to 
 proper char[]? I tried something like (1) but that failed.

fragger = fragger[0 .. strlen(fragger.ptr)]; you can find strlen in std.string.
Apr 01 2005
next sibling parent AEon <aeon2001 lycos.de> writes:
Ben Hinkle wrote:

So the question is how do I turn the C strings fragger/fragged back to 
proper char[]? I tried something like (1) but that failed.

fragger = fragger[0 .. strlen(fragger.ptr)]; you can find strlen in std.string.

Thanx, works just fine. AEon
Apr 01 2005
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Fri, 1 Apr 2005 20:53:02 -0500, Ben Hinkle <ben.hinkle gmail.com> wrote:
 So the question is how do I turn the C strings fragger/fragged back to
 proper char[]? I tried something like (1) but that failed.

fragger = fragger[0 .. strlen(fragger.ptr)]; you can find strlen in std.string.

Will this also work: fragger.length = strlen(fragger.ptr); Regan
Apr 01 2005