switch with string problem

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Sun Jul 15 07:30:55 PDT 2007


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


More information about the Digitalmars-d-learn mailing list