| Author |
Message |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Sun 04 Oct 2009, 12:02 Post subject:
C++ database coding attempt Subject description: was: C++ reading an object - eh - how |
|
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: | #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;
} |
_________________ Puppy WIKI
Last edited by Lobster on Tue 06 Oct 2009, 22:36; edited 1 time in total
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Tue 06 Oct 2009, 03:45 Post subject:
|
|
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 WIKI
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Tue 06 Oct 2009, 15:15 Post subject:
|
|
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: | #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 WIKI
|
|
Back to top
|
|
 |
tronkel

Joined: 30 Sep 2005 Posts: 1059 Location: Vienna Austria
|
Posted: Tue 06 Oct 2009, 16:58 Post subject:
|
|
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:
| Quote: | //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
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Tue 06 Oct 2009, 22:34 Post subject:
|
|
| Quote: | | 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 WIKI
|
|
Back to top
|
|
 |
tronkel

Joined: 30 Sep 2005 Posts: 1059 Location: Vienna Austria
|
Posted: Wed 07 Oct 2009, 14:40 Post subject:
|
|
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:
| Quote: | | g++ -g contact.cpp main.cpp |
main.cpp
| Quote: | #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
| Quote: | #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
| Quote: | #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
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Wed 07 Oct 2009, 15:25 Post subject:
|
|
studying it - creating external class is useful
many thanks
_________________ Puppy WIKI
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Wed 07 Oct 2009, 20:57 Post subject:
|
|
| Quote: | | 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 WIKI
|
|
Back to top
|
|
 |
tronkel

Joined: 30 Sep 2005 Posts: 1059 Location: Vienna Austria
|
Posted: Thu 08 Oct 2009, 02:56 Post subject:
|
|
@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
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Thu 08 Oct 2009, 03:53 Post subject:
|
|
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 WIKI
|
|
Back to top
|
|
 |
tronkel

Joined: 30 Sep 2005 Posts: 1059 Location: Vienna Austria
|
Posted: Thu 08 Oct 2009, 06:51 Post subject:
|
|
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
|
|
Back to top
|
|
 |
tronkel

Joined: 30 Sep 2005 Posts: 1059 Location: Vienna Austria
|
Posted: Fri 09 Oct 2009, 11:48 Post subject:
|
|
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
_________________ Life is too short to spend it in front of a computer
Last edited by tronkel on Tue 13 Oct 2009, 16:12; edited 1 time in total
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Fri 09 Oct 2009, 12:13 Post subject:
|
|
I | Quote: | | '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 WIKI
|
|
Back to top
|
|
 |
Lobster
Official Crustacean

Joined: 04 May 2005 Posts: 15109 Location: Paradox Realm
|
Posted: Sun 11 Oct 2009, 23:15 Post subject:
|
|
| Quote: | | 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 WIKI
|
|
Back to top
|
|
 |
BarryK
Puppy Master

Joined: 09 May 2005 Posts: 6866 Location: Perth, Western Australia
|
Posted: Mon 12 Oct 2009, 04:06 Post subject:
|
|
| Lobster wrote: | | Quote: | | 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.
_________________ http://bkhome.org/blog2/
|
|
Back to top
|
|
 |
|