www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - switch with string problem

reply qnull <interflug1 gmx.net> writes:
I've got a problem with a test program i created. There is a switch with
strings inside. 
When I start the program with the argument "t" the result is:
  q = t
  q_len = 116
  default

I don't understand why the program is taking the default branch of the switch
and why q.length = 116 and not q.length = 1.
can somebody give me a hint?
Thank you


Code:
import std.string;

import std.stdio;

import std.c.stdlib;



char[] q;



int main(char[][] args)

{	

	if (args.length == 2) {

		sscanf(&args[1][0],"%s",&q);

	} 

	else {

		printf("just one argument!\n");

		exit(55);

	}

	printf("q = %s\nq_len = %d\n",&q,q.length);


	switch (q)

	{

    	case "t": printf("arg was t!\n"); break;

    	case "l2": printf("arg wasn't t!\n"); break;

    	default: printf("default\n"); break;

	}

	return 0;

}



compiled with gdc 0.23
Jul 15 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
This sort of stuff should really be posted in digitalmars.D.learn. 
Followup-To set (assuming I did it correctly).

qnull wrote:
 I've got a problem with a test program i created. There is a switch with
strings inside. 
 When I start the program with the argument "t" the result is:
   q = t
   q_len = 116
   default
 
 I don't understand why the program is taking the default branch of the switch
and why q.length = 116 and not q.length = 1.
 can somebody give me a hint?
 Thank you

Short version: you're using stuff wrong. Long version:
 Code:
 import std.string;
 
 import std.stdio;
 
 import std.c.stdlib;
 
 
 
 char[] q;

A char[] in D contains a length and a pointer. IIRC both DMD and GDC put them in memory in that order.
 int main(char[][] args)
 
 {	
 
 	if (args.length == 2) {
 
 		sscanf(&args[1][0],"%s",&q);

Here you're basically telling sscanf to copy the first parameter to &q. Unfortunately, &q is the address of the (length, ptr) pair, not the pointer itself. This compiles because C-style variadic functions like sscanf and printf can't check the types of the variadic parameters. The simplest correct way to copy the first parameter to q would be "q = args[1].dup;" (That also allocates storage for the copy, something you forgot to do)
 
 	} 
 
 	else {
 
 		printf("just one argument!\n");

You really shouldn't be using printf in D. You imported std.stdio, so why aren't you using writef[ln]?
 
 		exit(55);
 
 	}
 
 	printf("q = %s\nq_len = %d\n",&q,q.length);

The first format sequence + parameter tell printf to read a string from &q (which is what sscanf put there, but not what D would consider to be the contents of the array) q.length is the first four bytes (on a 32-bit system) of &q. Those contain 't', \0, \0, \0 (the latter two were how they were initialized at program startup, the first two were put there by your wrong use of sscanf. q.ptr is still null (as initialized on startup).
 	switch (q)

Here you're inspecting the contents of an array with .length == 116 (the ASCII character code for 't') and .ptr == null. The only reason you're not segfaulting on the null pointer is that the code that implements the string switch checks that the length is equal before checking that the content is equal, and so never actually dereferences the null because the only options it's comparing against are a length-1 and a length-2 string.
 
 	{
 
     	case "t": printf("arg was t!\n"); break;
 
     	case "l2": printf("arg wasn't t!\n"); break;
 
     	default: printf("default\n"); break;
 
 	}
 
 	return 0;
 
 }
 
 
 
 compiled with gdc 0.23

Jul 15 2007
parent qnull <interflug1 gmx.net> writes:
Thank you for this lesson!
Now the result is as I expected it. 
Next time i'll check digitalmars.D.learn first.
Jul 16 2007