Files

This is a discussion on Files within the C++ Programming forums, part of the General Programming Boards category; I have to figure out how to input some variables into a file and read them back Code: struct party ...

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    51

    Files

    I have to figure out how to input some variables into a file and read them back
    Code:
    struct party {
    	char heroname[50];
    	int Hclass;
    	int hp;
    	int stamina;
    	int mp;
    	int damage;
    }hero1;
    
    
    	herostats.open ("Rpg++.txt", ios::trunc | ios::in);
    
    	if (herostats.is_open()) {
    	cout<<"Charater creation!\n";
    	cout<<"What is your heros name?";
    	cin.getline(hero1.heroname,49,'\n');
    	cout<<"What is your hero class?";
    	cin>>hero1.Hclass;
    	herostats<<hero1.heroname;
    	herostats<<hero1.Hclass;
    	herostats.close();
    	}
    	else{
    	cout<<"Error: Couldn't create/open the file called herostats\n";
    	}
    I was able to make it write to the file but I was wondering how would I get a certain part of the file aka only the charaters name and not the numbers with it

    *Edit*I was just basically wondering how I could seperate the data and receive only that part aka lets say they enter Bob paladin 500(hp) 500(mp)

    so when It writes to the file it has like a divider Bob|paladin|500|500 and I could just get like block one or two only
    Last edited by Shadowwoelf; 01-11-2007 at 07:39 PM.

  2. #2
    pwns nooblars
    Join Date
    Oct 2005
    Location
    Portland, Or
    Posts
    1,094
    The simplest way, read the file in, find what you want to change, change it in the buffer, write the whole file back out. That is how most games do it, you load the save file, then when done or selected you write it all back out (save it)

  3. #3
    Registered User
    Join Date
    Dec 2006
    Posts
    51
    Can you show me an example or explain it abit more simpler because what you said confused me

  4. #4
    pwns nooblars
    Join Date
    Oct 2005
    Location
    Portland, Or
    Posts
    1,094
    Open the file
    Read the file to a buffer (like a char array) or into a struct if you are writing the struct to the file (look up binary file IO)
    If you read to a buffer, sort the information out into your struct
    Change the piece of information you need to change
    Write it back out to the file.

    In the above I just read your edit. What you would do is read in the whole thing (with the |s) then sort it all back out into your struct. What may make this easier for you, is to look into binary file IO and the reading/writing of structs to a file, then you wouldn't have any sorting to do.

  5. #5
    Registered User
    Join Date
    Dec 2006
    Posts
    51
    I can't seem to find a good website that explains file I/O, I don't suppose you can give me a recommended link? Also I cant seem to find a decent explanation of how to get a specific part of a text file like if I just want the characters from 1-10 in the entire file and not the entire line

  6. #6
    Registered User
    Join Date
    Sep 2005
    Posts
    142
    Quote Originally Posted by Shadowwoelf
    I have to figure out how to input some variables into a file and read them back
    Code:
    struct party {
    	char heroname[50];
    	int Hclass;
    	int hp;
    	int stamina;
    	int mp;
    	int damage;
    }hero1;
    
    
    	herostats.open ("Rpg++.txt", ios::trunc | ios::in);
    
    	if (herostats.is_open()) {
    	cout<<"Charater creation!\n";
    	cout<<"What is your heros name?";
    	cin.getline(hero1.heroname,49,'\n');
    	cout<<"What is your hero class?";
    	cin>>hero1.Hclass;
    	herostats<<hero1.heroname;
    	herostats<<hero1.Hclass;
    	herostats.close();
    	}
    	else{
    	cout<<"Error: Couldn't create/open the file called herostats\n";
    	}
    I was able to make it write to the file but I was wondering how would I get a certain part of the file aka only the charaters name and not the numbers with it

    *Edit*I was just basically wondering how I could seperate the data and receive only that part aka lets say they enter Bob paladin 500(hp) 500(mp)

    so when It writes to the file it has like a divider Bob|paladin|500|500 and I could just get like block one or two only
    Dude i have been messin with this problem for some time now and it's not as easy as it may sound, from what i have learnt you have to read the file into a buffer then monipulate the contents some how.

    the way i have been trying to do it is with string class members.

    um i can't really show you because i haven't finished it yet.

    all i know is that writing code to sort file contents can be time consuming and long winded ( if you know what i mean ) but don't give up because i have learnt a lot from playing around with it.

    Please PM me and keep me updated as i am doing the same thing we could help each other ( if you want )


    one other thing if you use ios::trunc you will delete the contentsof the file which i don't think you want to do
    WhAtHA hell Is GoInG ON

  7. #7
    Registered User
    Join Date
    Sep 2005
    Posts
    142
    Quote Originally Posted by Shadowwoelf
    I can't seem to find a good website that explains file I/O, I don't suppose you can give me a recommended link? Also I cant seem to find a decent explanation of how to get a specific part of a text file like if I just want the characters from 1-10 in the entire file and not the entire line
    you can do this with strings, but the problem i am having is i am searching numbers to find descriptions when the description name varies in size.
    WhAtHA hell Is GoInG ON

  8. #8
    Registered User
    Join Date
    Dec 2006
    Posts
    51
    Yea thanks wart101 I know that trunc will delete the entire file what I showed you up there was simply the New game function and not the Load game function. I sort of figured out how to fix the problem I just need to know how to actually get certain parts of the file like only characters 1-10 or 4-6.

  9. #9
    Peace
    Join Date
    Aug 2001
    Posts
    1,510
    Look up seekp in your documentaion. You can seek ahead into your save file any amount of bytes to your desired data and read in only that.
    "There's always another way"
    -lightatdawn (lightatdawn.cprogramming.com)

  10. #10
    Registered User
    Join Date
    Dec 2006
    Posts
    51
    if I use seekp to set it at lets say byte 1 and then if I use readsome and have it read only 4 characters will that work?
    Last edited by Shadowwoelf; 01-11-2007 at 11:26 PM.

  11. #11
    Registered User
    Join Date
    Sep 2005
    Posts
    142
    Quote Originally Posted by Shadowwoelf
    if I use seekp to set it at lets say byte 1 and then if I use readsome and have it read only 4 characters will that work?
    i think it would but if you are reading the file you would have to use seekg.
    WhAtHA hell Is GoInG ON

  12. #12
    Kiss the monkey. CodeMonkey's Avatar
    Join Date
    Sep 2001
    Posts
    920
    You COULD create a pos_type for every entry, but that would be foolish. Take Wraithan's advice: read it all into memory, and then deal with it. When you're done, write it back.
    save file:
    Code:
    Bob|Paladin|500|500|George|Necromancer|230|750|
    I might...
    Put it all in memory, then make a vector of the entries between |'s.
    Use that for data.
    Something like this:
    Code:
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    namespace saving   //namespaces = tidy code (when not excessive)
    {
    
    namespace file_settings
    {
       const char delim = '|';
    }
    
    bool load(const std::string & path,std::vector<std::string> & parsed_out)
    {
    std::ifstream saved_f(path.c_str());
    
    //check stream for validity
    if(!saved_f) return false;  //however you deal with this
    
    std::stringstream file_data;
    char ch;
    while(saved_file.get(ch)) file_data.put(ch); //copy streams, char for char
    //keep in mind that file_data's get pointer is still at 0
    
    std::string entry;
    while( std::getline(file_data,entry,file_settings::delim) ) parse_out.push_back(entry); //parse input
    
    return true;
    //ifstream destructor is called, so close() is called
    }
    
    bool save(const std::string & path,std::vector<std::string> & parsed_in)
    {
    std::ofstream saved_f(path.c_str());
    
    //check stream for validity
    if(!saved_f) return false;  //however you deal with this
    
    //put it back out, with separator
    for(int x = 0; x < parsed_in.size(); x++) saved_f << parsed_in[x] << file_settings::delim;
    
    return true;
    }
    
    } //namespace
    
    int main()
    {
       std::string path = "C:\\game\\saved\\001.sav";
       std::vector<std::string> saved_info;
       if(!saving::open(path,saved_info)) 
       {
         std::cerr << "open failure" << std::endl;
         //use defaults
       }
       //..... do all sorts of things... run a game.....
       //...just modify saved_info...
       //..then, whenever user wants to REALLY save
       if(!saving::save(path,saved_info)) std::cerr << "save failure" << std::endl;
       //......
       return 0;
    }
    Also, something like this might come in handy:
    Code:
    namespace specs
    {
       const int num = 4;
       enum { NAME, CLASS, HP, MP };
       const char* names[num] = {"name","class","hp","mp"};
    }
    Then you could display the contents of the file:
    Code:
    //given std::vector<std:string> info
    for(int y = 0; y < info.size(); y++)
    {
       if(y%specs::num == 0 && y != 0) std::cout << std::endl; //newline after every profile
       std::cout << specs::names[y%specs::num] << ": " << info[y] << std::endl;
    }
    So, should your program change what sort of info it saves (as it might), you only have to change these settings namespaces, rather than all of your code.

    Anyway, hope I was a help.

    PS: If anyone sees anything wrong with my idea or code, please do correct me. I'm just learning, too.
    "If you tell the truth, you don't have to remember anything"
    -Mark Twain

  13. #13
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,479
    I can't seem to find a good website that explains file I/O
    Have you tried the tutorial on this site? Its good at explaining io, although a little breif. It may be a better idea to grab a beginners C++ book. Check out the book recomendations on this site to see which ones are the best to choose from.
    I'm just trying to be a better person - My Name Is Earl

  14. #14
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    *Edit*I was just basically wondering how I could seperate the data and receive only that part aka lets say they enter Bob paladin 500(hp) 500(mp)
    As was mentioned, the easiest way is to read in the whole file. You can read each line of the file into an array of strings. If you want to change the info for a given name, then you can search the array for the line containing the name, change the info, and then write the whole array back to the file overwriting what was previously in the file.

    1) The basic setup for reading from a file is like this:

    Code:
    while( getline(myInputFile, aLine) )
    {
    	//do something with the string, e.g. store it in an array
    }
    The key concept is to make the read statement the while loop conditional. If you do that, then when you get to the end of the file, the while loop will terminate automatically. Also, the while loop will terminate before you get to the end of the file if any errors occur while reading from the file, which is what you want, or else your program will get stuck in an infinite while loop.


    2) To store the lines in an array, you need to declare an array that is equal to the maximum number of lines you anticipate will be in the file:

    string linesInFile[1000];

    Then, inside your while loop you can add a counter:
    Code:
    int i = 0;
    while( getline(myInputFile, aLine) )
    {
    	//do something with the string, e.g. store it in an array
    
    	++i;
    }
    That will allow you to store each line at the next spot in the array:
    Code:
    int i = 0;
    string linesInFile[1000];
    string aLine;
    
    while( getline(myInputFile, aLine) )
    {
    	linesInFile[i] = aLine;
    
    	++i;
    }
    3) Then it's a matter of searching through the strings in the array to find the information you want. To find a line with a given name on it, you can do this:
    Code:
    string targetName = "Bob paladin";
    int j;
    for(j = 0; j < i ; j++)
    {
    	if(linesInFile[j].find(targetName) != string::npos)  //string::npos is returned by find() 
                                                          //when the target is not in the string
    	{
    		//do something to the line
    	}
    }
    Now, suppose you want to read out a couple of numbers on a line to use in a mathematical calculation. The problem is that the data is inside a string type. If you need to use the int values in a mathematical calculation, then you have to convert the string values to integer values. There is a very handy thing in C++ called a stringstream(#include <sstream>) that allows you to easily convert strings to numbers(or numbers to string). Here is an example:

    Code:
    stringstream ss;
    ss<<"Bob palidin 12 32"; //output the line to the stringstream
    
    string first, last;
    int num1, int num2;
    
    ss>>first>>last>>num1>>num2; //input data from the stringstream just like with cin
    cout<<num1<<" "<<num2;
    Note: the >> operator stops reading data when it encounters a whitespace, so to get to the numbers, you first need to read in the first and last names. Because ss contains a string, but num1 and num2 were declared as int types, an automatic conversion from string to int occurs when you read from ss into an int type.

    If you want to change some data, then you need to change the appropriate string in the array, then write all the lines in the array back to the file.

    One problem with the code is that you have to declare an array that is as big as the maximum number of lines you anticipate ever having in the file. Supppose that maximum is 10,000 lines but mostly you will only have 10 lines. That means 9,990 strings will be set aside in memory that you never use. So, a better way is to store the lines from the file in a vector. A vector is just like an array, but it starts off small and grows to any size as you add elements to it.
    Last edited by 7stud; 01-12-2007 at 04:21 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Ressources files
    By mikahell in forum Windows Programming
    Replies: 4
    Last Post: 06-19-2006, 07:50 AM
  2. add source files to embedded VC 4.0
    By George2 in forum C++ Programming
    Replies: 4
    Last Post: 06-13-2006, 04:28 AM
  3. *.cpp and *.h files understanding
    By ElastoManiac in forum C++ Programming
    Replies: 4
    Last Post: 06-11-2006, 05:45 AM
  4. Linking header files, Source files and main program(Accel. C++)
    By Daniel Primed in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2006, 11:46 AM
  5. Multiple Cpp Files
    By w4ck0z in forum C++ Programming
    Replies: 5
    Last Post: 11-14-2005, 02:41 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21