tags:

views:

44

answers:

4

Hi. I'm writing a function that should parse a string containing a description of a dice roll, for instance "2*1d8+2". I extract the four values OK when they are integers, but I want to be able to use floats as well for the multiplier and the addition at the end. Things get nasty when I try to parse such a string: "1.8*1d8+2.5".

I have determined that the problem is with the function strcspn. I ask it to parse the input string s (which contains the dice string) and stop at either an asterisk or an 'x':

const char * s = "1.8*1d8+2.5";
size_t l = strcspn(s,"*x");

The function should return 3, as the asterisk is at the 4th position. However, it seems to stop on the decimal separator (period) and returns 1.

It's not that I can't continue writing my function without this, as there are other ways to get things done, but still I'm curious why such a thing would happen. Has anyone ever encountered this problem before?

[EDIT]

Nevermind, I've found the answer, and it was my stupidity rather than the compiler playing tricks on me. I used this code:

if (l = strcspn(s,"*x") < strlen(s)) {
...

which returned 1 (or true) because strcspn(s,"*x") < strlen(s) evaluates to true - and was assigned to the l variable. I should have added parentheses:

if ((l = strcspn(s,"*x")) < strlen(s)) {
...

Thanks for your answers nonetheless, particularly @sleske, who made me analyse my code more deeply (which led to finding the answer).

A: 

I'd use sscanf instead of manually finding stop points and parsing myself. You can get your integers and floats easily out of the string with that.

Santiago Lezica
Yes, I know. I'm not looking for an alternative solution, because there are multiple options available. I'm just wondering why `strcspn` would stop on the period instead of either `*` or `x`.
mingos
+1  A: 

There must be an error somewhere else. I wrote a test program:

#include <stdio.h>
#include <string.h>
void main(){
  const char * s = "1.8*1d8+2.5";
  size_t l = strcspn(s,"*x");
  printf("l: %d\n", l);
}

and compiled it with gcc on Linux. On my system, it outputs "3".

Please post a complete, working example that exhibits the problem. Then we'll see...

sleske
A: 

This code:

#include <stdio.h>
#include <string.h>

int main(void)
{
    const char * s = "1.8*1d8+2.5";
    size_t l = strcspn(s,"*x");
    printf("<<%s>> %zd <<%s>>\n", s, l, s+l);
    return 0;
}

produces this answer on MacOS 10.6.4 (GCC 4.5.1):

<<1.8*1d8+2.5>> 3 <<*1d8+2.5>>

If your compiler and library does not produce the same answer, get a fixed/upgraded version of the software.

(NB: The 'z' modifier in the printf() format string is a C99 feature - it indicates that the type of the parameter is size_t.)

Jonathan Leffler
+1  A: 

Your code works just as you posted it for me1.

#include <stdio.h>
#include <string.h>

int main(void) {
  const char * s = "1.8*1d8+2.5";
  size_t l = strcspn(s,"*x");
  printf("%zd (%.*s)\n", l, (int)l, s);
  return 0;
}
so ross$ ./a.out
3 (1.8)

1. Mac OS X 10.6.4

DigitalRoss