Jump to content

  • Log In with Google      Sign In   
  • Create Account

Reading from a text file (c++)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 AntonioR   Members   -  Reputation: 208

Like
0Likes
Like

Posted 04 May 2011 - 05:21 AM

Hi, I need some help.

I want to be able to write some variable values in a text file and then read it from inside the application.

1.
Text file example :
window=0
screenwidth=800
screenheight=600
app_title=my project

So i want to read "window" and then its value, and then apply that value to appropriate variable inside the code.
Also I want to be able to read string or char values.

2.
I would also want to put more variables in the same row, and the read it one by one:
1 0 day month 1000 500


Sponsor:

#2 AndyEsser   GDNet+   -  Reputation: 386

Like
0Likes
Like

Posted 04 May 2011 - 05:33 AM

So which bit are you having a problem with? Reading from a file? Splitting it at the =? Determining whether it's a string or a char?

No-one here is going to just do it for you.

But as a start look into strings, iostream, and data structures.

#3 SiCrane   Moderators   -  Reputation: 9670

Like
0Likes
Like

Posted 04 May 2011 - 05:42 AM

Actually I wouldn't go that route (manually parsing using streams) for a configuration file. Find an existing configuration file library with a syntax that you like and just use that. INI files are strangely popular and so are XML files. There's also boost::program_options for a possibility.

#4 npri   Members   -  Reputation: 107

Like
0Likes
Like

Posted 04 May 2011 - 05:56 AM

For a quick and easy bit of string manipulation if you have access to boost I'd recommend looking at boost::split (within boost/algorithm/string.hpp).
- Teach a programmer an answer, he can code for a day. Show a programmer the documentation, he can code for a lifetime.

#5 AntonioR   Members   -  Reputation: 208

Like
0Likes
Like

Posted 04 May 2011 - 06:03 AM

I just need it for some simple stuff, I don't want to use a whole new library for that.

I know something about iostream, I can read numbers like this.

ifstream filein("config.txt");
filein >>  fullscreen >> SCREENW >> SCREENH  ;

But the text file has just numbers inside so it won't be readable if I add some new stuff.
1
1024
768

So I guess

Splitting it at the =? Determining whether it's a string or a char?

is the actual problem.

#6 mozie   GDNet+   -  Reputation: 194

Like
0Likes
Like

Posted 04 May 2011 - 06:22 AM

If you are going to do it that way (roll your own), I think the basic process is:

1) read the line
2) find offset of '='
3) read before the '=' into a token variable
4) read behind the'=' into a value variable
5) switch on the token to assign the value variable to the correct program variable.
6) repeat with next line

#7 AntonioR   Members   -  Reputation: 208

Like
0Likes
Like

Posted 04 May 2011 - 07:59 AM

I managed to find some code example, it works:

bool LoadSettings(int *Width, int *Height, int *Fullscreen)
{
	FILE* fp;
	
	char string[500];
	fp = fopen("config.txt","r");

	if (fp!=NULL)
	{
		char item[300];
		char value[300];

		while (fgets (string , 300 , fp)!=NULL)
		{
        	//sscanf(string,"%s %[^\n]",&item, &value);
			sscanf(string,"%s %s",&item, &value);

			if (strcmp(item, "width")==0)
			{
				*Width = atoi(value);
			}
			else if (strcmp(item, "height")==0)
			{
				*Height = atoi(value);
			}
			else if (strcmp(item, "fullscreen")==0)
			{
				*Fullscreen = atoi(value);
			}	
		}
	}
	else
	{
    	return false;
	}

}

Txt file:
width 1024
height 768
fullscreen 0


#8 szecs   Members   -  Reputation: 2185

Like
0Likes
Like

Posted 04 May 2011 - 08:25 AM

well, you could simply use
while (fgets (string , 300 , fp)!=NULL)
{
   sscanf(string,"width %d",Width);
   sscanf(string,"height %d",Height);
   sscanf(string,"fullscreen %d",Fullscreen);
}

If the string is not matching, the variables won't be affected, so it can be simple as that. You can even check the return value of sscanf (look it up)

But that's C, not C++. I'm sure C++ has better methods

#9 yewbie   Members   -  Reputation: 665

Like
0Likes
Like

Posted 04 May 2011 - 08:32 AM

Here is what I have been using for awhile, it doesn't read everything at once, but you can continually check the file for various settings.
Feel free to use it or make one yourself based on this, Its a modified version from some tutorial I read about 5 years ago, sorry but I do not have the link :/

ReadConfig.h

//Read a specific variable from our config file and return its value
//This is our error logging class
#ifndef READCONFIG_OBJECT

#define READCONFIG_OBJECT

#include <winsock.h>
#include <stdio.h>
#include <io.h>
#include <FCNTL.H>
#include <iostream>
#include <fstream>
#include <string>
#include <list>
using namespace std;

#define MAX_STRING 255



int ReadConfigInt(char* Filename,char* Variable);  //return -1 on fail, -2 on file not found
string ReadConfigString(const char* Filename,char* Variable); //returns NULL on failure

#endif

ReadConfig.cpp

//Read config
#include "stdafx.h"
#include "ReadConfig.h"

int ReadConfigInt(char* Filename,char* Variable)
{
	

	char line[MAX_STRING];
	memset(line,0,MAX_STRING);
	ifstream myconfig(Filename);
	if(!myconfig)//could not open file
		{
			return NULL; //-2 file not found
		}

	while(!myconfig.eof()) 
		{
				
			myconfig.getline(line, MAX_STRING);  // delim defaults to '\n'
			if(myconfig)
			{
				if(line[0] == '/')  //we are skipping this line
					{ // skip comment line
						continue;
					}
				else
					{
						

						char *pointerchar = NULL;
						char var[MAX_STRING] = {'\0'}; // variable name
						char val[MAX_STRING] = {'\0'}; // value its set to
						size_t length =0;
						pointerchar = strchr(line, '\n'); // find our newline
						if(pointerchar != NULL) 
							{
								*pointerchar = '\0'; //change newline to null character
							}
						length = strlen(line);
						pointerchar = strchr(line, '='); //find our equals character
						if(pointerchar == NULL) 
							{ 
								return NULL; //failure
							} //Parse Error
						
						memcpy(var, line, pointerchar - line);// get the part before the first =
						pointerchar++;// skip the actual '=' sign
						memcpy(val, pointerchar, (line+length)-pointerchar);// get the value of the var
						if (strcmp(var,Variable)==0)//see if we found it
							{
								return atoi(val);
							}
					}

			}
				
		}
	
	myconfig.close();
	

return NULL; //didnt find that variable
}



string ReadConfigString(const char* Filename,char* Variable)
{
	

	char line[MAX_STRING];
	memset(line,0,MAX_STRING);
	ifstream myconfig(Filename);
	if(!myconfig)//could not open file
		{
			return "Unknown";
		}

	while(!myconfig.eof()) 
		{
				
			myconfig.getline(line, MAX_STRING);  // delim defaults to '\n'
			if(myconfig)
			{
				if(line[0] == '/')  //we are skipping this line
					{ // skip comment line
						continue;
					}
				else
					{
						

						char *pointerchar = NULL;
						char var[MAX_STRING] = {'\0'}; // variable name
						char val[MAX_STRING] = {'\0'}; // value its set to
						size_t length =0;
						pointerchar = strchr(line, '\n'); // find our newline
						if(pointerchar != NULL) 
							{
								*pointerchar = '\0'; //change newline to null character
							}
						length = strlen(line);
						pointerchar = strchr(line, '='); //find our equals character
						if(pointerchar == NULL) 
							{ 
								return NULL; 
							} //Parse Error
						
						memcpy(var, line, pointerchar - line);// get the part before the first =
						pointerchar++;// skip the actual '=' sign
						memcpy(val, pointerchar, (line+length)-pointerchar);// get the value of the var
						if (strcmp(var,Variable)==0)//see if we found it
							{
								return val;
							}
					}

			}
				
		}
	
	myconfig.close();
	

return NULL; //didnt find that variable
}


#10 rip-off   Moderators   -  Reputation: 8727

Like
2Likes
Like

Posted 04 May 2011 - 08:51 AM

Doing the same in c++:
#include <string>
#include <fstream>

bool LoadSettings(int &Width, int &Height, int &Fullscreen)
{
   std::ifstream file("config.txt");
   if(!file.is_open())
   {
       return false;
   }
   std::string line;
   while(std::getline(file, line))
   {
       std::stringstream stream(line);
       std::string name;
       int value;
       if(stream >> name >> value)
       {
           if(name == "width")
           { 
               Width = value;
           }
           else if(name == "height")
           { 
               Height = value;
           }
           else if(name == "fullscreen")
           {
               Fullscreen = value;
           }
           else
           {
               std::cerr << "Unknown config name: " << name << '\n';
           }
       }
       else
       {
           std::cerr << "Failed to parse line: " << line << '\n';
       }
   }
}
Note this also features more robust error checking. The code you posted fails to fclose() the file you fopen(), among other issues.

I would not recommend using yewbie's code, it is terrible.

#11 yewbie   Members   -  Reputation: 665

Like
0Likes
Like

Posted 04 May 2011 - 08:59 AM

Note this also features more robust error checking. The code you posted fails to close the file, among other issues.

I would not recommend using yewbie's code, it is terrible.


Heh, I am not going to defend what I posted as good code but the tutorial specifically said that when ifstream goes out of scope it cleanly closes the file.
And most of what is posted is directly from the tutorial. ( Edit: not that tutorials are to be trusted )

Much like the OP I only needed it for a couple of config lines and it worked fine for that.
Your code looks much better.

#12 rip-off   Moderators   -  Reputation: 8727

Like
0Likes
Like

Posted 04 May 2011 - 09:13 AM

... when ifstream goes out of scope it cleanly closes the file.

That comment was directed at the OP's code, which uses fopen() but fails to call fclose(). I wrote my post before the intermediate comments, and I edited it to include a note about the code you posted, so I can see now why you might think that.

#13 AntonioR   Members   -  Reputation: 208

Like
0Likes
Like

Posted 04 May 2011 - 10:36 AM

Thanks for the help.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS