Phantasmal MUD Lib for DGD

Phantasmal Site > DGD > DGD LPC Reference > sscanf in DGD

The sscanf() Function

From: dgd at list.imaginary.com (Erwin Harte)
Date: Tue Dec  4 22:05:01 2001
Subject: [DGD] sscanf

On Tue, Dec 04, 2001 at 07:36:22PM -0800, Chooser Fireman wrote:
> Question on sscanf ... how can I do:
> 
> if (sscanf(sInput, "%s %s", sParam1, sParam2)
> 
> and allow for sParam2 to be more than 1 word and even a sentence?

That's the default behaviour of DGD, as opposed to the C *scanf()
behaviour:

    void
    process_input(string line)
    {
        string verb, rest;

        if (sscanf(line, "%s %s", verb, rest) < 2) {
            verb = line;
            rest = nil;
        }
        /* ... */
    }

This will split up a line like 'put foo in bar' into 'put' and
'foo and bar' or a line like 'smile' into 'smile' and nil.

Erwin.
-- 
Erwin Harte

From: dgd at list.imaginary.com (Jay Shaffstall)
Date: Wed May  7 10:32:00 2003
Subject: [DGD] Use of sscanf

I'm using sscanf to try to distinguish between ints and floats, and I'm not 
sure if the results I'm seeing are a bug in sscanf, or simply an 
undocumented feature.  Here's the code I use:

if (sscanf (temp, "%d", value) != 1)
	if (sscanf (temp, "%f", value) != 1)
		error ("variable does not hold an integer or float value.  Contents are: 
" + temp);

Where temp is a string variable containing a number the user typed in and 
value is a mixed variable.  What I'm seeing is that the use of %d in sscanf 
will truncate a float number and return me the integer portion of it.  So:

	sscanf ("77.30","%d",value)

gives me an integer 77 in value.

Is this what is supposed to happen?  I had expected that if the string did 
not contain an integer, then %d would not match anything, and my code would 
continue on to try to match a float.

Jay

From: dgd at list.imaginary.com (Robert Forshaw)
Date: Wed Jan  7 11:51:01 2004
Subject: [DGD] status

I am trying to figure out the best way to find the master object of a clone 
object. Right now my code is:

static nomask find_object(mixed obj, int master)
{
	if(master)
	{
		if(typeof(obj) == T_STRING) return 
::find_object(seek_and_return_string(obj, "#"));
		return ::find_object(seek_and_return_string(object_name(obj), "#"));
	}

	if(typeof(obj) == T_STRING) return ::find_object(obj);
	return obj;
}

Where seek_and_return_string(string haystack, string needle) looks for 
'needle' in 'haystack' and returns the string up to where 'needle' was 
found.

I get that funny feeling though where I think I might be doing something 
awkwardly or I'm missing an obviously more efficient way of achieving a 
solution. I had a look at status.h and saw this:

# define O_INDEX	5	/* unique ID for master object */

This clearly isn't the same as kernel libs version, which claims to return 
the issue number of an object 
(http://phantasmal.sourceforge.net/DGD/Kernel/Inheritance.html <- bottom of 
that page). The problem is I have no idea what 'unique ID for master object' 
means. Does O_INDEX contain an object pointer? A string? An issue number? 
Does a master object even have an issue number? I thought it didn't. :)

From: dgd at list.imaginary.com (Erwin Harte)
Date: Wed Jan  7 12:14:00 2004
Subject: [DGD] Re: status

On Wed, Jan 07, 2004 at 05:50:52PM +0000, Robert Forshaw wrote:
[...]
> Where seek_and_return_string(string haystack, string needle) looks for 
> 'needle' in 'haystack' and returns the string up to where 'needle' was 
> found.

I think you want to look into sscanf() to replace
seek_and_return_string().

> I get that funny feeling though where I think I might be doing something 
> awkwardly or I'm missing an obviously more efficient way of achieving a 
> solution. I had a look at status.h and saw this:
> 
> # define O_INDEX	5	/* unique ID for master object */
> 
> This clearly isn't the same as kernel libs version, which claims to return 
> the issue number of an object 
> (http://phantasmal.sourceforge.net/DGD/Kernel/Inheritance.html <- bottom of 
> that page). The problem is I have no idea what 'unique ID for master 
> object' means. Does O_INDEX contain an object pointer? A string? An issue 
> number? Does a master object even have an issue number? I thought it 
> didn't. :)

The 'issue' and 'unique id for master object' refer to the same
thing.  I would describe O_INDEX as a unique identifier for the _code_
that an object runs with, which for clones would be the code of the
master object from which the clone was made.

Hope that helps,

Erwin.
-- 
Erwin Harte

From: DGD Mailing List (Michael McKiel)
Date: Sun Feb  8 10:36:00 2004
Subject: [DGD] Fixed get_log_time()

Thanks to Zell for pointing out sscanf...had my mind wrapped around explode
and wasn't seeing the forest for the trees or something :)
Here's the Code, perhaps an example for a newb who knows.
It returns a string that looks like:  "(11:28) 02/08/04"
We use it as a timeStamp in logs. so we know when errors happen, 
and its not as Wordy as ctime().


#include <config.h>
#include <options.h>

string *months;

void create()
{
    months = ({ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 
                "Sep", "Oct", "Nov", "Dec" });
}

string get_log_time()
{
    int i;
    string str;
    mixed *date;

    date = allocate(5);

    sscanf(ctime(time()), "%*s %s %d %d:%d:%*d %d",
        date[0], date[1], date[2], date[3], date[4]);

    /*
       i = pos. of the month date[0] in the months array +1
       getting the number of the calendar month
     */
    i = member_array((string)date[0], months) + 1;

    /* If the month is < 10 we want to add a 0 before it */
    str = (i < 10) ? "0"+i : ""+i;

    /* If the DAY of the month is < 10, again add a 0 before it */
    str += ((int)date[1] < 10) ? "/0"+date[1] : "/"+date[1];

    /* Take the modulus 100 of the year, again < 10 add a 0 */
    str += (( i = (int)date[4] % 100) < 10 ) ? "/0"+i : "/"+i;

    /* Add in the HR:MN and were done :) */
    str = "("+date[2]+":"+date[3]+") "+str;

    return str;
}

From: DGD Mailing List (Neil McBride)
Date: Wed May 19 11:06:09 2004
Subject: [DGD] Scanf vs explode

> I fashioned my creator() function in driver.c after the way the sscanf's
> were
> originally done, due to the way the directories have changed, it requires
> quite a few of them depending on which one is true, I was wondering if it
> would be more efficient to do a single explode, and a switch() instead.

So, uh, I couldn't sleep.  I was wondering about some code efficiency too
but never really looked into how to find a good way to test coding styles
for efficiency, until I couldn't sleep .....

In my insomniac driven boredom, I put the following little file together. 
Somewhat imaginatively, I called it test.c:

void t1() {
  int i, j;

  for(i = 0; i < 10; i++) {

    j = status()[23];
    if(i == 0) {
      this_user()->message(i + "\n");
    } else if(i == 1) {
      this_user()->message(i + "\n");
    } else if(i == 2) {
      this_user()->message(i + "\n");
    } else if(i == 3) {
      this_user()->message(i + "\n");
    } else if(i == 4) {
      this_user()->message(i + "\n");
    } else if(i == 5) {
      this_user()->message(i + "\n");
    } else if(i == 6) {
      this_user()->message(i + "\n");
    } else if(i == 7) {
      this_user()->message(i + "\n");
    } else if(i == 8) {
      this_user()->message(i + "\n");
    } else if(i == 9) {
      this_user()->message(i + "\n");
    }
    j -= status()[23];
    this_user()->message("Ticks used: " + j +"\n");
  }
}

void t2() {
  int i, j;

  for(i = 0; i < 10; i++) {

    j = status()[23];
    switch(i) {
      case 0:
        this_user()->message(i + "\n");
      break;
      case 1:
        this_user()->message(i + "\n");
      break;
      case 2:
        this_user()->message(i + "\n");
        this_user()->message(i + "\n");
      break;
      case 3:
        this_user()->message(i + "\n");
      break;
      case 4:
        this_user()->message(i + "\n");
      break;
      case 5:
        this_user()->message(i + "\n");
      break;
      case 6:
        this_user()->message(i + "\n");
      break;
      case 7:
        this_user()->message(i + "\n");
      break;
      case 8:
        this_user()->message(i + "\n");
      break;
      case 9:
        this_user()->message(i + "\n");
      break;
    }
    j -= status()[23];
    this_user()->message("Ticks used: " + j +"\n");
  }
}

void t3() {
  int i, j;

  for(i = 0; i < 10; i++) {

    j = status()[23];
    this_user()->message(((i == 0) ? i : (i == 1) ? i : (i == 2) ? i : (i
== 3) ? i : (i == 4) ? i : (i == 5) ? i : (i == 6) ? i : (
i == 7) ? i : (i == 8) ? i : (i == 9) ? i : i) + "\n");
    j -= status()[23];
    this_user()->message("Ticks used: " + j +"\n");
  }
}

Oh yeah, element 23 status() results is ST_TICKS or the remaining ticks. 
Was the only way I could think of at 2am to get a good indication.  Any
other way? :)  Another thing, it's obvious the if/then and switch
statements can be removed in the given example and just send the user his
message, but that's not the point now is it?

Then, the moment of compiling .....

> compile test.c
$33 = </usr/sarak/sys/test>
> code $33->t1();
0
Ticks used: 303
1
Ticks used: 307
2
Ticks used: 311
3
Ticks used: 315
4
Ticks used: 319
5
Ticks used: 323
6
Ticks used: 327
7
Ticks used: 331
8
Ticks used: 335
9
Ticks used: 338
$34 = nil
> code $33->t2();
0
Ticks used: 303
1
Ticks used: 303
2
Ticks used: 303
3
Ticks used: 303
4
Ticks used: 303
5
Ticks used: 303
6
Ticks used: 303
7
Ticks used: 303
8
Ticks used: 303
9
Ticks used: 303
$35 = nil
> code $33->t3();
0
Ticks used: 303
1
Ticks used: 307
2
Ticks used: 311
3
Ticks used: 315
4
Ticks used: 319
5
Ticks used: 323
6
Ticks used: 327
7
Ticks used: 331
8
Ticks used: 335
9
Ticks used: 339

The verdict: Switch wins hands down, even after the first iteration :)

I hope you've all enjoyed this little adventure into what goes on when I
can't sleep :)

*bow*