Sign in to follow this  
Gylis

[C++]litter in output file + file not auto created

Recommended Posts

I am back again... Sadly... My little program isn't working as intended. It's supposed to read few strings and store them nicely into a file allowing some sort of random access after that. And this is where it gets nasty. Firstly, Database.crpt WILL NOT be created automatically and program will work only if file is created manually. Secondly, it writes something about iterators into my file where it is supposed to be whitespace! The last, but not the least is numbers returned by ofile.tellp(), in program output, lines "Records creation 1, 2" it prints 400, 200. Shouldn't it be 200, 400? I think that's all. Sorry for the lack of comments, didn't think I'll need 'em for such a simple, short term project. Really looking forward to Your answers. Thank You. Program output
Open status:
1
Database size in bytes: 0
Records creation 1: 400
Records creation 2: 200
Enter 0 login:
login_0
Enter 0 name:
name_0
Enter 0 pass:
pass_0
Length:
400
Enter 1 pass:
pass_1
Length:
400
Database.crpt
name_0                                                                                              login_0                                           
pass_0                                                    
m a p / s e t   e r a s e   i t e r a t o r   o u t s i d e   r a n g e                 f : \ p r o g r a m   f i l e s \ m i c r o s o f t   
pass_1 
                                          
Database.h
[source lang = "cpp"]
#ifndef GUARD_DATABASE_H
#define GUARD_DATABASE_H
#include <map>
#include <fstream>
#include <string>
#include <iomanip>

class database
{
public:
	database();
	database(int a, int b, int c);
	int length();
	
	
	std::streampos create_record();  //Creates empty space in a file for name, password, login
	std::streampos edit_name(std::string str, const int &n); //Edits name in already created space
	std::streampos edit_login(std::string str, const int &n);
	std::streampos edit_pass(std::string str, const int &n);
	
	
	bool open(const char*  file_name)
	{
		ofile.open(file_name, std::ios_base::out | std::ios_base::in);
		ifile.open(file_name);
		return ifile.is_open() && ofile.is_open();
	}
	void close()
	{
		ofile.close();
		ifile.close();
	}
private:
	std::map<std::string, int> name_list;
	std::ifstream ifile;
	std::ofstream ofile;
	const int lname; 
	const int llogin;
	const int lpass;
	const int lrec;
};

#endif

[b]Database.cpp[/b]


[source lang = "cpp"]
#include "Database.h"

database::database():lname(100), llogin(50), lpass(50), lrec(lname+llogin+lpass)  {}//Default constructor

database::database(int name, int login, int pass):lname(name), llogin(login), lpass(pass), lrec(lname+llogin+lpass){}//Manually initialised constructor


int database::length(void)
{	
	ifile.seekg(0, std::ios_base::beg);
	int begin = ifile.tellg();
	ifile.seekg(0, std::ios_base::end);
	int end = ifile.tellg();
	return end - begin;
}


std::streampos database::create_record(void)
{
	ofile.seekp(0, std::ios_base::end);
	ofile<<std::string(" ", lname + llogin + lpass);
	return ofile.tellp();
}

std::streampos database::edit_name(std::string str, const int &n)
{
	ofile.seekp(n * lrec, std::ios_base::beg);
	ofile<<std::left <<std::setw(lname) <<str;
	return ofile.tellp();
}


std::streampos database::edit_login(std::string str, const int &n)
{
	ofile.seekp(n * lrec + lname, std::ios_base::beg);
	ofile<<std::left <<std::setw(llogin) <<str;
	return ofile.tellp();
}
std::streampos database::edit_pass(std::string str, const int &n)
{
	ofile.seekp(n * lrec + lname + llogin, std::ios_base::beg);
	ofile<<std::left <<std::setw(lpass) <<str;
	return ofile.tellp();
}


Main.cpp
[source lang = "cpp"]
#include <iostream>
#include <string>
#include "Database.h"
#include <fstream>

//
int main()
{	
	database db;
	std::cout<<"Open status: " <<std::endl;
	std::cout<<db.open("database.crpt") <<std::endl;

	std::cout<<"Database size in bytes: " <<db.length()<<std::endl;
	std::string str;

	std::cout<<"Records creation 1: "<<db.create_record()<<std::endl 
		<<"Records creation 2: "<<db.create_record()<<std::endl;
	
	std::cout<<"Enter 0 login:"<<std::endl;
	std::cin>>str;
	db.edit_login(str, 0);
	str.clear();
	
	std::cout<<"Enter 0 name: " <<std::endl;
	std::cin>>str;
	db.edit_name(str, 0);
	str.clear();
	
	std::cout<<"Enter 0 pass: " <<std::endl;
	std::cin>>str;
	db.edit_pass(str, 0);
	str.clear();
	
	std::cout<<"Length: " <<std::endl;
	std::cout<<db.length()<<std::endl;
	
	std::cout<<"Enter 1 pass: " <<std::endl;
	std::cin>>str;
	db.edit_pass(str, 1);
	
	std::cout<<"Length:" <<std::endl;
	std::cout<<db.length()<<std::endl;
	std::cin.get();
	std::cin.get();
	

	return 0;
}
	
	
	


Share this post


Link to post
Share on other sites
Quote:
Original post by Gylis
I am back again... Sadly... My little program isn't working as intended.
It's supposed to read few strings and store them nicely into a file allowing some sort of random access after that. And this is where it gets nasty. Firstly, Database.crpt WILL NOT be created automatically and program will work only if file is created manually.


Don't open your "output" file for both output and input. Open it only for output, since that's what you'll be doing with it. (Trying to read to and write from the same file at once tends not to work very reliably anyway.)

Also, keeping stream objects as data members of a class is usually a bad idea. What you should probably do is store the file name, and keep file data in memory; in the constructor of the object, open a local-variable ifstream, read the file and store the data; in the destructor, open a local-variable ofstream (for that same file) and output the data. That way, the reading and writing is automatically performed and your calling code doesn't have to remember about it.
You can also keep the data in a more easily manipulated structure in-memory.

If you want an actual database (with querying and so forth) on the other hand, use an actual database.

Quote:
Secondly, it writes something about iterators into my file where it is supposed to be whitespace!


Try flushing your written data (e.g. the blank data written by create_record()) before you try to read it or overwrite it.

Quote:
The last, but not the least is numbers returned by ofile.tellp(), in program output, lines "Records creation 1, 2" it prints 400, 200. Shouldn't it be 200, 400? I think that's all.


The two function calls are allowed, by the language standard, to be made in any order. What's happening for you is that the second one in your code is executed first, putting the 200 value in the second "slot" of your output. You need to break it up into two statements to make that work.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this