B
BobR
(e-mail address removed) wrote in message ...
OK. Eliminated another 'possible'.
I'll snip most of your code below to reduce bandwith, but, I'll check it out
later.
I don't think it will be too bad. I'll show you a little 'helper' further
down.
That's what I was drifting toward. A std::vector can hold objects, but then
you would definitely need a proper copy constructor (assuming you are still
using (an array of) pointers.
OK, nothing so far requires the copy constructor or assignment. Clean.
vector<File*> vFiles;
If you do it like this (different name), you can develop it in parallel with
your existing code (just an idea).
I haven't finished reviewing your code, but I don't remember seeing this
used.
So it's your(his) 'style' choice. That's fine. I'd say 'documentation', but
that
would be more typeing, and save nothing. Just so you know it.
Here's that 'helper' I mentioned.
template<class Seq> void EmptyThis( Seq &con ){
for( class Seq::iterator i( con.begin() ); i != con.end(); ++i ){
delete *i;
*i = 0; // in case it gets called again
}
// >> delete Directories.at( i );
// >> }
EmptyThis( Directories );
Yeah, I know, "I can't use templates!!". Well, your stuck using 'concrete'
functions then.
void EmptyThis( std::vector<Directory*> &con ){
for( std::vector<Directory*>::iterator i( con.begin() );
i != con.end(); ++i ){
delete *i;
*i = 0; // in case it gets called again
}
} // EmptyThis( std::vector<Directory*> &)
If you put that in class, you won't need the '*i=0' since you will call it
from the destructor, and when the destructor us done the object no longer
exists.
Using the template version, and vector vFiles, you could have used it like:
EmptyThis( vFiles );
EmptyThis( Directories );
No biggie, what ever you choose to use.
That's where the copy constructor comes into play. When you push_back(), it
makes a copy of the object. So, there's no problem when the temp disappears.
Good. You could also use an std::istringstream to simulate input.
std::istringstream scin("word word2 morewords etc.\n anotherword\n");
std::string temp;
scin >> temp;
Your way is fine, just pointing out another option.
(would save a file open)
Correct. I forgot for a minute (good excuse, eh.) that it was a container of
pointers. But, I did mention that 'predicate' may be needed (nice save, eh?
<G>).
That might look something like:
bool predicate(const Directory *X, const Directory *Y)
{ return ( (*X)->name < (*Y)->name); }
std::sort( Directories.begin(), Directories.end(), predicate);
[ I don't have much practice with 'predicates', so, that may need some
adjustments. <G> ]
If you want to go that way, and have trouble, just start a new thread on that
subject. Some of the experts in this NG are really good at that (predicates).
Directory *Parent?
bool Directory:perator==(const string &D){
return ( Name == D );
}
Another point, It could have been:
bool Directory:perator==(const string & D){
if(Name != D)
return false; // it leaves the function.
return true;
}
You could simplify it:
bool Directory:perator<( Directory const &D ){
// both names are strings so this should work.
return ( Name < D.Name );
}
Inside the if()s, you are resolving an expression to a bool, and then
returning true or false upon the condition. Eliminate the middle man
( if() ).
bool Directory::Empty(){
return ( (NumSubDirs == 0) && (NumFiles == 0) );
}
// etc.
Well, ya gotta kiss-up or lose the grade! The more you code, the more you'll
develop your own style. Hopefully you'll lose the bad habits, and develop
good ones after you *pass* the course.
Neither! Unemployed (due to partial disability, and staying off welfare
(anybody out there have a home freelance C++ programming job for me? <G> $1 a
kloc?)). My favorite computer games are Adventure. C++ is like playing them,
I like problem solving/puzzles.
I've seen things like that in GNU/Linux, but never been interested enough to
investigate. win98 is the last ms thing I'll use, If my next machine build
won't run win98, I'll go pure Debian GNU/Linux. Maybe ask on an ms NG.
[ anybody else out there hard core enough to do a Linux kernel using g++
3.x.x (4.x?) ?]
[ ...and yeah, it works.]
Actually my QuickSort works. I had to overload operators for it to do
so, but it seems to be fine.
OK. Eliminated another 'possible'.
I'll snip most of your code below to reduce bandwith, but, I'll check it out
later.
I know. And I think the destructor is going to be a pain too. I think I
will have to loop through the array and delete each pointer to each
file.
I don't think it will be too bad. I'll show you a little 'helper' further
down.
The problem that this solves? is that I need to be able to 'loop' and
create a new object multiple times. I don't know how to do that except
with a pointer; as in
x = new file.
Also if I 'hard-coded' file x, then it would go out of scope and be
deleted at the end of the function even if I put it into a public array
would it not?
That's what I was drifting toward. A std::vector can hold objects, but then
you would definitely need a proper copy constructor (assuming you are still
using (an array of) pointers.
Umm... it did work actually. Here is the 'new' header:
OK, nothing so far requires the copy constructor or assignment. Clean.
***********************************************************
#ifndef Directory_h
class Directory{ private:
// Prevent assignment and copy-construction:
Directory( Directory const & ); // just this, don't define it.
void operator=( Directory const & );
string Name; // Name of the Directory
unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
int Level;
File *Files; //Pointer to an array of Files
vector<File*> vFiles;
If you do it like this (different name), you can develop it in parallel with
your existing code (just an idea).
vector<Directory*> Directories; // vector to pointers to directories
Directory *Parent; // pointer to this directories parent dir
I haven't finished reviewing your code, but I don't remember seeing this
used.
Directory(Directory *Parent, string N);
Parent?
The prof is big on seeing those words though. It does make it clearer too.
So it's your(his) 'style' choice. That's fine. I'd say 'documentation', but
that
would be more typeing, and save nothing. Just so you know it.
Yup. A big nasty one. I will have to loop through and delete each File
from the array, then the array. Big pain, but I think that's the point.
Here's that 'helper' I mentioned.
template<class Seq> void EmptyThis( Seq &con ){
for( class Seq::iterator i( con.begin() ); i != con.end(); ++i ){
delete *i;
*i = 0; // in case it gets called again
}
// >> for( size_t i(0); i < Directories.size(); ++i ){} //template said:Directory::~Directory(){
delete[] Files;
// and since your vector holds pointers to 'new' objects.
// >> delete Directories.at( i );
// >> }
EmptyThis( Directories );
Yeah, I know, "I can't use templates!!". Well, your stuck using 'concrete'
functions then.
void EmptyThis( std::vector<Directory*> &con ){
for( std::vector<Directory*>::iterator i( con.begin() );
i != con.end(); ++i ){
delete *i;
*i = 0; // in case it gets called again
}
} // EmptyThis( std::vector<Directory*> &)
If you put that in class, you won't need the '*i=0' since you will call it
from the destructor, and when the destructor us done the object no longer
exists.
Using the template version, and vector vFiles, you could have used it like:
EmptyThis( vFiles );
EmptyThis( Directories );
No biggie, what ever you choose to use.
How can I dynamically create actual objects though? They do go out of
scope at the end of the function don't they?
That's where the copy constructor comes into play. When you push_back(), it
makes a copy of the object. So, there's no problem when the temp disappears.
The sort for the vector however does not seem to. In fact I cannot see
it changing anything.
I added code to read a comma delimited file with a bunch of random
words in it. I use that to create directories (who wants to type all
that!) the vector sort is given at the end of each addition, I then
list the directory and the files come back out in the order they went
in.
Good. You could also use an std::istringstream to simulate input.
std::istringstream scin("word word2 morewords etc.\n anotherword\n");
std::string temp;
scin >> temp;
Your way is fine, just pointing out another option.
(would save a file open)
My suspicion is that they are sorted by the pointer, not the thing
pointed to. I am looking at that but....
Correct. I forgot for a minute (good excuse, eh.) that it was a container of
pointers. But, I did mention that 'predicate' may be needed (nice save, eh?
<G>).
That might look something like:
bool predicate(const Directory *X, const Directory *Y)
{ return ( (*X)->name < (*Y)->name); }
std::sort( Directories.begin(), Directories.end(), predicate);
[ I don't have much practice with 'predicates', so, that may need some
adjustments. <G> ]
If you want to go that way, and have trouble, just start a new thread on that
subject. Some of the experts in this NG are really good at that (predicates).
here is the new cpp file, it has changed a little to accomodate things
like automated directory addition.
********************************* [snip]
Directory:irectory(Directory *Parent, string N){
Directory *Parent?
Name = N;
NumSubDirs = 0;
NumFiles = 0;
MaxSubDirs = 5;
MaxFiles = 5;
Level = -1;
Directories.clear();
Files = new File[MaxFiles];
}
/* operator== */
bool Directory:perator==(const string & D){
if(Name != D)
return false;
else
return true;
}
bool Directory:perator==(const string &D){
return ( Name == D );
}
Another point, It could have been:
bool Directory:perator==(const string & D){
if(Name != D)
return false; // it leaves the function.
return true;
}
bool Directory:perator<(const Directory & D){
// both names are strings so this should work.
//if the Directory Name is >, then false
if(Name > D.Name)
return false;
//if the Directory Name is <, then true
if(Name < D.Name)
return true;
}
You could simplify it:
bool Directory:perator<( Directory const &D ){
// both names are strings so this should work.
return ( Name < D.Name );
}
Inside the if()s, you are resolving an expression to a bool, and then
returning true or false upon the condition. Eliminate the middle man
( if() ).
//Empty()
bool Directory::Empty(){
if(NumSubDirs == 0 && NumFiles == 0)
return true;
else
return false;
}
bool Directory::Empty(){
return ( (NumSubDirs == 0) && (NumFiles == 0) );
}
// etc.
************************************************
Oh; a comment on the std:: - the teaching assistant seems to favour NOT
using std:: so that's the way I will go for now. He's got to mark it.
Best to keep it to what he likes.
Well, ya gotta kiss-up or lose the grade! The more you code, the more you'll
develop your own style. Hopefully you'll lose the bad habits, and develop
good ones after you *pass* the course.
By the way... are you independantly wealthy or just very generous with
your time??
Neither! Unemployed (due to partial disability, and staying off welfare
(anybody out there have a home freelance C++ programming job for me? <G> $1 a
kloc?)). My favorite computer games are Adventure. C++ is like playing them,
I like problem solving/puzzles.
Also; is there a way to get the system to email me if there is a reply?
I've seen things like that in GNU/Linux, but never been interested enough to
investigate. win98 is the last ms thing I'll use, If my next machine build
won't run win98, I'll go pure Debian GNU/Linux. Maybe ask on an ms NG.
[ anybody else out there hard core enough to do a Linux kernel using g++
3.x.x (4.x?) ?]
[ ...and yeah, it works.]