Thread: Working with files

  1. #1
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105

    Working with files

    So I started using files recently and I need to implement them in a more complex program than what I'm going to post here.

    Code:
    #include <iostream>
    #include <ctime>
    #include <fstream>
    
    
    using namespace std;
    
    
    int main()
    {
        //Starts timing
        clock_t begin = clock();
    
    
        int letter;
        cin>>letter;
        cin.ignore();
    
    
        //Obtains the total amount of seconds taken
        clock_t end = clock();
        double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
    
    
        cout << "\nCongratulations, you took " <<elapsed_secs <<" seconds to solve the puzzle!\n\n"
           
    
    
        ofstream a_file ( "Times.txt", ios::app );
     
        a_file<<elapsed_secs <<" seconds\n" <<endl;
    
        a_file.close();
    
    
        cin.get();
    }
    Ok so the program times how long you take to insert a number and saves that time on a .txt file.
    The file must store a maximum of 10 lines (10 times) and sort them out every time there is a time lower than the last the one.
    (The 1st line contains the fastest time, the 10th line contains the slowest time and the list shall be updated when there's a time lower than some in the list).

    My issue is how to work with single lines. All I can do atm is append times to the file continuously without the 10 lines restriction. After I accomplish that I need to sort out the file lines everytime there is a new time. Any help could be appreciated, specially links-based as I'm unaware of the functions related to c++ files,

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    The easiest way to accomplish your task will be to read the file into memory and do all the appending and sorting in memory then when you have everything sorted out print these results to the file. You would open the file for reading, read the file, close the file. Then reopen the file, truncating the contents and then rewrite the file.


    Jim

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    link based huh....
    ifstream
    ofstream

    like jim said: you want to open the file for reading in the beginning, extract all data from it into a vector or something (i imagine at some point you will add player names to complete the best times list); close the file; work the data as you see fit; and open it as a output file to update it, writing over what was there before.
    .. if you want to have the game run on a loop without the program needing to be closed and reopened (something like a "try again" option) you will have to make sure you close the ofstream before you reopen as an ifstream (same as before)

    cheers
    Last edited by killme; 04-12-2013 at 07:09 AM.

  4. #4
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    Ok so I made the following code which counts how many lines the file has:

    Code:
    #include <iostream>
    #include <ctime>
    #include <fstream>
    #include <string>
    
    
    using namespace std;
    
    
    int LinesCounter(string filename)
    {
    	ifstream b_file(filename);
    	
    	// new lines will be skipped unless we stop it from happening:    
    	b_file.unsetf(ios_base::skipws);
    
    
    	// count the newlines with an algorithm specialized for counting:
    	unsigned line_count = count(
    		istream_iterator<char>(b_file),
    		istream_iterator<char>(),
    
    
    		'\n');
    
    
    	return line_count;
    
    
    }
    
    
    int main()
    {
    	//Starts timing
    	clock_t begin = clock();
    
    
    	int letter;
    	cin>>letter;
    	cin.ignore();
    
    
    
    
    	//Obtains the total amount of seconds taken
    	clock_t end = clock();
    	double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
    
    
    	cout << "\nCongratulations, you took " <<elapsed_secs <<" seconds.";
    
    
    	int NumberOfLines = LinesCounter("Times.txt");
    
    
    	if (NumberOfLines < 10)
    	{
    		ofstream a_file ( "Times.txt", ios::app );
    
    
    		a_file<<elapsed_secs <<" seconds" <<endl;
    
    
    		a_file.close();
    	}
    
    
    	cout<<endl <<endl <<endl <<LinesCounter("Times.txt");
    
    
    	cin.get();
    }
    Now I need to sort the times out whenever there's a new time. As Jim said I was also thinking about moving each line to a vector/array and sort it out with quick/bubblesort. Now my issue is how do I move each line to an array position?

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    While your count lines function is very nice, I would just create a function to read the file into a vector. Then you could use the size of the vector to replace your count lines function. Then insert the new time into the vector, sort the vector and write out the complete vector to the file. Remove the last element of the vector if your vector is larger than your desired size before writing the vector to the file.


    Jim

  6. #6
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    Yeh that sounds good as well, but what I'm really having a hard time on is converting a file line into an array position.

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Show what you've tried.

    Also you are making things harder on yourself by tacking on "seconds" to each line.

    Jim

  8. #8
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    In fact each line must look like this "<name> <gender> <time> seconds", I'm just trying to put things easier at this point.

    Anyway, I looked up some info online but I can't seem to get it to work.

    Code:
    #include <iostream>
    #include <ctime>
    #include <fstream>
    #include <vector>
    #include <string>
    
    
    using namespace std;
    
    
    vector<int> lines;
    
    
    bool readFile(string filename){
    
    
    	ifstream d_file;
    	string line;
    
    
    	d_file.open(filename.c_str());
    
    
    	if(!d_file.is_open()){
    		return false;
    	}
    
    
    	while (getline(d_file, line)) {
    		lines.push_back(line);
    	}
    
    
    	return true;
    }
    
    
    int main()
    {
    	clock_t begin = clock();
    
    
    	int letter;
    	cin >> letter;
    	cin.ignore();
    	cout << endl;
    
    
    	clock_t end = clock();
    	double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
    
    
    	ofstream times_file ("Times.txt", ios::app);
    	times_file << elapsed_secs <<endl;
    	times_file.close();
    
    
    	cout<<"you took " <<elapsed_secs <<" secs";
    
    
    	if (readFile("Times.txt"))
    	{
    		for(int i = 0; i < lines.size(); ++i)
    		{
    			cout << lines[i] << endl;
    		}
    	}
    
    
    	cin.get();
    
    
    }
    I don't know why is it not compiling, but it should print out the whole vector content (Which should be the file content)

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Well the error messages from my compiler tell me something:
    main.cpp||In function ‘bool readFile(std::string)’:|
    main.cpp|30|error: no matching function for call to ‘std::vector<int>:ush_back(std::string&)’|
    You defined your global vector as a vector<int> but you're trying to push back a string. Since your file should only have numbers in it, one number per line you could just use the extraction operator to extract the information into a double, which is also what your vector should be.

    Also stop using the global variable and pass it to your function as a parameter.

    Code:
    #include <iostream>
    #include <fstream>
    #include <vector>
    
    using namespace std;
    
    bool readFile(const string& filename, std::vector<double>& lines)
    {
       ifstream d_file(filename.c_str());
    
       if(!d_file.is_open()) {
          return false;
       }
    
       double temp;
       while (d_file >> temp) {
          lines.push_back(temp);
       }
    
       return true;
    }
    
    int main()
    {
       vector<double> lines;
    
       if (readFile("Times.txt", lines))
       {
          cout << lines.size() << endl;
          for(int i = 0; i < lines.size(); ++i)
          {
             cout << lines[i] << endl;
          }
       }
    
       cin.get();
    }
    Jim

  10. #10
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    Yeah, I looked up the code and forgot to make a couple of changes.
    Although it doesn't seem to be working alright. It returns nothing if the file hasn't been opened (which is fine) but when Times.txt is opened it returns 0 regardless of the content of the file

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    The code I posted works for me when the file looks something like:
    0.15
    0.15
    0.2
    0.21
    0.25
    0.25
    0.5
    0.5
    0.5
    0.5
    Jim

  12. #12
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    Hmm it's weird. I created a new project, copy-pasted your code and made a Times.txt file with the content above (0.15 etc etc), but it returns nothing.
    What does yours return exacly?

  13. #13
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    What do you mean by it returns nothing? Do you mean that the program doesn't output anything?

    When I compiled the code I supplied the program outputs the information I posted above.

    Try changing the function so it prints an error message if the file fails to open:

    Code:
    bool readFile(const string& filename, std::vector<double>& lines)
    {
       ifstream d_file(filename.c_str());
     
       if(!d_file.is_open()) {
          cerr << "Oh No! The file failed to open properly\n";
          return false;
       }
     
       double temp;
       while (d_file >> temp) {
          lines.push_back(temp);
       }
     
       return true;
    }
    Jim

  14. #14
    Registered User
    Join Date
    Mar 2013
    Location
    Portugal, Porto.
    Posts
    105
    Yes it outputs nothing. Ill try to do so later, im not at home atm

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Make sure it can actually find the file. Where it should be depends on your IDE (or lack thereof). Typically, when using an IDE, it should be in the project directory. If you are running the executable directly, then put it where the executable is.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Working with png files
    By rodrigorules in forum C Programming
    Replies: 5
    Last Post: 05-12-2010, 10:09 AM
  2. working with files in C
    By dallo07 in forum C Programming
    Replies: 2
    Last Post: 12-04-2008, 11:12 PM
  3. Working with files in C
    By fmchrist in forum C++ Programming
    Replies: 2
    Last Post: 12-27-2005, 02:28 PM
  4. working with files in c
    By fmchrist in forum C Programming
    Replies: 4
    Last Post: 12-27-2005, 02:03 PM
  5. Working with DLL files...
    By Devil Panther in forum Windows Programming
    Replies: 8
    Last Post: 11-15-2004, 12:42 AM