Read from files

Posted by Zeno on Mon 16 Aug 2004 05:16 AM — 5 posts, 19,435 views.

USA #0
Eh, I haven't done a lot of code for reading from files, so I ran into a problem. I want to read from a file and store it in the account data. (account->character) But I don't want the character files to be written to, only read. Here's what I have so far:

D_CHAR *load_character(char *player)
{
  FILE *fp;
  D_CHAR *character = NULL;
  char cfile[256];
  char cName[20];
  int size, i;

  cName[0] = toupper(player[0]);
  size = strlen(player);
  for (i = 1; i < size; i++)
    cName[i] = tolower(player[i]);
  cName[i] = '\0';

  sprintf(cfile, "../chars/%s.char", cName);
  if ((fp = fopen(cfile, "r")) == NULL)
    return NULL;

  fclose(fp);
  return character;
}

In the select cmd:

    if ((load_character(arg)) == NULL)
    {
      act_send(act, "No such char.\n\r");
      return;
    }



Everything returns NULL though.

In the main header file, in the account strut:

  D_CHAR        * character;

In the main header file (in diff parts):

typedef struct  character     D_CHAR;

struct character
{
  char          * name;
  char          * skill;
};

D_CHAR *load_character        ( char *character);



So want I want it to do, is when an account selects a character, it loads the char file to account->character, and something like account->character->name will work.
Amended on Mon 16 Aug 2004 05:19 AM by Zeno
Australia Forum Administrator #1

  sprintf(cfile, "../chars/%s.char", cName);
  if ((fp = fopen(cfile, "r")) == NULL)
    return NULL;

// <-- read it here?

  fclose(fp);
  return character;


You seem to be missing a bit. After opening the file you immediately close it. That would be a good spot to read data from it.
USA #2
Yeah, I had tried that before, but gave me a crash that wouldn't debug.

  if ((fp = fopen(cfile, "r")) == NULL)
    return NULL;

  word = fread_word(fp);
  while (!done)
  {
    found = FALSE;
    switch (word[0])
    {
      case 'E':
        if (compares(word, "EOF")) {done = TRUE; found = TRUE; break;}
        break;
      case 'N':
        SREAD( "Name",      character->name      );
        break;
      case 'S':
        SREAD( "Skill",  character->skill  );
        break;
    }
    if (!found)
    {
      bug("Load_char: unexpected '%s' in %s's cfile.", word, player);
      return NULL;
    }

    if (!done) word = fread_word(fp);
  }


  fclose(fp);
  return character;


Now the only problem is, how do I define character? That seems to be what I'm having trouble with.

[EDIT] Forgot g3 flag in my Makefile, made I can debug it now.

Yep. Need a way to define character as the file.
Amended on Mon 16 Aug 2004 06:33 AM by Zeno
USA #3
Try, this.

Define a D_CHAR variable,
D_CHAR *char;

Then make the section look like below:

    if ((char = load_character(arg)) == NULL)
    {
      act_send(act, "No such char.\n\r");
      return;
    }
    else
     account->character = char;

Of course since your working with socketmud you'll need to throw in memory allocation, so you need to add something like this in load_character:

    if ((character = malloc(sizeof(*character))) == NULL)
    {
      bug("Load_player: Cannot allocate memory.");
      abort();
    }

Of course you can do something like I did (and SMAUG did) and create memory allocation macros so you dont need to bother with that all the time. Based upon what I've seen, your loading should work, you probably just needed to allocate memory.
USA #4
Thanks, it worked, with a little tweaking. (Wouldn't let me use char as the D_CHAR var, for obvious reasons)

I plan on making a char.lst, and only have the chars in char.lst selectable. How would I do that? Also, I'm going to try to generate a char list from char.lst, but not sure how to do it.

Going to finish up select/char struct for a while, so if I knew a way to do char.lst before I started, it would help.