Re: Problems with write_to_output and buf (sprintf)

From: Thomas Arp (t_arp@stofanet.dk)
Date: 07/31/02


From: "Mathew Earle Reuther" <graymere@zipcon.net>
>   sprintf(buf, "\r\n [Runic Languages] -> ");
>       write_to_output(d, buf);
>     if (class_ok_by_race[(int)GET_RACE(d->character)][16]) {
>       sprintf(buf + strlen(buf), "(%s)%s  ", classes[16].class_letter,
> classes[16].class_name);
>       write_to_output(d, buf); }
>     if (class_ok_by_race[(int)GET_RACE(d->character)][17]) {
>       sprintf(buf + strlen(buf), "(%s)%s  ", classes[17].class_letter,
> classes[17].class_name);
>       write_to_output(d, buf); }

Quick fix:

       write_to_output(d, "\r\n [Runic Languages] -> ");
     if (class_ok_by_race[(int)GET_RACE(d->character)][16])
       write_to_output(d, "(%s)%s  ", classes[16].class_letter,
 classes[16].class_name);
     if (class_ok_by_race[(int)GET_RACE(d->character)][17])
       write_to_output(d, "(%s)%s  ", classes[17].class_letter,
 classes[17].class_name);

Read more below for ideas to make this code better[1]:

First off - to make your code easier to debug, make some macros.
These are examples, meant to be stupid, and also only here to get
my point across.

#define CLASS_MAGIC_STUDIES_ONE 0
#define CLASS_MAGIC_STUDIES_TWO 14
#define CLASS_MAGIC_STUDIES_THREE 19
#define CLASS_RUNIC_LANG_ONE 16
#define CLASS_RUNIC_LANG_TWO 17
etc.

if you wish to keep the same struct you already have, use something
like this:

void list_valid_classes(struct descriptor_data *d) {
  char buf[MAX_STRING_LENGTH];
  int len = 0;
  struct char_data *ch = d->character;

   write_to_output(d, "Please Select a Profession:\r\n\r\n");

   if (class_ok_by_race[(int)GET_RACE(ch)][CLASS_MAGIC_STUDIES_ONE])
      len += snprintf(buf + len, sizeof(buf) - len, "(%s)%s  ",
                      classes[CLASS_MAGIC_STUDIES_ONE].class_letter,
                      classes[CLASS_MAGIC_STUDIES_ONE].class_name);

   if (class_ok_by_race[(int)GET_RACE(ch)][CLASS_MAGIC_STUDIES_TWO])
      len += snprintf(buf + len, sizeof(buf) - len, "(%s)%s  ",
                      classes[CLASS_MAGIC_STUDIES_TWO].class_letter,
                      classes[CLASS_MAGIC_STUDIES_TWO].class_name);

   if (class_ok_by_race[(int)GET_RACE(ch)][CLASS_MAGIC_STUDIES_THREE])
      len += snprintf(buf + len, sizeof(buf) - len, "(%s)%s  ",
                      classes[CLASS_MAGIC_STUDIES_THREE].class_letter,
                      classes[CLASS_MAGIC_STUDIES_THREE].class_name);

   if (len) {
      write_to_output(d, "[Magical Studies] -> %s", buf);
      strcpy(buf, "");
      len = 0;
   }
   and so on, for the other professions.

Or change the 'classes' struct a bit - this _will_ pay off in the
long run:

Instead of a struct like this:

const struct classes_type {
  char class_letter;
  const char *class_name;
  /* more info on the merits of this class */
} classes[] = {
  { 'g', "animist" /*, more info*/},
  { 'h', "elementalist"/*, more info*/}
};

and having to keep track of which classes have which number,
it might pay off to have a struct more like this:

struct classes_sub_type {
  char class_letter;
  const char *class_name;
  int class_number;
  /* more info on the merits of this class */
  struct classes_sub_type *next;
}

struct classes_type {
  const char *super_class_name; /* full name of this class base */
  struct classes_sub_type *classes_list;
                  /* linked list of classes, info as above */
}

Of course this kind of structure would need another kind of
initialisation[2], but would allow you to have more compact and
easier to debug code; assuming you during initialization have
set the int num_classes to the amount of initialized classes_type
structs, this would work:

void list_valid_classes(struct descriptor_data *d) {
  int i, len = 0, output = FALSE;
  struct classes_sub_type c;
  char buf[MAX_STRING_LENGTH-3]; /* \r\n\0 in write_to_output call */
  struct char_data *ch = d->character;

  for (i = 0;i < num_classes;i++){
    /* first, write the profession name at the start of the line */
    len = snprintf(buf, sizeof(buf), "[%20s] ->",
                   classes[i].super_class_name);

    /* now, check the list for available classes */
    for (c = classes[i].classes_list;c != NULL;c = c->next) {
      if (class_ok_by_race[(int)GET_RACE(ch)][c->class_number]) {

        /* if any, write those too (appended to the current line)*/
        len += snprintf(buf + len, sizeof(buf) - len, "(%c)%20s ",
                        c->class_letter, c->class_name);

        /* and make sure to send it */
        output = TRUE;
      }
    }
    if (output) {
      write_to_output(d, "%s\r\n", buf); /* ok */
      output = FALSE;
    }
  }
}


Welcor

[1] 'better' in the meaning "easier to read, debug, expand and perhaps
    faster too"

[2] for instance, an external file:

Magic studies
#1 a
Illusions
#2 b
Summons
#3 e
Necromancy
###
Natural Theology
#14 g
Animist
#17 h
Elementalist
###
etc.

--
   +---------------------------------------------------------------+
   | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
   | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html |
   | Newbie List:  http://groups.yahoo.com/group/circle-newbies/   |
   +---------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 06/25/03 PDT