Game Development Community

reading different variables from a single textfile

by Aegis Lord · in Technical Issues · 12/18/2000 (7:38 pm) · 8 replies

For the past nine weeks I've been developing classes for my RPG in Borland C++ 5.0. Now two of them are complete but when I try to read multiple variables in from a textfile it never works. For example, when I try to read 'int, apstring, char, int' into the file for the enemy stats or spell stats it either generates random numbers or nothing at all. Please help. An example of code would be very helpful and greatly appreciated. This has been bugging me for weeks!
Thanks!

About the author

Recent Threads

  • really advanced AI

  • #1
    12/18/2000 (9:21 pm)
    Let me get this right you have a TEXT data-file that you are trying to read data from.

    'int, apstring, char, int'

    I am assuming 'apstring' is just a typical zero terminated C string.

    TEXT FILE
    10 name z 20
    READ
    int a;
    char b[50];
    char c;
    int d;
    handle = fopen("datafile.txt", "r");
    fscanf(handle, "%d %s %c %d", &a, b, &c, &d);
    fclose(handle);
    WRITE
    int a = 10;
    char b[50] = "name";
    char c = 'z';
    int d = 20;
    handle = fopen("datafile.txt", "w+");
    fprintf("%d %s %c %d", a, b, c, d);
    fclose(handle);

    --Rick
    #2
    12/18/2000 (10:57 pm)
    I'd like to expand upon this if I may. This is an example that I hope helps. Lets say this is a player data file:
    // This is a character data file
    
    // Player ID
    Id = 0
    
    Str = 9
    Con = 11
    Dex = 10
    Int = 19
    Wis = 14
    Cha = 18
    Ok, now I put comments in there purposly, and this would read it correctly as well...here is the code to read it:
    // First this is a read-line function, which reads the file
    // it is passed, line by line, ignoring C-style comments
    // ONLY if they are all that is on the line.
    //
    void readLine( FILE *readFile, char *buffer ) {
         do {
              fgets( buffer, 256, readFile );
         } while( ( buffer[0] == '/' ) || ( buffer[0] == '\n' ) );
    }
    
    // Now using this function, we can read the file like so:
    //
    void getData() {
         FILE *dataFile = fopen( "datafile.dat", "rt" );
         char line[255];
    
         // Here is the variables we are reading
         int id, str, con, dex, int, wis, cha;
    
         // Ok, this is going to cut through blank lines
         // that have nothing but a newline character (10)
         // On them, and it will cut out comments until
         // it gets to some data
         readLine( dataFile, line );
         sscanf( line, "Id = %i", &id );
    
         // Get the next line, and keep reading...
         readLine( dataFile, line );
         sscanf( line, "Str = %i", &str );
    
         readLine( dataFile, line );
         sscanf( line, "Con = %i", &con );
    
         readLine( dataFile, line );
         sscanf( line, "Dex = %i", &dex );
    
         readLine( dataFile, line );
         sscanf( line, "Int = %i", &int );
    
         readLine( dataFile, line );
         sscanf( line, "Wis = %i", &wis );
    
         readLine( dataFile, line );
         sscanf( line, "Cha = %i", &cha );
    
         // Ok now you can do whatever you want with the data you just read.
    }

    I hope that helped, I didn't test that EXACT code, I just kind of copy-paste and messed with some code I had. So fux around with it (as my CS professor would say) to make it do exactly what you need.
    -KB
    #3
    12/19/2000 (10:47 am)
    I whipped together a little program for you. This allows you to organize your script in any order you want and easily allows you to add new things. There are better ways to handle the parameter name handling but this one should work good enough for you.

    #include "stdafx.h"
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    typedef struct _CharStats
    {
    	int nInt;
    	int nDex;
    	int nStr;
    	int nCon;
    	int nCha;
    	int nWis;
    } CharStats;
    
    void strtrm ( char* szTrim )
    {
    	char* szStart;
    	char* szEnd;
    
    	// Find the trimmed start of the string.
    	for(szStart=szTrim;
                 *szStart=='\n'||*szStart=='\r'||*szStart==' '||*szStart=='\t';
                 szStart++);
    	
    	// Find the trimmed end of the string.
    	for(szEnd=szTrim+strlen(szTrim)-1;
                 *szStart=='\n'||*szStart=='\r'||*szStart==' '||*szStart=='\t';
                 szEnd-- );
    
    	// Trim the string
    	strncpy ( szTrim, szStart, szEnd - szStart + 1 );
    	szTrim[szEnd-szStart] = '[[6281e0c09eed4]]';
    }
    
    void ParseCharScript ( const char* szFilename, CharStats* pStats )
    {
    	FILE* pFile = fopen(szFilename,"rt");
    	char szLine[1024];
    
    	if(NULL==pFile)
    		return;
    
    	// Read all the lines in the file
    	while(fgets(szLine,1024,pFile))
    	{
    		char* szEqual = strchr ( szLine, '=' );
    		char* szName  = szLine;
    		char* szValue = szEqual + 1;
    
    		// skip lines that dont have a name/value pair
    		if(NULL == szEqual)
    			continue;
    
    		// Split the line string into the name and value 
    		*szEqual = '[[6281e0c09eed4]]';
    
    		// trim whitespace from both strings
    		strtrm ( szName );
    		strtrm ( szValue );
    
    		// Handle name value pairs here.  Here is where 
    		// you could get creative with your code, but i
    		// will just do it the easy way.
    		if ( stricmp ( szName, "str" ) == 0 )
    			pStats->nStr = (int)atol(szValue);
    		else if ( stricmp ( szName, "wis" ) == 0 )
    			pStats->nWis = (int)atol(szValue);
    		else if ( stricmp ( szName, "int" ) == 0 )
    			pStats->nInt = (int)atol(szValue);
    		else if ( stricmp ( szName, "cha" ) == 0 )
    			pStats->nCha = (int)atol(szValue);
    		else if ( stricmp ( szName, "dex" ) == 0 )
    			pStats->nDex = (int)atol(szValue);
    		else if ( stricmp ( szName, "con" ) == 0 )
    			pStats->nCon = (int)atol(szValue);
    	}
    
    	// Close up
    	fclose(pFile);
    }
    
    int main(int argc, char* argv[])
    {
    	if(argc<2)
    	{
    		printf("Please specify a script to parse\n" );
    		return -1;
    	}
    
    	// Initialize the stats structure and parse the character file
    	CharStats stats;
    	memset (&stats, 0, sizeof(stats) );
    	ParseCharScript ( argv[1], &stats );
    
    	// Print results
    	printf("stats:  str=%d  int=%d  con=%d  dex=%d  wis=%d  cha=%d\n",
    	       stats.nStr, stats.nInt, stats.nCon, stats.nDex, stats.nWis, stats.nCha );
    
    	return 0;
    }

    Bryan Dube
    XenWars Coder
    apoxol@hotmail.com
    #4
    12/19/2000 (11:05 am)
    The code was a great help. Unfortunately, my school hasn't taught us how to read multiple variables from a text file or random access files either. They're only required to mention them. Anyway, the code will help me get my classes running now and hopefully my battle program as well! Thanks very much!
    #5
    12/19/2000 (11:46 am)
    I tried to compile your programs but my compiler doesn't have '#include"stdafx.h". So I couldn't test the program out as I'd planned. Otherwise, with a few modifications I believe it can work with my text file.
    Just to clear things up my spell text file is:
    int sor_num; // the number of the spell that will be used when sorting the spells by number.
    apstring s_name; // the name of the spell. Also used when sorting spells alphabetically.
    char s_type; // used to determine type of spell such as attack, heal, support.
    int s_str; // strength of spell. LV 1, 2, or 3
    char s_element; // element of spell. used to determine which of the opponents elements to compare to before calculating damage, probability, or HP healed.
    unsigned total_lp; // spell total exp.
    long n_learn_pnts; // needed pnts to learn or level spell up. profinciency and n_learn_pnts increase when the spell gains a level.
    long learn_pnts; // pnts gained on that spell level. When n_learn_pnts - learn_pnts <= 0, the spell gains a level.
    int prof; // spell profinciency = 0 <= prof <= 100, the closer the number gets to 100, the more powerful it becomes.
    bool learned; // if the spell is learned or not.
    #6
    12/19/2000 (1:00 pm)
    Yeah, i noticed that i left that in. Its a precompiled header, you can just remove it and it should all compile.

    I was wondering if you could explain your script a bit more. Are you defining a structure in that script or are you showing us the format? Will one of your scripts actually look like what was posted? Usually its not too good of an idea to put programming constructs like int, bool, etc. into a script because the people using the scripts arent programmers (if they were you might as well just program it rather than have a script). Ive written alot of scripting parsers for work and for games that im working on so if you need any help let me know.


    Bryan Dube
    XenWars Coder
    apoxol@hotmail.com
    #7
    12/19/2000 (4:58 pm)
    Actually, the variables I posted are its format in order from top to bottom. In th txt file it wil read them in the same order as posted. Then, after they're read from the text file the data will be used implemented into the class constructor. My other classes follow the same format but each have different variables and usually more of them. Also, do you know how to make it randomly access the file as well. The programming classes at my school only teach how to read one variable from a file in sequential order which is of little help to me.
    #8
    12/20/2000 (11:04 am)
    The code that I posted earlier reads a name value pair in any order. With a few changes you should be able to just use that.