C++ database coding attempt

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

C++ database coding attempt

#1 Post by Lobster »

I taught everything I knew about C++ (just above zero) to my programming buddy Shadow.
I don't think he has programmed in C++ before
but soon we had hacked the below program together
It writes an object to a file
but we can not seem to read it in as an object?

any help welcome :)

The idea is to eventually marry this with other work
on pbase which we started some time ago

Code: Select all

#include <fstream>
#include <iostream>  
using namespace std;  

class person {  
	protected: string name, fname; short age;
	
	public: string getFileName() {
		fname = name; 
		fname.append(".dat"); 
		return fname;
	}

	public: string getName() {
		return name;
	}
	          
	public: void getData(){  
		cout << "Enter name: "; cin >> name;  
		cout << "Enter age: "; cin >> age; 
    }  
};


int main() {
	//person newPerson;   
	//newPerson.getData();
	//char filename[80]; 
	//strcpy(filename, newPerson.getFileName().c_str());
	//ofstream outfile(filename, ios::binary);  
	//outfile.write(reinterpret_cast<char*>(&newPerson), sizeof(newPerson));
	
	char filename[80];
	cout << "Enter filename to read: "; cin >> filename;
	person oldPerson;  
	ifstream infile(filename, ios::binary);
	infile.read(reinterpret_cast<char*>(&oldPerson), sizeof(oldPerson));
	//cout << oldPerson.getName();
		
	return 0;
}
Last edited by Lobster on Wed 07 Oct 2009, 02:36, edited 1 time in total.
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#2 Post by Lobster »

:D Using emergency rations of sardines
we managed to solve this problem . . .
(Shadow did the programming, I tried to comprehend it)

So now we can write and read a potential database
Next stop vectors
- which I have a feeling are not vegetarian doctors

:)
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#3 Post by Lobster »

OK here is the code so far
(console database pre alpha for Puppy)
the 'add' option is the only one implemented
and we are getting a segmentation error
- any clues on curing that?

Code: Select all

#include<iostream>
#include<fstream>
#include<vector>
#include<string>
using namespace std;

class Person {
	string field[3]; 
	//vector<string> field;
	
	public:
	Person(){}
	Person(string n, string a, string e) {field[0] = n; field[1] = a; field[2] = e;}
	Person(string f[3]) {field[0] = f[0]; field[1] = f[1]; field[2] = f[2];}
	~Person(){}
	
	void SetValue(int id,string n) {field[id] = n;}
	string GetValue(int id) {return field[id];}
};

class PersonCollection {
	vector<Person> PersonsList;
	
	public:
	PersonCollection(){}
	~PersonCollection(){PersonsList.clear();}
	
	void Add(Person p) {PersonsList.push_back(p);}
	int Size() {return PersonsList.size();}
	Person Item(int i) {return PersonsList[i];}
	int compare(int id,Person p1,Person p2) {if(p1.GetValue(id) > p2.GetValue(id)) return 1;if(p2.GetValue(id) > p1.GetValue(id)) return 2;return 0;}
	
	void Sort(){
		Person tmp;
		for(int i=0;i<Size();i++) {
			for(int j=0;j<Size()-1-i;j++) {
				if(compare(0,PersonsList[j],PersonsList[j+1]) == 1) {
					tmp = PersonsList[j];
					PersonsList[j] = PersonsList[j+1];
					PersonsList[j+1] = tmp;
				}
			}
		}	
	}
	Person Find(int id, string s){
		for(int i=0;i<Size();i++) {
			if(PersonsList[i].GetValue(id).compare(s) == 0) return PersonsList[i];
		}
		return Person();
	}

};

class PersonFileProcessor {
	char* file;
	public:
	PersonFileProcessor(char* f) {file = f;}
	~PersonFileProcessor(){}
	
	void Save(PersonCollection addressbook) {
		ofstream out(file, ios::app); 
		out.write((char*) &addressbook, sizeof(addressbook));
		out.close();
	}
	
	PersonCollection Read() {
		PersonCollection addressbook;
		ifstream in(file);
		in.read((char*) &addressbook, sizeof(addressbook));
		in.close();	
		return addressbook;	
	}	

};

int main(int argc, char *argv[])
{
	system("clear");
	
	PersonFileProcessor pp((char*)"Address.dat");
	
	string name, address, email, inputmenu;
		cout << "A=Add Records F=Find Records S=Search Records T=Table Display" << endl; cin >> inputmenu;
		if(inputmenu == "A" || inputmenu == "a")
			{
		cout << "Enter Name:" << endl; cin >> name;
		cout << "Enter Address:" << endl; cin >> address;
		cout << "Enter Email Address:" << endl; cin >> email;
		PersonCollection addressbook; 
	  Person p1(name, address, email);
	  addressbook.Add(p1);
	  pp.Save(addressbook);	
			 }
			 if(inputmenu == "F" || inputmenu == "f")
			{
				cout << "Search for name:" << endl; cin >> name;
				PersonCollection addressbook = pp.Read();
				cout << "Size:" << addressbook.Size() << endl; 
				Person p1 = addressbook.Find(0,name);
				cout << "Name:" << p1.GetValue(0) << endl; 
				cout << "Address:" << p1.GetValue(1) << endl; 
				cout << "Email:" << p1.GetValue(2) << endl; 
		}
	
	return 0;
}
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#4 Post by tronkel »

Gosh that's a valiant attempt - but in order to write a database of Person objects and store them in a list, you really could make more use of the STL and its very useful iterator classes rather than attempting to do stuff in the old-fashioned slow way using char * etc. STL <string> is also much less error-prone than char *. Confirmed by Bjarne Stroustrup, the creator of C++

Yes, I know that kernel space specialists frown on using C++ inside the kernel itself, but in user space it is a god-send for stuff like hacking together databases.

For storing the Person list, I would go for an STL <list> rather than the <vector> as used here. <list> while maybe being a tad less efficient in theory, is more robust in practice than the likes of <vector>

You can grab a <list> iterator thus:
//declare and initialise the list iterator
list<Person>::iterator li=personList.begin();

//loop through the personList until you find what you are looking for:

for(;li !=personList.end();i++)
{
//your search code goes here
}
You could use serialisation to store you objects to hard disk. This is really the best way to do it, but for this relatively simple structure, a text file containing lines of text strings is maybe the best compromise here.

The main menu would be better implemented using the switch statement- again less error-prone.

I'll try to cobble some code together at the weekend. In the meantime, read up on the above techniques in say Deitel and Deitel.
Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#5 Post by Lobster »

Gosh that's a valiant attempt
Thanks Jack :)
Appreciate very much the comments.
We (Shadow + Lobster making tea) are very grateful.
Basically 80% of the time is spent looking for samples on the web, which then somehow
- only his third day programming in C++ Shadow manages to tweak, modify and improve . . .

We may well go from vector to list
- we did consider using 'map' but dropped that
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#6 Post by tronkel »

Ok Ed, here is a start on your Contacts Database.
Copy the code from here into three correspondingly named files and stick them into a folder on your system

Open a terminal in that folder and compile the project with the command:
g++ -g contact.cpp main.cpp
main.cpp
#include "contact.h"
#include <iostream>

using namespace std;

int main()
{
//temporary code for testing Contact class
Contact newcontact("Lobster", "fishtank", "carp@tank.com");
cout << newcontact.returnName() << endl;
cout << newcontact.returnAddress() << endl;
cout << newcontact.returnEmail() << endl;

return 0;

// todo:
// create a file controller class that saves and loads data at program startup
// best place for loading data is the constructor for a main program object
// create a main database class that holds a list of contacts. Use an STL list<Contact> object for this
// code the database search function (using a list<Contact>::iterator)
// create a user menu



}
contact.h
#ifndef CONTACT_H
#define CONTACT_H

#include <string>
using namespace std;


class Contact
{//class definition for Contact object

private:

string name;
string address;
string email;

public:

Contact(); //default constructor
Contact(string, string, string); //parameterised constructor

string returnName();
string returnAddress();
string returnEmail();






};

#endif
contact.cpp
#include "contact.h"
#include <string>

using namespace std;


Contact::Contact()
{ }

Contact::Contact(string aname, string anaddress, string anemail)
{// definition of Contact object constructor

name=aname;
address=anaddress;
email=anemail;

}


string Contact::returnName()
{
return name;

}


string Contact::returnAddress()
{
return address;

}


string Contact::returnEmail()
{
return email;

}
Study this code. Sequel to follow at the weekend!
Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#7 Post by Lobster »

studying it - creating external class is useful :)
many thanks
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#8 Post by Lobster »

g++ -g contact.cpp main.cpp
I am assuming -g 'groups' the two files into one run time but I can find no reference to it on google?
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#9 Post by tronkel »

@Ed

The -g option for has nothing to do with grouping the files to be compiled.


The -g option for g++ tells the compiler to build an executable that contains/includes degugging information. This is necessary in case you need to run the GNU debugger called GDB on your source code in the event of having bugs that are difficult to track down.

Once the final version of the program has been built and tested, you can then recompile the project without the -g option and thereby have a smaller executable - i.e. without the superfluous degugging information.
Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#10 Post by Lobster »

Thanks Jack

We did use the debugger from the command line
(when we got the segmentation fault)
but could not make much from the data created

:)
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#11 Post by tronkel »

The debugger is only of use in certain circumstances. You need to learn to use the debugger in conjunction with setting watch expressions as well.

There a several good tools available in Puppy that can help. There is a version of Emacs for Puppy available as a pet package somewhere in the forum. This allows you to edit your code and debug it in the same window.

Not sure about Geany - I don't think it can do that.
Other tools are Codeblocks and Netbeans (needs Java though).

There is also an sfs for Anjuta as well that would be suitable
Life is too short to spend it in front of a computer

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#12 Post by tronkel »

Hi Ed,

I've just been looking at that original C++ code you posted here.
After I added #include <stdlib.h> it compiled fine.

Tried adding a few records and that seemed to work OK - but when I tried to do a search, it bombed straight out as if it was unable to access the file properly.

On studying that code, whoever wrote it. has used the in.Read() way of doing things that I have never used much in the past. I have a feeling that this function cannot retrieve type information - i.e. only data information using this method. This would certainly make it crash. Would be an interesting task to fix this, but this would mean having to alter the program somewhat.

I'll play with this original code some more and also enhance the program to do searching etc. using a purely STL method as originally suggested.

Keep going with it.

Jack
Last edited by tronkel on Tue 13 Oct 2009, 20:12, edited 1 time in total.
Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#13 Post by Lobster »

I
've just been looking at that original C++ code you posted here.
Thanks Tronkel

Shadow did some minor mods - added your list ideas :)
but we won't be doing any coding until Monday
(Shadow is on holiday - his job is MS programmer)

Anyways any improvements and suggestions welcome

:)
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#14 Post by Lobster »

Other tools are Codeblocks and Netbeans (needs Java though)
I added the 'LXRAD GUI' from the puppy package manager in 4.3.1 release cndidate. When I looked at this previously it was completely unstable but may have been improved/recompiled. Anyway that seems sufficient to what we may need in the future. :)
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
BarryK
Puppy Master
Posts: 9392
Joined: Mon 09 May 2005, 09:23
Location: Perth, Western Australia
Contact:

#15 Post by BarryK »

Lobster wrote:
Other tools are Codeblocks and Netbeans (needs Java though)
I added the 'LXRAD GUI' from the puppy package manager in 4.3.1 release cndidate. When I looked at this previously it was completely unstable but may have been improved/recompiled. Anyway that seems sufficient to what we may need in the future. :)
Nah, it's the same old Lxrad PET package. I haven't looked at it since I did so originally. As I recall, it had bugs.

The author stated that he was bewildered by GTK libs and was going to move Lxrad to using Wxwidgets, but I don't know if that ever happened, or even if he did anything more on the Lxrad project.
[url]https://bkhome.org/news/[/url]

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#16 Post by Lobster »

As I recall, it had bugs.
OK - will bear that in mind. It is a shame it is buggy because generating the GUI was very straightforward.
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#17 Post by tronkel »

@ed

Here is the latest C++ code for the contacts database
Add, delete, search and list all contacts have been implemented

It uses an STL list<Contacts> as the main data structure
You could play around and have a go with a vector or map. Trouble with vectors are that it is difficult to access them in the middle if you need to insert or delete something. It can be done but it's a lot of bother and very error-prone. Much the same as with a C-style array.

The map though is a better idea. It uses a red-black binary tree as its base container and is therefore lightning fast on search and insert. You can also quite easliy make your own binary tree, but there is no specific STL version i.e. you would need to write it yourself.

Instead of using in.read() and out.write() this code implements an overloaded operator for << and >> that allows input and output of entire objects direct to and from disk file.

Here's the code:

contact.h
#ifndef CONTACT_H
#define CONTACT_H

#include <string>
#include <iostream>
#include <fstream>
#include <list>
using namespace std;


class Contact
{//class definition for Contact object

friend ofstream & operator<<(ofstream &, Contact &);
friend ifstream & operator>>(ifstream &, Contact &);

private:

string name;
string address;
string email;

public:

Contact(); //default constructor
Contact(string, string, string); //parameterised constructor
string returnName();
string returnAddress();
string returnEmail();
void setName(string);
void setAddress(string);
void setEmail(string);








};

#endif
main.cpp

#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include "contact.h"
#include <stdlib.h>
#include <cctype>


using namespace std;

//globals
//forward declarations of menu functions

void quit(list<Contact> alist);
Contact makeContact(list<Contact> & alist);
void search(list<Contact> alist);
Contact displayMenu();
void initdata();
void kill();
void listall(list<Contact> alist);

list<Contact> mainlist; // this structure holds the main list of contacts


int main()
{


initdata(); //load data from file and display user menu


}


void quit(list<Contact> alist)
{// quit and save changes to disk
ofstream output;
output.open("lob");

list<Contact>::iterator li=alist.begin();
for(;li!=alist.end();li++)
{
output << *li;

}

output.close();

}

Contact makeContact(list<Contact> & alist)
{// ask user for details of new contact
string name,address,email;

cout << "Please enter a name" << endl;
getline(cin,name);
cout << "Please enter an address" << endl;
getline(cin,address);
cout << "Please enter an email address" << endl;
getline(cin,email);
Contact newcontact(name,address,email);
alist.push_back(newcontact); //insert into mainlist
quit(mainlist);//save back to disk
return newcontact;
}

void search(list<Contact> alist)
{//search mainlist based on name

system("clear");
string term="";
cout << "please enter name" << endl;
getline(cin,term);
list<Contact>::iterator ali;
ali=alist.begin();
for(;ali!=alist.end();ali++)
{
if(ali->returnName()==term)
{
cout << "Your search has returned the following record(s) >> " << endl << endl;
cout << "name: " << ali->returnName() << endl;
cout << "address: " << ali->returnAddress() << endl;
cout << "email: " << ali->returnEmail() << endl << endl;

}

}

getchar();
}

Contact displayMenu()
{

int choice;
Contact acontact;

do{//this loop redraws menu unless quit is selected

cin.clear();
system("clear");
cout << "Welcome to Lobster's Database!" << endl << endl;
cout << "YOU HAVE " << mainlist.size() -1 << " CONTACTS IN YOUR DATABASE" << endl << endl;
cout << "enter your choice >>" << endl;

cout << "1. Add contact" << endl;
cout << "2. List all contacts" << endl;
cout << "3. Search for a contact" << endl;
cout << "4. Delete a contact" << endl;
cout << "5. Quit" << endl;


cin >> choice;
cin.ignore();
if(choice < 1 || choice > 5 )
{
cout << "you must select a NUMBER from the menu list" << endl;
exit(1);
}




switch(choice)
{
case 1: makeContact(mainlist);
break;
case 2: listall(mainlist);
break;
case 3: search(mainlist);
break;
case 4: kill();
break;
case 5: quit(mainlist);
break;
}

}while(choice!=5); //end of do loop

return acontact;



}

void initdata()
{
ifstream input;
input.open("lob");


while(input.good() )
{//recover saved data from disk file and insert into mainlist
Contact acontact;
input >> acontact;

mainlist.push_back(acontact);
}

input.close();


displayMenu(); //show main menu

}

void kill()
{
string temp="";
char ans='z';
list<Contact>::iterator xi;
cout << "This action will permanently delete a selected contact from your database!" << endl;
cout << "name of contact to delete >> " << endl;
getline(cin,temp);
cout << "Are you sure? enter y or n" << endl;
ans=getchar();
cin.ignore();
if(ans=='Y'||ans=='y')
{
xi=mainlist.begin();
for(;xi!=mainlist.end();xi++)
if(xi->returnName()==temp)
{
mainlist.erase(xi);
cout << "contact " << temp << " has been deleted from your list of contacts" << endl << endl;
cout << "Press enter to exit" << endl;
getchar();
quit(mainlist);
return;
}
}

else
cout << "deletion of contact " << temp << " aborted" << endl << endl;
cout << "Press enter to exit" << endl;
getchar();


}

void listall(list<Contact> alist)
{
cout <<"Your list of all contacts: " << endl <<endl;
list<Contact>::iterator li=alist.begin();
for(;li!=alist.end();li++)
{

cout << li->returnName() << endl;
cout << li->returnAddress() << endl;
cout << li->returnEmail() << endl << endl;

}
cout << "Press enter to exit. Have a nice day 8-)" << endl;
getchar();


}
contact.cpp

//#include "toplevel.h"
#include <string>
#include <fstream>
#include <list>
#include "contact.h"

using namespace std;


Contact::Contact()
{ } //default ctor

Contact::Contact(string aname, string anaddress, string anemail)
{// definition of Contact object constructor

name=aname;
address=anaddress;
email=anemail;

}

string Contact::returnName()
{
return name;

}


string Contact::returnAddress()
{
return address;

}


string Contact::returnEmail()
{
return email;

}

void Contact:: setName(string name)
{
this->name=name;
}

void Contact:: setAddress(string address)
{
this->address=address;
}

void Contact:: setEmail(string email)
{
this->email=email;
}

ofstream & operator<<(ofstream & output, Contact & acontact)
{//def of overloaded << operator


output << acontact.returnName() << "\n"
<< acontact.returnAddress() << "\n"
<< acontact.returnEmail() << "\n";
}

ifstream & operator>>(ifstream & input, Contact & acontact)
{
string name,address,email;
input >> name >> address >> email ;

acontact.setName(name);
acontact.setAddress(address);
acontact.setEmail(email);

}

Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#18 Post by Lobster »

Here is the latest C++ code for the contacts database
will have a look soon
must go into the real world
(just to make sure it is still there . . .)
be right back . . .
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

User avatar
tronkel
Posts: 1116
Joined: Fri 30 Sep 2005, 11:27
Location: Vienna Austria
Contact:

#19 Post by tronkel »

Lobster wrote:
must go into the real world
(just to make sure it is still there . . .)
The real world ?????
What is it!

If you find anything worth knowing about, please let me know! I went there once, but that was so long ago I've forgotten what it was like.

You mean there are actually OTHER people out there????

I've also been informed though, that there are people out there who don't just sit at their PC's all day. What do they do all day I wonder?

Be careful out there. They say it can be fun but VERY dangerous! Would like to hear of any interesting real-world activities (if such things exist).
Life is too short to spend it in front of a computer

User avatar
Lobster
Official Crustacean
Posts: 15522
Joined: Wed 04 May 2005, 06:06
Location: Paradox Realm
Contact:

#20 Post by Lobster »

Image
Where I went mostly trees and sky and such like . . . stuff
Nice day . . . and now back to the virtual world
OK got the program working now playing :)
:)
Puppy Raspup 8.2Final 8)
Puppy Links Page http://www.smokey01.com/bruceb/puppy.html :D

Post Reply