create a dynamic array of pointers with initial values of NULL

Discussion in 'C++' started by sandy@murdocks.on.ca, Nov 28, 2006.

  1. Guest

    I need (okay, I want) to make a dynamic array of my class 'Directory',
    within my class Directory (Can you already smell disaster?)

    Each Directory can have subdirectories so I thought to put these in an
    array. The application compiles but aborts without giving me any useful
    information.

    What I suspect is happening is infinite recursion. Each Directory
    object creates an array of Subdirectories each of which has an array of
    sub-directorires...

    I think it basically is recursively killing itself.

    Is there some way to declare this array so that the values are NULL
    initially? Thus (I think) doing away with the recursion problem. Then
    as I add ACTUAL sub-directories it should work. As I delete
    Sub-directories I take the array item and set it to NULL... or so my
    theory goes.

    currently in my header I declare my array like this:

    Directory *Directories; // pointer to an array of Directories

    and I had been instantiating it like this in my .cpp file:

    Directories = new Directory[MaxSubDirs];

    is there some way to automatically set the values to NULL? I can't loop
    because it has already died by then. I need something in the order of
    (of course this does not work)

    Directories = new Directory[MaxSubDirs] = NULL;

    I realize that I should be able to do the same thing with a linked
    list, but I think that using the array will be faster (if it is
    possible) due to the date the assignment is due.

    Did I mention I am a student? I am a student.

    Thanks.
     
    , Nov 28, 2006
    #1
    1. Advertising

  2. Guest

    Oops. My subject is incorrect, I want to create a dynamic array of my
    class Directory, within my class Directory.
     
    , Nov 28, 2006
    #2
    1. Advertising

  3. mlimber Guest

    wrote:
    > I need (okay, I want) to make a dynamic array of my class 'Directory',
    > within my class Directory (Can you already smell disaster?)
    >
    > Each Directory can have subdirectories so I thought to put these in an
    > array. The application compiles but aborts without giving me any useful
    > information.
    >
    > What I suspect is happening is infinite recursion. Each Directory
    > object creates an array of Subdirectories each of which has an array of
    > sub-directorires...
    >
    > I think it basically is recursively killing itself.
    >
    > Is there some way to declare this array so that the values are NULL
    > initially? Thus (I think) doing away with the recursion problem. Then
    > as I add ACTUAL sub-directories it should work. As I delete
    > Sub-directories I take the array item and set it to NULL... or so my
    > theory goes.
    >
    > currently in my header I declare my array like this:
    >
    > Directory *Directories; // pointer to an array of Directories
    >
    > and I had been instantiating it like this in my .cpp file:
    >
    > Directories = new Directory[MaxSubDirs];
    >
    > is there some way to automatically set the values to NULL? I can't loop
    > because it has already died by then. I need something in the order of
    > (of course this does not work)
    >
    > Directories = new Directory[MaxSubDirs] = NULL;
    >
    > I realize that I should be able to do the same thing with a linked
    > list, but I think that using the array will be faster (if it is
    > possible) due to the date the assignment is due.
    >
    > Did I mention I am a student? I am a student.


    Use std::vector, std::set or std::list:

    class File;

    class Directory
    {
    Directory& parent_;
    std::string name_;
    std::set<File> files_;
    std::set<Directory> subdirs_;
    public:
    Directory( const Directory& parent, const std::string& name )
    : parent_( parent )
    , name_( name )
    , files_()
    , subdirs_()
    {}

    void AddDir( const std::string& name )
    {
    subdirs_.insert( Directory( *this, name ) );
    }

    // ...
    };

    Cheers! --M
     
    mlimber, Nov 28, 2006
    #3
  4. wrote:
    > I need (okay, I want) to make a dynamic array of my class 'Directory',
    > within my class Directory (Can you already smell disaster?)
    >
    > Each Directory can have subdirectories so I thought to put these in an
    > array. The application compiles but aborts without giving me any
    > useful information.
    >
    > What I suspect is happening is infinite recursion. Each Directory
    > object creates an array of Subdirectories each of which has an array
    > of sub-directorires...
    >
    > I think it basically is recursively killing itself.
    >
    > Is there some way to declare this array so that the values are NULL
    > initially? Thus (I think) doing away with the recursion problem. Then
    > as I add ACTUAL sub-directories it should work. As I delete
    > Sub-directories I take the array item and set it to NULL... or so my
    > theory goes.
    >
    > currently in my header I declare my array like this:
    >
    > Directory *Directories; // pointer to an array of Directories
    >
    > and I had been instantiating it like this in my .cpp file:
    >
    > Directories = new Directory[MaxSubDirs];
    >
    > is there some way to automatically set the values to NULL? [..]


    In the initialiser list:

    ... Directories(new Directory[MaxSubDirs]()) ...

    And consider using std::vector instead, which can also be
    initialised. Imagine that 'Directories' is declared as

    std::vector<Directory*> Directories;

    then you do

    ... Directories(MaxSbDirs, (Directory*)NULL) ...

    (although you don't really need that, vector can grow as
    needed).

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Nov 28, 2006
    #4
  5. Guest

    Thanks for the reply. I may have to try the vectors... we have only
    discussed them in class, not used them.

    Can you explain this a bit:

    Directories(new Directory[MaxSubDirs]());

    I tried it as is and got the error:
    `((Directory*)this)->Directory::Directories' cannot be used as a
    function

    Obviously I don't understand what was meant.

    Victor Bazarov wrote:
    > wrote:
    > > I need (okay, I want) to make a dynamic array of my class 'Directory',
    > > within my class Directory (Can you already smell disaster?)
    > >
    > > Each Directory can have subdirectories so I thought to put these in an
    > > array. The application compiles but aborts without giving me any
    > > useful information.
    > >
    > > What I suspect is happening is infinite recursion. Each Directory
    > > object creates an array of Subdirectories each of which has an array
    > > of sub-directorires...
    > >
    > > I think it basically is recursively killing itself.
    > >
    > > Is there some way to declare this array so that the values are NULL
    > > initially? Thus (I think) doing away with the recursion problem. Then
    > > as I add ACTUAL sub-directories it should work. As I delete
    > > Sub-directories I take the array item and set it to NULL... or so my
    > > theory goes.
    > >
    > > currently in my header I declare my array like this:
    > >
    > > Directory *Directories; // pointer to an array of Directories
    > >
    > > and I had been instantiating it like this in my .cpp file:
    > >
    > > Directories = new Directory[MaxSubDirs];
    > >
    > > is there some way to automatically set the values to NULL? [..]

    >
    > In the initialiser list:
    >
    > ... Directories(new Directory[MaxSubDirs]()) ...
    >
    > And consider using std::vector instead, which can also be
    > initialised. Imagine that 'Directories' is declared as
    >
    > std::vector<Directory*> Directories;
    >
    > then you do
    >
    > ... Directories(MaxSbDirs, (Directory*)NULL) ...
    >
    > (although you don't really need that, vector can grow as
    > needed).
    >
    > V
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
     
    , Nov 29, 2006
    #5
  6. * :
    > [top-posting, overquoting]


    Please don't -- read the FAQ -- corrected.


    * :
    > Thanks for the reply. I may have to try the vectors... we have only
    > discussed them in class, not used them.


    Use them.


    > Can you explain this a bit:
    >
    > Directories(new Directory[MaxSubDirs]());
    >
    > I tried it as is and got the error:
    > `((Directory*)this)->Directory::Directories' cannot be used as a
    > function
    >
    > Obviously I don't understand what was meant.


    You have extranous parentheses, but don't try to correct this: use
    std::vector.


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Nov 29, 2006
    #6
  7. BobR Guest

    wrote in message ...
    >Thanks for the reply. I may have to try the vectors... we have only
    >discussed them in class, not used them.
    >
    >Can you explain this a bit:
    >
    >Directories(new Directory[MaxSubDirs]());
    >
    >I tried it as is and got the error:
    > `((Directory*)this)->Directory::Directories' cannot be used as a
    >function
    >
    >Obviously I don't understand what was meant.


    I think Victor meant for you to use that *in* an initialiser list:

    class Directory{
    static const size_t MaxSubDirs = 5;
    Directory *Directories; // pointer to an array of Directories
    public:
    // - like this -
    Directory() : Directories( new Directory[ MaxSubDirs ]() ) {}

    ~Directory(){ delete[] Directories; }
    };

    Is that the way you tried it?

    Go with the std::vector.

    --
    Bob R
    POVrookie
     
    BobR, Nov 29, 2006
    #7
  8. Guest

    Thanks for all your help.

    I am still trying to figure this out... and maybe I will have to go
    with a linked list. Hard to say.
    Anyway:

    In my header I have this in the private section:

    vector<Directory*> Directories; // pointer to an array of Directories

    and in the cpp file I am trying this (and maybe I shouldn't... more to
    follow):
    Directories.resize[MaxSubDirs];

    which will not compile:
    invalid types `<unknown type>[unsigned int]' for array subscript

    MaxSubDirs is an unsigned int in this case, but I have tried int as
    well.

    With regular arrays one of the issues is what to do when it gets full.
    In order to save time, instead of adding one more slot at a time, we
    use doubling. With Vector I have been reading and I am not clear.

    When I push_back an item, it adds it to the vector and takes space from
    the capacity. When capacity is reached does vector double itself? Add
    1? Do I need to add functions to double the size of my vector the way I
    do my arrays, not because it's the only way to make more space but
    because it is more efficient (time wise) to add many slots at once?

    Notice I have two questions there.

    Thanks for your time.
     
    , Nov 29, 2006
    #8
  9. * :
    > Thanks for all your help.
    >
    > I am still trying to figure this out... and maybe I will have to go
    > with a linked list. Hard to say.
    > Anyway:
    >
    > In my header I have this in the private section:
    >
    > vector<Directory*> Directories; // pointer to an array of Directories


    Make that

    vector<Directory> directories;

    unless you're going to share those objects or use polymorphism.

    But if you need pointers, use e.g.

    typedef boost::shared_ptr<Directory> DirectoryPtr;
    typedef std::vector<DirectoryPtr> DirectoryPtrs;

    DirectoryPtrs directories;

    so that object destruction is taken care of automatically.


    > and in the cpp file I am trying this (and maybe I shouldn't... more to
    > follow):
    > Directories.resize[MaxSubDirs];
    >
    > which will not compile:
    > invalid types `<unknown type>[unsigned int]' for array subscript


    Wrong kind of parenthesis.


    > MaxSubDirs is an unsigned int in this case, but I have tried int as
    > well.
    >
    > With regular arrays one of the issues is what to do when it gets full.
    > In order to save time, instead of adding one more slot at a time, we
    > use doubling. With Vector I have been reading and I am not clear.


    Guaranteed average O(1) for push_back, which essentially means (that
    vector uses internal) doubling or some other factor to increase capacity
    when exceeded.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Nov 29, 2006
    #9
  10. BobR Guest

    wrote in message ...
    >Thanks for all your help.
    >
    >I am still trying to figure this out... and maybe I will have to go
    >with a linked list. Hard to say.
    >Anyway:
    >In my header I have this in the private section:
    >
    >vector<Directory*> Directories; // pointer to an array of Directories
    >
    >and in the cpp file I am trying this (and maybe I shouldn't... more to
    >follow):
    >Directories.resize[MaxSubDirs];


    What Alf said. Try this example, maybe it will clear some cobwebs.
    ( if it don't kill ya first.<G>).
    [ BTW, please do not top-post. (ref: other posts of yours)]

    // --------------------------
    #include <iostream>
    #include <ostream>
    #include <vector>
    // --------------------------
    void PrintVec( std::vector<int> const &vec, std::eek:stream &sout){
    sout<<" size="<<vec.size()<<" cap="<<vec.capacity()<<std::endl;
    return;
    } // PrintVec(vector<int> const&,ostream&)
    // --------------------------
    void VecIntSize( std::eek:stream &cout ){
    cout<<"\n--- VecInt() size test ---"<<std::endl;
    std::vector<int> VecInt(10);
    PrintVec( VecInt, cout);
    VecInt.push_back( 1 );
    PrintVec( VecInt, cout);
    for(size_t i(0); i < 11; ++i){ VecInt.push_back( i );}
    PrintVec( VecInt, cout);
    VecInt.resize( 50 );
    PrintVec( VecInt, cout);
    VecInt.push_back( 1 );
    PrintVec( VecInt, cout);
    VecInt.resize( 40 );
    PrintVec( VecInt, cout);
    cout<<" std::vector<int>( ).swap( VecInt );"<<std::endl;
    std::vector<int>( ).swap( VecInt );
    PrintVec( VecInt, cout);
    cout<<"--- VecInt() size test ---END"<<std::endl;
    return;
    }
    // --------------------------

    int main(){
    VecIntSize( std::cout );

    std::vector<double> vecD( 10, 3.14 ); // init 10 elements to 3.14.
    for(size_t i(0); i < vecD.size(); ++i){
    std::cout<<" vecD.at("<<i<<")= "
    <<vecD.at( i )<<std::endl;
    } // for(i)
    vecD.clear();
    std::cout<<" vecD.size()="<<vecD.size()<<std::endl;
    std::cout<<" vecD.capacity()="<<vecD.capacity()<<std::endl;

    { // initialise with string array
    std::string B[]={"001","2","we","the world"};
    std::vector<std::string> vBstr( B, B+(sizeof B/sizeof *B) );
    for(size_t i(0); i < vBstr.size(); ++i){
    std::cout << vBstr.at( i ) <<std::endl;
    }
    } // initialise with string array - end

    return 0;
    } // main()

    /* --- VecInt() size test --- (some output snipped)
    size=10 cap=10
    size=11 cap=20 // note cap doubled
    size=22 cap=40 // note cap doubled
    size=50 cap=50 // re-sized
    size=51 cap=100 // note cap doubled.
    size=40 cap=100 // note cap didn't shrink
    size=0 cap=0 // a reset
    --- VecInt() size test ---END
    // run to see the other output.
    */
    --
    Bob R
    POVrookie
     
    BobR, Nov 29, 2006
    #10
  11. Guest

    BobR wrote:
    > wrote in message ...
    > >Thanks for all your help.
    > >
    > >I am still trying to figure this out... and maybe I will have to go
    > >with a linked list. Hard to say.
    > >Anyway:
    > >In my header I have this in the private section:
    > >
    > >vector<Directory*> Directories; // pointer to an array of Directories
    > >
    > >and in the cpp file I am trying this (and maybe I shouldn't... more to
    > >follow):
    > >Directories.resize[MaxSubDirs];

    >
    > What Alf said. Try this example, maybe it will clear some cobwebs.
    > ( if it don't kill ya first.<G>).
    > [ BTW, please do not top-post. (ref: other posts of yours)]
    >
    > // --------------------------
    > #include <iostream>
    > #include <ostream>
    > #include <vector>
    > // --------------------------
    > void PrintVec( std::vector<int> const &vec, std::eek:stream &sout){
    > sout<<" size="<<vec.size()<<" cap="<<vec.capacity()<<std::endl;
    > return;
    > } // PrintVec(vector<int> const&,ostream&)
    > // --------------------------
    > void VecIntSize( std::eek:stream &cout ){
    > cout<<"\n--- VecInt() size test ---"<<std::endl;
    > std::vector<int> VecInt(10);
    > PrintVec( VecInt, cout);
    > VecInt.push_back( 1 );
    > PrintVec( VecInt, cout);
    > for(size_t i(0); i < 11; ++i){ VecInt.push_back( i );}
    > PrintVec( VecInt, cout);
    > VecInt.resize( 50 );
    > PrintVec( VecInt, cout);
    > VecInt.push_back( 1 );
    > PrintVec( VecInt, cout);
    > VecInt.resize( 40 );
    > PrintVec( VecInt, cout);
    > cout<<" std::vector<int>( ).swap( VecInt );"<<std::endl;
    > std::vector<int>( ).swap( VecInt );
    > PrintVec( VecInt, cout);
    > cout<<"--- VecInt() size test ---END"<<std::endl;
    > return;
    > }
    > // --------------------------
    >
    > int main(){
    > VecIntSize( std::cout );
    >
    > std::vector<double> vecD( 10, 3.14 ); // init 10 elements to 3.14.
    > for(size_t i(0); i < vecD.size(); ++i){
    > std::cout<<" vecD.at("<<i<<")= "
    > <<vecD.at( i )<<std::endl;
    > } // for(i)
    > vecD.clear();
    > std::cout<<" vecD.size()="<<vecD.size()<<std::endl;
    > std::cout<<" vecD.capacity()="<<vecD.capacity()<<std::endl;
    >
    > { // initialise with string array
    > std::string B[]={"001","2","we","the world"};
    > std::vector<std::string> vBstr( B, B+(sizeof B/sizeof *B) );
    > for(size_t i(0); i < vBstr.size(); ++i){
    > std::cout << vBstr.at( i ) <<std::endl;
    > }
    > } // initialise with string array - end
    >
    > return 0;
    > } // main()
    >
    > /* --- VecInt() size test --- (some output snipped)
    > size=10 cap=10
    > size=11 cap=20 // note cap doubled
    > size=22 cap=40 // note cap doubled
    > size=50 cap=50 // re-sized
    > size=51 cap=100 // note cap doubled.
    > size=40 cap=100 // note cap didn't shrink
    > size=0 cap=0 // a reset
    > --- VecInt() size test ---END
    > // run to see the other output.
    > */
    > --
    > Bob R
    > POVrookie


    I THINK I am inserting into my vector correctly; I am sure that I am
    not getting back my data.

    I did use a vector of pointers to my Directory class:

    vector<Directory*> Directories; // from my .h file

    In my cpp I then had:
    Directories.resize(0);

    to insert into my vector I have this:

    bool Directory::MKDir()
    {
    string DN; // directory name
    int i; // a counter

    //Get the name of the new file.
    do
    {
    if(i > 0)
    {
    cout << "Please enter a valid Directory name. No spaces and
    must ";
    cout << "not include a dot." << endl;
    }

    cout << "Enter directory name: ";
    getline(cin, DN);

    //Check to see if that Directory name is allowed
    //ValidName = tmpFile->ValidName(FN);
    i++;
    }while(DN == "" ); //|| ValidName == false

    Directory *ND = new Directory(NULL, DN);
    Directories.push_back(ND);
    NumSubDirs++;

    }

    I have tried the following to get access to the 'directory' after I
    inserted it into my vector (I think)

    /* for(int i = 0; i < Directories.size(); i++)
    {
    cout << Directories.at(i)->GetName() << " "; // << endl;
    }
    //Directory *D;
    */
    /* for (vector<Directory*>::iterator i = Directories.begin(); i !=
    Directories.end(); ++i)
    {
    D = new Directory *i
    D.Print() << endl;
    }*/

    for(size_t i(0); i < Directories.size(); ++i){
    std::cout<<" vecD.at("<<i<<")= "
    <<Directories.at( i )->GetName()<<std::endl;
    } // for(i)

    they all compile, but they all crash when I try to use the loop to show
    the names of the directories. I have two function associated that I
    could use:
    ..Print() (which does a cout of the name)
    ..GetName() (which returns the name of the directory)

    I am also going to need to sort this thing, so I really need access to
    those data elements... well I guess that was a given! <g>.

    Also about top-posting... do you mean typing my comments at the top of
    the previous users comments? If so; I shall stop.

    Thanks.
     
    , Nov 30, 2006
    #11
  12. BobR Guest

    wrote in message ...
    >
    >I THINK I am inserting into my vector correctly; I am sure that I am
    >not getting back my data.
    >I did use a vector of pointers to my Directory class:
    >
    > vector<Directory*> Directories; // from my .h file


    In your class, or at global scope?

    >
    >In my cpp I then had:
    >Directories.resize(0);


    You can just do:

    Directories.clear();

    .....to empty the vector. If you just created 'Directories', it isn't needed,
    yet.

    >
    >to insert into my vector I have this:
    >
    >bool Directory::MKDir(){
    > string DN; // directory name

    // > int i; // a counter

    Problem!! 'i' is not initialised, could be anything.
    int i( 0 ); // a counter
    // same result as int i = 0;

    >
    > do{ //Get the name of the new file.
    > if( i > 0 ){


    // since 'i' was not initialised, it was more than likely
    // not zero first pass thru loop.

    // > cout << "Please enter a valid Directory name."
    // <<" No spaces and must "
    // > << "not include a dot." << endl;

    cout << "Please enter a valid Directory name."
    "\nNo spaces and must "
    "not include a dot." <<std::endl;
    // string literals concatenate. pretty trick, eh?

    // You want this to print every loop except the first?

    > }
    >
    > cout << "Enter directory name: ";
    > getline(cin, DN);
    >
    > //Check to see if that Directory name is allowed
    > //ValidName = tmpFile->ValidName(FN);
    > i++;
    > }while(DN == "" ); //|| ValidName == false


    // std::string.empty() returns true if the string is empty. So, you could do:

    } while( DN.empty() ); //|| ValidName == false

    >
    > Directory *ND = new Directory(NULL, DN);
    > Directories.push_back( ND );


    // good.

    > NumSubDirs++;
    > } // Directory::MKDir()
    >
    >I have tried the following to get access to the 'directory' after I
    >inserted it into my vector (I think)
    >
    > /* for(int i = 0; i < Directories.size(); i++){
    > cout << Directories.at( i )->GetName() << " "; // << endl;
    > }
    > //Directory *D;
    > */
    > /* for (vector<Directory*>::iterator i = Directories.begin(); i !=
    > Directories.end(); ++i ){
    > D = new Directory *i
    > D.Print() << endl;
    > }*/

    /*
    That last one is wrong. If you want to use iterators, do:
    for( vector<Directory*>::iterator i = Directories.begin();
    i != Directories.end(); ++i ){
    (*i)->Print();
    std::cout<<std::endl;
    }
    */

    >
    > for(size_t i(0); i < Directories.size(); ++i){
    > std::cout<<" Directories.at("<<i<<")= "
    > <<Directories.at( i )->GetName()<<std::endl;
    > } // for(i)


    That should work. This is running inside the class (in a function), right?
    (or is 'Directories' at global scope?)

    >
    >they all compile, but they all crash when I try to use the loop to show
    >the names of the directories. I have two function associated that I
    >could use:
    >.Print() (which does a cout of the name)
    >.GetName() (which returns the name of the directory)


    Lesson 83649: 'Crash' means many things. What was the last thing you saw? The
    more information you give us, the quicker we can come up with a possible
    solution.

    Let's try something (I know you aren't ready, but, just copy/paste (delete
    later)).

    #include <stdexcept> // for exception

    { // scope of your function (maybe in your class)/main()

    try{
    for(size_t i(0); i < Directories.size(); ++i){
    std::cout<<" Directories.at("<<i<<")= "
    <<Directories.at( i )->GetName()<<std::endl;
    } // for(i)

    } // try
    catch( std::eek:ut_of_range &Oor ){
    std::cerr<<" caught: "<<Oor.what()<<std::endl;
    }
    catch(...){
    std::cerr<<" caught: some other error."<<std::endl;
    }

    } // scope of your function

    Now, run your prog and see which "caught:" you get. This will help narrow
    down the search for the bug.
    May be a good idea to post your 'Directory' class (and the definitions for
    'Print' and 'GetName', if not inline in the class).

    >
    >I am also going to need to sort this thing, so I really need access to
    >those data elements... well I guess that was a given! <g>.


    Piece of cake, but, one thing at a time. Find bug first<beats chest like
    Tarzan>!!

    >
    >Also about top-posting... do you mean typing my comments at the top of
    >the previous users comments? If so; I shall stop.
    >Thanks.


    This post was better. Next, trim (delete) old post that you do not need for
    your reply ( like notice that I cut out your text from prior post and my code
    which we are done with).

    --
    Bob R
    POVrookie
     
    BobR, Nov 30, 2006
    #12
  13. Guest

    > > vector<Directory*> Directories; // from my .h file
    >
    > In your class, or at global scope?


    I am doing this in the private section of my .h file
    >
    > >
    > >In my cpp I then had:
    > >Directories.resize(0);

    >
    > You can just do:
    >
    > Directories.clear();


    I have done that AND discovered that one of my constructors used 0 and
    one used 1! I never (really) got to see your code work. When I ran it
    here's what happened (some conjecture some fact).

    My directory object was created, setting my vector resize (1) (two
    slots) I added 1 directory. I then used my 'dir' command to list the
    files and directories. The program immediately launched a popup asking
    me to open my visual studio as a debugger (I am writing in Dev C++).

    The first error I saw pop up was:
    Unhandled exception at 0x00434b78 in COSC202H_Ass3.exe: 0xC0000005:
    Access violation reading location 0x00000000.

    when I pressed continue it would just keep popping back the same error.
    (That isn't what your catch does is it? I expected a cout on the
    screen.)

    Eventually I hit break and this line was highlighted:
    00434B78 mov eax,dword ptr [eax]
    which of course means NOTHING to me. HOWEVER I did find that by fixing
    my constructor using the method you suggested: Directories.clear(); the
    problem was fixed.

    DOH!

    > >to insert into my vector I have this:
    > >
    > >bool Directory::MKDir(){
    > > string DN; // directory name

    > // > int i; // a counter
    >
    > Problem!! 'i' is not initialised, could be anything.
    > int i( 0 ); // a counter
    > // same result as int i = 0;


    Thanks. Fixed it. It worked but at some point could have blown up I am
    sure.

    > cout << "Please enter a valid Directory name."
    > "\nNo spaces and must "
    > "not include a dot." <<std::endl;
    > // string literals concatenate. pretty trick, eh?
    >
    > // You want this to print every loop except the first?


    Yes. The idea is you create one 'directory' at a time. If you want to
    make more than one you (from the menu/screen) type mkdir again and go
    through the process. If you are looping it means your first attempt did
    not provide a valid name. (error checking is not in place yet).

    > >
    > > cout << "Enter directory name: ";
    > > getline(cin, DN);
    > >
    > > //Check to see if that Directory name is allowed
    > > //ValidName = tmpFile->ValidName(FN);
    > > i++;
    > > }while(DN == "" ); //|| ValidName == false

    >
    > // std::string.empty() returns true if the string is empty. So, you could do:
    >
    > } while( DN.empty() ); //|| ValidName == false
    >

    Thanks.

    > That last one is wrong. If you want to use iterators, do:
    > for( vector<Directory*>::iterator i = Directories.begin();
    > i != Directories.end(); ++i ){
    > (*i)->Print();
    > std::cout<<std::endl;
    > }
    > */
    >
    >
    > That should work. This is running inside the class (in a function), right?
    > (or is 'Directories' at global scope?)
    >

    Believe it or not it's inside my directories class. From a directory
    (object) you can create another directory (object) which is a child of
    the creator (subdirectory). At this point it's all still theory. ;)

    > Lesson 83649: 'Crash' means many things. What was the last thing you saw? The
    > more information you give us, the quicker we can come up with a possible
    > solution.


    It would list my files (from a prior loop listing files) then launch
    visual studio to debug (see above).

    >
    > Let's try something (I know you aren't ready, but, just copy/paste (delete
    > later)).
    >
    > #include <stdexcept> // for exception
    >
    > { // scope of your function (maybe in your class)/main()
    >
    > try{
    > for(size_t i(0); i < Directories.size(); ++i){
    > std::cout<<" Directories.at("<<i<<")= "
    > <<Directories.at( i )->GetName()<<std::endl;
    > } // for(i)
    >
    > } // try
    > catch( std::eek:ut_of_range &Oor ){
    > std::cerr<<" caught: "<<Oor.what()<<std::endl;
    > }
    > catch(...){
    > std::cerr<<" caught: some other error."<<std::endl;
    > }
    >
    > } // scope of your function
    >
    > Now, run your prog and see which "caught:" you get. This will help narrow
    > down the search for the bug.
    > May be a good idea to post your 'Directory' class (and the definitions for
    > 'Print' and 'GetName', if not inline in the class).
    >

    okay, here is my .h file:

    ***************************************
    #ifndef Directory_h
    #define Directory_h

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include "File.h"
    #include <vector>

    //using namespace std;

    class Directory
    {
    private:
    string Name; // Name of the Directory
    unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
    int Level;
    File *Files; //Pointer to an array of Files
    vector<Directory*> Directories; // vector to pointers to
    directories
    //vector<Directory*>::iterator iter;

    Directory *Parent; // pointer to this directories parent dir

    /*
    DoubleDirectories

    Input: Directories (array)
    Output: None

    Note: Double the size of the Directories array. Initially all
    arrays will start at 5 (just because).
    */
    void DoubleDirectories();

    /*
    DoubleFiles

    Input: Files (array)
    Output: None

    Note: Double the size of the Files Array. Initially all
    arrays will start at 5 (just because).
    */
    void DoubleFiles();

    /*
    ClearFiles

    Input: None
    Output: None

    Note: Used to delete all Files from the directory.
    */
    void ClearFiles();

    /*
    ClearDirectories

    Input: None
    Output: None

    Note: Used to delete all sub-directories from this directory.
    */
    void ClearDirectories();

    /*
    FindFile

    Input: Array of Files, first position, last position key.
    Output: Int (position in the array of the item if found,
    otherwise
    -1)
    */
    int FindFile(File sortedArray[], int first, int last,
    string key);

    public:

    /*
    Constructor

    Input: None
    Output: None

    Note: Create a new Directory object which is empty.
    */
    Directory();

    /*
    Constructor

    Input: N (directory name)
    Output: None

    Note: Creates a new empty Directory named Name
    */
    Directory(Directory *Parent, string N);

    /*
    Empty

    Input: None
    Output: Bool

    Note: Used to check to see if the directory is empty. A directory
    is empty if it has no files and no subdirectories.
    }
    */
    bool Empty();

    /*
    Insert

    Input: CF (Current file)
    Output: bool

    Note: Will return false if the file cannot be inserted into
    the directory. This will occur if the filename is already
    in
    use.
    */
    bool Insert(File CF);

    /*
    MKFile (make file)

    Input: Filename
    Output: bool

    Note: Used to prompt for input to create a file, then uses
    Insert
    to insert the file into the files array.
    */
    bool MKFile();

    /*
    Remove

    Input: FN (File name)
    Output: bool

    Note: Will remove a file from the directory if it can be
    found.
    Will return false if the file was not found.
    */
    bool Remove(string FN);

    /*
    Create

    Input: Dir (Subdirectory)
    Output: bool

    Note: Will attempt to add a subdirectory to this directory.
    Returns
    false if this cannot be done (duplicate).
    */
    bool Create(Directory Dir);

    bool MKDir();

    /*
    Delete

    Input: DN (Directory Name)
    Output: None

    Note: Used to delete a subdirectory and all of it's
    contents.
    */
    bool Delete(string DN);

    bool Delete();

    bool DeleteFile(int i);

    /*
    Move

    Input: DN (Directory Name)
    Output: bool

    Note: Will move to the parent directory (..) or a
    subdirectory
    as required. Returns true or false for success. Asking
    for
    parent of the root will return false. Asking for a subdir
    where it cannot be found will return false.
    */
    bool Move(string DN);

    /*
    Print

    Input: None
    Output: bool

    Note: Will print the contents of this directory(files) and ALL
    SUBDIRECTORIES. Uses the property Level to determin how
    many characters to indent before each line of output.

    will return false if there is nothing to print.
    */
    void Print();

    /*
    SMPrint (Small Print)

    Input: None
    Output: None

    Note: Prints only the content of the current directory and
    not
    of any subdirectories.
    */
    void SMPrint();

    /*
    GetNumFiles

    Input: None
    Output: None
    */
    int GetNumFiles();


    void insertionSort ( File A [ ], int low, int high );
    inline void Directory::swap ( File & x, File & y );
    /*
    QuickSort

    */
    void FilesQuickSort ( File A [ ], int low, int high );

    /*
    FindFile
    */
    int FindFile(File sortedArray[], int first, int last, int
    key);

    /*
    GetFileCount
    */
    int FileCount();

    /*
    FindFile

    Input: F (File)
    Output: bool

    Note: will find a file matching the file passed in will return
    true if found.
    */
    bool FileExists(File &F);

    string GetName();

    };

    #endif
    *********************************

    here is my .cpp file:

    #include "Directory.h"
    #include <stdexcept> // for exception

    //#include <iostream>
    //#include <cstdlib>
    //#include <string>

    /*
    Constructor
    */
    Directory::Directory()
    {
    Name = "";
    NumSubDirs = 0;
    NumFiles = 0;
    MaxSubDirs = 5;
    MaxFiles = 5;
    Level = -1;

    //Directories.resize(MaxSubDirs){NULL};
    Directories.clear();
    //Directories.push_back(new Directory);
    Files = new File[MaxFiles];
    }

    Directory::Directory(Directory *Parent, string N)
    {
    Name = N;
    NumSubDirs = 0;
    NumFiles = 0;
    MaxSubDirs = 5;
    MaxFiles = 5;
    Level = -1;

    Directories.clear();
    Files = new File[MaxFiles];
    }

    /*
    DoubleFiles (Double array file size)
    */
    void Directory::DoubleFiles()
    {
    File * OldArray = Files;
    Files = new File[MaxFiles * 2];
    for(int i = 0; i <= MaxFiles -1; i++)
    {
    Files = new File(OldArray.GetFileName());
    }

    delete [] OldArray;

    MaxFiles = MaxFiles * 2;
    }

    //Empty()
    bool Directory::Empty()
    {
    if(NumSubDirs == 0 && NumFiles == 0)
    return true;
    else
    return false;
    }

    //MKFile()
    bool Directory::MKFile()
    {
    string FN; //File name
    //system("cls"); // clear screen
    int i = 0;
    bool ValidName = false;
    File *tmpFile = new File;

    //Get the name of the new file.
    do
    {
    if(i > 0)
    {
    cout << "Please enter a valid file name. No spaces and must ";
    cout << "include a dot." << endl;
    }

    cout << "Enter file name: ";
    getline(cin, FN);

    //Check to see if that file name is allowed
    ValidName = tmpFile->ValidName(FN);
    i++;
    }while(FN.empty() || ValidName == false);

    if(NumFiles > 0 && FindFile(Files, 0, NumFiles, FN)< 0)
    {
    // this would be a unique file
    Files[NumFiles] = tmpFile;
    if(NumFiles == MaxFiles -1)
    {
    DoubleFiles(); // double the size of the files array
    }
    NumFiles++;
    }
    else if(NumFiles == 0)
    {
    // this would be a unique file
    Files[NumFiles] = tmpFile;
    if(NumFiles == MaxFiles -1)
    {
    DoubleFiles(); // double the size of the files array
    }
    NumFiles++;
    }
    else
    {
    // Error checking
    //cout << "NumFiles: " << NumFiles << endl;
    //cout << "FindFiles = " << FindFile(Files, 0, NumFiles, FN);
    delete tmpFile;
    cout << "** Error: File already exists. Aborted." << endl;
    system("PAUSE");
    }
    }

    bool Directory::MKDir()
    {
    string DN; // directory name
    int i = 0; // a counter

    //Get the name of the new file.
    do
    {
    if(i > 0)
    {
    cout << "Please enter a valid Directory name. No spaces and
    must ";
    cout << "not include a dot." << endl;
    }

    cout << "Enter directory name: ";
    getline(cin, DN);

    //Check to see if that Directory name is allowed
    //ValidName = tmpFile->ValidName(FN);
    i++;
    }while(DN.empty()); //|| ValidName == false

    Directory *ND = new Directory(NULL, DN);
    Directories.push_back(ND);
    NumSubDirs++;

    }


    bool Directory::Delete()
    {
    int index, i;
    string Item;
    bool result;

    system("cls");

    //SMPrint();

    do
    {
    if(i > 0)
    {
    cout << "Enter the name of the item you wish to delete: " <<
    endl;
    cout << "->";
    }
    getline(cin, Item);

    i++;
    }while(Item == "");

    //search for a file with that name
    index = FindFile(Files, 0, NumFiles, Item);

    //cout << "FindFile index = " << index << endl;

    if(index > -1)
    {
    result = DeleteFile(index);
    cout << "Deleted." << endl;
    system("PAUSE");
    }

    }

    bool Directory::DeleteFile(int i)
    {
    int j;

    //create a new array and copy all elements to it except the one to be
    // deleted
    File * OldArray = Files;
    *Files = new File[MaxFiles];
    for(j = 0; j <= NumFiles -1; j++)
    {
    //cout << "j = " << j << endl;
    if(j < i)
    {
    Files[j] = new File(OldArray[j].GetFileName());
    //cout << "Moved " << OldArray[j].GetFileName() << " to Files"
    << endl;
    }
    else
    {
    Files[j] = new File(OldArray[j+1].GetFileName());
    //cout << "Moved " << OldArray[j+1].GetFileName() << " to
    Files" << endl;
    }
    }
    NumFiles--; //decriment NumFiles
    delete [] OldArray;

    return true;
    }


    //GetNumFiles
    int Directory::GetNumFiles()
    {
    return NumFiles;
    }

    //SMPrint (Small Print)
    void Directory::SMPrint()
    {
    FilesQuickSort (Files, 0, NumFiles -1 );
    for(int i = 0; i <= NumFiles -1; i++)
    {
    Files.Print();
    cout << endl;
    }

    try{
    for(size_t i(0); i < Directories.size(); ++i)
    {
    std::cout<<" Directories.at("<<i<<")= " <<Directories.at( i
    )->GetName()<<std::endl;
    } // for(i)
    } // try
    catch( std::eek:ut_of_range &Oor )
    {
    std::cerr<<" caught: "<<Oor.what()<<std::endl;
    }
    catch(...){
    std::cerr<<" caught: some other error."<<std::endl;
    }
    }

    void Directory::insertionSort ( File A [ ], int low, int high )
    {
    for ( int p = low+1; p <= high; p++ )
    {
    File tmp = A [ p ];
    int j;

    for ( j = p; j > low && tmp < A [ j-1 ]; j-- )
    A [ j ] = A [ j-1 ];

    A [ j ] = tmp;
    }
    }

    inline void Directory::swap ( File & x, File & y )
    {
    File temp = x;
    x = y;
    y = temp;
    }

    //QuickSort
    // Best and average case time complexity of quickSort : O(n log n )
    // Worst case time complexity of quickSort : O(n^2)
    void Directory::FilesQuickSort ( File A [ ], int low, int high )
    {
    if ( low + 10 > high )
    insertionSort ( A, low, high );
    else
    {
    // Sort low, middle and high
    int middle = ( low + high ) / 2;
    if ( A [ middle ] < A [ low ] )
    swap ( A [ low ], A [ middle ] );

    if ( A [ high ] < A [ low ] )
    swap ( A [ low ], A [ high ] );

    if ( A [ high ] < A [ middle ] )
    swap ( A [ middle ], A [ high ] );

    // Place pivot at position high - 1
    File pivot = A [ middle ];
    swap ( A [ middle ], A [ high-1 ] );

    // Partition around the pivot
    int i, j;
    for ( i = low, j = high-1; ; )
    {
    while ( A [ ++i ] < pivot ) { }
    while ( pivot < A [ --j ] ) { }
    if ( i < j )
    swap ( A [ i ], A [ j ] );
    else
    break;
    }

    swap ( A [ i ], A [ high-1 ] );

    FilesQuickSort ( A, low, i-1 );
    FilesQuickSort ( A, i+1, high );
    }
    }

    /*
    FindFile
    */

    int Directory::FindFile(File sortedArray[], int first, int last, string
    key)
    {
    while (first <= last) {
    int mid = (first + last) / 2; // compute mid point.
    if (sortedArray[mid] < key)
    first = mid + 1; // repeat search in top half.
    else if (sortedArray[mid] > key)
    last = mid - 1; // repeat search in bottom half.
    else
    return mid; // found it. return position /////
    }
    return -(first + 1); // failed to find key
    }

    int Directory::FileCount()
    {
    return NumFiles;
    }

    bool Directory::FileExists(File &F)
    {
    if(FindFile(Files, 0, NumFiles, F.GetFileName()) > -1)
    return true;
    else
    return false;
    }

    string Directory::GetName()
    {
    return Name;
    }

    void Directory::print()
    {
    cout << Name;
    }
    *******************************************
    > >
    > >I am also going to need to sort this thing, so I really need access to
    > >those data elements... well I guess that was a given! <g>.

    >
    > Piece of cake, but, one thing at a time. Find bug first<beats chest like
    > Tarzan>!!
    >
    > >
    > >Also about top-posting... do you mean typing my comments at the top of
    > >the previous users comments? If so; I shall stop.
    > >Thanks.

    >
    > This post was better. Next, trim (delete) old post that you do not need for
    > your reply ( like notice that I cut out your text from prior post and my code
    > which we are done with).
    >
    > --
    > Bob R
    > POVrookie


    Thanks for all the time and effort.

    I'd particularly like to get that try catch working. I asked about it
    in class but was told that isn't taught in this class (or the one
    prior). I'd like it not so much for throwing errors, but to catch all
    the weird input that I didn't expect and be able to recover with a 'hey
    dummy type something that makes sense' kind of message!

    ;) Thanks again.
     
    , Nov 30, 2006
    #13
  14. BobR Guest

    wrote in message ...

    >Access violation reading location 0x00000000.


    Look for a pointer that was never set to anything.

    >
    >I'd particularly like to get that try catch working. I asked about it
    >in class but was told that isn't taught in this class (or the one
    >prior). I'd like it not so much for throwing errors, but to catch all
    >the weird input that I didn't expect and be able to recover with a 'hey
    >dummy type something that makes sense' kind of message!


    I'll check out your code in a little bit[1]. Thought I'd throw(pun) you a
    bone in the meantime.

    Get "Thinking in C++", 2nd ed. Volume 1&2 by Bruce Eckel
    (available for free here. You can buy it in hardcopy too.):
    http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html

    In Vol 2, Part 1, there is a chapter on 'Exception Handling'. Some of it may
    be over your head, but, he gives enough examples that you should be able to
    figure it out.

    Be aware that the way you(we) want to use exceptions is a slightly improper
    use. However, I have found it a useful tool for narrowing down a problem area
    (bug hunting) while developing new code. Normally, you would only use
    exceptions to handle situations that can't be delt with in normal program
    flow.

    At a top level, you can do:

    int main(){
    using std::cerr;
    using std::endl;
    try{
    // your code here
    if( true ){ throw "Help Me!!";}
    } // try
    catch( std::bad_alloc const &ba ){
    cerr << "Out of memory! " << ba.what() << endl;
    }
    catch( std::runtime_error const &re ){
    cerr << re.what() << endl;
    }
    catch( char const *r_e ){ // catch "Help Me!!"
    cerr<<"error: " << r_e << endl;
    }
    // as many catch() clauses as you need
    catch(...){ // a 'catch all'
    cerr << "caught something not caught above" << endl;
    }
    return 0;
    } // main()


    Also, I noticed you said something about 'Dev-C++'. It defaults to
    MinGW(GCC). If you build a debug version of your program (using -g switch, or
    one of it's variants), and then jump to the ms debugger, you may get false
    information. If you build with GCC, you should use 'gdb' (the GCC debugger).
    I don't know if 'Insight' is still alive. It was a nice front-end for gdb and
    worked nice wirh Dev-C++. Maybe 'Google' for it if interested (there was a
    link on the Bloodshed site).

    I'll get back to you on your Directory class (if one of the experts in this
    NG don't 'correct' it first).

    [1] - first pass through I think I spotted some potential problems. Need to
    check it out more so I don't send you down the wrong path.
    --
    Bob R
    POVrookie
     
    BobR, Nov 30, 2006
    #14
  15. BobR Guest

    wrote in message ...
    >
    > I never (really) got to see your code work. When I ran it
    >here's what happened (some conjecture some fact).
    >
    >My directory object was created, setting my vector resize (1) (two
    >slots)


    One 'slot', index 0. As soon as you push_back() once, the max valid index
    goes to 1 ( so now you have 0 and 1).

    > I added 1 directory. I then used my 'dir' command to list the
    >files and directories. The program immediately launched a popup asking
    >me to open my visual studio as a debugger (I am writing in Dev C++).



    OK, I can't be sure yet, but I think your one of your problems is with
    'FilesQuickSort()'.
    Comment that out of your program temporarily (read below first).

    I don't know what is in your "File.h".

    < just a thought >
    Now, here is a bigger problem. You use a pointer to a dynamic allocated array
    ('*Files'). If you do anything that needs to copy the Directory class object
    (std containers use copy constructor), the default copy constructor just
    copies the pointer, no new allocation takes place. That's is a big problem,
    all the copies are trying (could be) to work on the same realestate. That may
    be the problem in 'FilesQuickSort()'.
    Rule Of Three (or two, if you use smart pointers)!

    Let's do a test:

    class Directory{
    private:

    // Prevent assignment and copy-construction:
    Directory( Directory const & ); // just this, don't define it.
    void operator=( Directory const & );

    // rest of your class
    }; // class Directory

    Now, try to compile it. Work? ( it should not ).

    A little side note: a class defaults to 'private', so you don't need to put
    'private:' at the very top of your class.
    class Directory{
    // this part is private
    public:
    // this part is public
    private:
    // this part is private again
    }; // class Directory

    Your class also needs a destructor that will clean up 'Files'. As is, you
    have a memory leak.

    Directory::~Directory(){
    delete[] Files;
    // and since your vector holds pointers to 'new' objects.
    for( size_t i(0); i < Directories.size(); ++i ){
    delete Directories.at( i );
    }
    } // Dtor

    If the vector held actual objects, it would do all the cleanup for you.

    Your book should have something on copy constructors and assignment
    operators.
    ( If not, 'Thinking in C++' vol 1 does. )


    >when I pressed continue it would just keep popping back the same error.
    >( ** That isn't what your catch does is it? ** I expected a cout on the
    >screen.)


    No. If it got to 'catch(...)', it would have put a message on crt.
    (but not everything gets caught by that)
    If you had put the FilesQuickSort() call inside the try{}, you may have seen
    a message. Try it and see (may give another clue).



    >*********************************
    >here is my .cpp file:
    >
    >#include "Directory.h"
    >#include <stdexcept> // for exception
    >
    >//#include <iostream>
    >//#include <cstdlib>
    >//#include <string>
    >
    >/* Constructor */
    >Directory::Directory(){
    > Name = "";
    > NumSubDirs = 0;
    > NumFiles = 0;
    > MaxSubDirs = 5;
    > MaxFiles = 5;
    > Level = -1;
    >
    > //Directories.resize(MaxSubDirs){NULL};
    > Directories.clear();
    > //Directories.push_back(new Directory);
    > Files = new File[MaxFiles];
    >}


    Unless your instructor expressly prohibited it, you should learn to use
    'initialiser lists'.

    Directory::Directory() : // put a colon there
    Name( "" ), // a coma after all but last
    NumSubDirs( 0 ),
    NumFiles( 0 ),
    MaxSubDirs( 5 ),
    MaxFiles( 5 ),
    Level( -1 )// no coma
    {
    Directories.clear();
    Files = new File[MaxFiles];
    } // Directory Ctor default


    >/* DoubleFiles (Double array file size) */
    >void Directory::DoubleFiles(){
    > File * OldArray = Files;
    > Files = new File[MaxFiles * 2];
    > for(int i = 0; i <= MaxFiles -1; i++){
    > Files = new File(OldArray.GetFileName());
    > }
    > delete [] OldArray;
    > MaxFiles = MaxFiles * 2;
    > }


    If you also make 'Files' a std::vector, you won't need things like
    'DoubleFiles()'.

    >//Empty()


    If std::vector<File> Files, just:
    if( Files.empty() ){ /* do whatever */ }

    >//GetNumFiles


    Files.size()

    std::sort( Files.begin(), Files.end() );
    // but, you may need to write a 'predicate' to sort the way you want.
    // dependes on what 'File' is.

    std::unique( Files.begin(), Files.end() ); // remove dups.
    // but, you may need to write a 'predicate'.
    // dependes on what 'File' is.

    Starting to see the value of the std containers and library?


    >void Directory::insertionSort ( File A [ ], int low, int high ){


    if( ( low < 0 ) || ( high > MaxFiles ) ){ return; }

    Murphy's laws: If more than one thing can go wrong, the one that will go
    wrong is the one that will do the most damage!

    > for ( int p = low+1; p <= high; p++ ){
    > File tmp = A [ p ];
    > int j;
    >
    > for ( j = p; j > low && tmp < A [ j-1 ]; j-- )
    > A [ j ] = A [ j-1 ];
    >
    > A [ j ] = tmp;
    > }
    >}
    >*******************************************


    Work on those things a little, and come back.

    Nobody ever said C++ was easy! Hang in there!
    --
    Bob R
    POVrookie
     
    BobR, Dec 1, 2006
    #15
  16. Guest

    BobR wrote:
    > wrote in message ...
    >
    > OK, I can't be sure yet, but I think your one of your problems is with
    > 'FilesQuickSort()'.
    > Comment that out of your program temporarily (read below first).
    >

    Actually my QuickSort works. I had to overload operators for it to do
    so, but it seems to be fine.

    > I don't know what is in your "File.h".
    >
    > < just a thought >
    > Now, here is a bigger problem. You use a pointer to a dynamic allocated array
    > ('*Files'). If you do anything that needs to copy the Directory class object
    > (std containers use copy constructor), the default copy constructor just
    > copies the pointer, no new allocation takes place. That's is a big problem,
    > all the copies are trying (could be) to work on the same realestate. That may
    > be the problem in 'FilesQuickSort()'.
    > Rule Of Three (or two, if you use smart pointers)!
    >


    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.

    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?

    > Let's do a test:
    >
    > class Directory{
    > private:
    >
    > // Prevent assignment and copy-construction:
    > Directory( Directory const & ); // just this, don't define it.
    > void operator=( Directory const & );
    >
    > // rest of your class
    > }; // class Directory
    >
    > Now, try to compile it. Work? ( it should not ).


    Umm... it did work actually. Here is the 'new' header:
    ***********************************************************

    #ifndef Directory_h
    #define Directory_h

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include "File.h"
    #include <vector>

    //using namespace std;
    class Directory{
    private:


    // Prevent assignment and copy-construction:
    Directory( Directory const & ); // just this, don't define it.
    void operator=( Directory const & );



    /*
    class Directory
    {
    private: */
    string Name; // Name of the Directory
    unsigned int NumSubDirs, NumFiles, MaxSubDirs, MaxFiles;
    int Level;
    File *Files; //Pointer to an array of Files
    vector<Directory*> Directories; // vector to pointers to
    directories
    //vector<Directory*>::iterator iter;

    Directory *Parent; // pointer to this directories parent dir

    /*
    DoubleDirectories

    Input: Directories (array)
    Output: None

    Note: Double the size of the Directories array. Initially all
    arrays will start at 5 (just because).
    */
    void DoubleDirectories();

    /*
    DoubleFiles

    Input: Files (array)
    Output: None

    Note: Double the size of the Files Array. Initially all
    arrays will start at 5 (just because).
    */
    void DoubleFiles();

    /*
    ClearFiles

    Input: None
    Output: None

    Note: Used to delete all Files from the directory.
    */
    void ClearFiles();

    /*
    ClearDirectories

    Input: None
    Output: None

    Note: Used to delete all sub-directories from this directory.
    */
    void ClearDirectories();

    /*
    FindFile

    Input: Array of Files, first position, last position key.
    Output: Int (position in the array of the item if found,
    otherwise
    -1)
    */
    int FindFile(File sortedArray[], int first, int last,
    string key);

    public:

    /*
    Constructor

    Input: None
    Output: None

    Note: Create a new Directory object which is empty.
    */
    Directory();

    /*
    Constructor

    Input: N (directory name)
    Output: None

    Note: Creates a new empty Directory named Name
    */
    Directory(Directory *Parent, string N);

    /*
    Empty

    Input: None
    Output: Bool

    Note: Used to check to see if the directory is empty. A directory
    is empty if it has no files and no subdirectories.
    }
    */
    bool Empty();

    /*
    Operator ==

    Inputs: string D (directory name)
    Output: bool

    Note: Used to detect if a directory name matches a string.
    For example, two Directories of the same parent cannot
    have the same name.
    */
    bool operator==(const string &D);

    /*
    operator <

    Inputs: Directory D
    Outputs: bool

    Notes: Used to determine if the NAME of the directory is
    less than (before) the one compared.
    */
    bool operator<(const Directory & D); //Note to self pointer to
    D???

    /*
    operator <

    Inputs: DN (Directory name)
    Outputs: bool

    Notes: If the Directory name is < the 'other' Directory name True.
    */
    bool operator<(string DN);

    /*
    operator >

    Inputs: Directory D
    Outputs: bool

    Note: Used to determine if the NAME of the directory is greater
    than the other.
    */
    bool operator>(const Directory & D);

    /*
    operator >

    Inputs: DN (string file name)
    Outputs: bool

    Note: Uses a string value to compare a string to the NAME
    of the directory.
    */
    bool operator>(string DN);

    /*
    Insert

    Input: CF (Current file)
    Output: bool

    Note: Will return false if the file cannot be inserted into
    the directory. This will occur if the filename is already
    in
    use.
    */
    bool Insert(File CF);

    /*
    MKFile (make file)

    Input: Filename
    Output: bool

    Note: Used to prompt for input to create a file, then uses
    Insert
    to insert the file into the files array.
    */
    bool MKFile();

    /*
    Remove

    Input: FN (File name)
    Output: bool

    Note: Will remove a file from the directory if it can be
    found.
    Will return false if the file was not found.
    */
    bool Remove(string FN);

    /*
    Create

    Input: Dir (Subdirectory)
    Output: bool

    Note: Will attempt to add a subdirectory to this directory.
    Returns
    false if this cannot be done (duplicate).
    */
    bool Create(string Dir);

    bool MKDir();

    /*
    Delete

    Input: DN (Directory Name)
    Output: None

    Note: Used to delete a subdirectory and all of it's
    contents.
    */
    bool Delete(string DN);

    bool Delete();

    bool DeleteFile(int i);

    /*
    Move

    Input: DN (Directory Name)
    Output: bool

    Note: Will move to the parent directory (..) or a
    subdirectory
    as required. Returns true or false for success. Asking
    for
    parent of the root will return false. Asking for a subdir
    where it cannot be found will return false.
    */
    bool Move(string DN);

    /*
    Print

    Input: None
    Output: bool

    Note: Will print the contents of this directory(files) and ALL
    SUBDIRECTORIES. Uses the property Level to determin how
    many characters to indent before each line of output.

    will return false if there is nothing to print.
    */
    void Print();

    /*
    SMPrint (Small Print)

    Input: None
    Output: None

    Note: Prints only the content of the current directory and
    not
    of any subdirectories.
    */
    void SMPrint();

    /*
    GetNumFiles

    Input: None
    Output: None
    */
    int GetNumFiles();


    void insertionSort ( File A [ ], int low, int high );
    //void insertionSort (vector<Directory*> A, int low, int
    high);

    inline void swap ( File & x, File & y );
    //inline void swap (Directory & x, Directory & y);
    /*
    QuickSort

    */
    void QuickSort ( File A [ ], int low, int high );
    //void QuickSort (vector<Directory> A, int low, int high);

    /*
    FindFile
    */
    int FindFile(File sortedArray[], int first, int last, int
    key);

    /*
    GetFileCount
    */
    int FileCount();

    /*
    FindFile

    Input: F (File)
    Output: bool

    Note: will find a file matching the file passed in will return
    true if found.
    */
    bool FileExists(File &F);

    string GetName();

    };

    #endif

    **********************************************

    >
    > A little side note: a class defaults to 'private', so you don't need to put
    > 'private:' at the very top of your class.
    > class Directory{
    > // this part is private
    > public:
    > // this part is public
    > private:
    > // this part is private again
    > }; // class Directory
    >


    The prof is big on seeing those words though. It does make it clearer
    too.

    > Your class also needs a destructor that will clean up 'Files'. As is, you
    > have a memory leak.
    >


    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.
    ;)

    > Directory::~Directory(){
    > delete[] Files;
    > // and since your vector holds pointers to 'new' objects.
    > for( size_t i(0); i < Directories.size(); ++i ){
    > delete Directories.at( i );
    > }
    > } // Dtor
    >


    > If the vector held actual objects, it would do all the cleanup for you.
    >

    How can I dynamically create actual objects though? They do go out of
    scope at the end of the function don't they?

    > If you had put the FilesQuickSort() call inside the try{}, you may have seen
    > a message. Try it and see (may give another clue).
    >

    I think the old bug is quite fixed. I have been using it for a while
    with no problem, even adding subdirectories. The QuickSort works for my
    Files (putting them in alphabetical order).

    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.

    My suspicion is that they are sorted by the pointer, not the thing
    pointed to. I am looking at that but....
    >


    here is the new cpp file, it has changed a little to accomodate things
    like automated directory addition.

    *********************************
    #include "Directory.h"
    #include <stdexcept> // for exception

    //#include <iostream>
    //#include <cstdlib>
    //#include <string>

    /*
    Constructor
    */
    Directory::Directory()
    {
    Name = "";
    NumSubDirs = 0;
    NumFiles = 0;
    MaxSubDirs = 5;
    MaxFiles = 5;
    Level = -1;

    //Directories.resize(MaxSubDirs){NULL};
    Directories.clear();
    //Directories.push_back(new Directory);
    Files = new File[MaxFiles];
    }

    Directory::Directory(Directory *Parent, string N)
    {
    Name = N;
    NumSubDirs = 0;
    NumFiles = 0;
    MaxSubDirs = 5;
    MaxFiles = 5;
    Level = -1;

    Directories.clear();
    Files = new File[MaxFiles];
    }

    /*
    operator==
    */
    bool Directory::eek:perator==(const string & D)
    {
    if(Name != D)
    return false;
    else
    return true;
    }

    bool Directory::eek: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;
    }

    /*
    operator>
    */
    bool Directory::eek:perator>(const Directory & D)
    {
    if(Name < D.Name)
    return false;

    if(Name > D.Name)
    return true;
    }


    /*
    DoubleFiles (Double array file size)
    */
    void Directory::DoubleFiles()
    {
    File * OldArray = Files;
    Files = new File[MaxFiles * 2];
    for(int i = 0; i <= MaxFiles -1; i++)
    {
    Files = new File(OldArray.GetFileName());
    }

    delete [] OldArray;

    MaxFiles = MaxFiles * 2;
    }

    //Empty()
    bool Directory::Empty()
    {
    if(NumSubDirs == 0 && NumFiles == 0)
    return true;
    else
    return false;
    }

    //MKFile()
    bool Directory::MKFile()
    {
    string FN; //File name
    //system("cls"); // clear screen
    int i = 0;
    bool ValidName = false;
    File *tmpFile = new File;

    //Get the name of the new file.
    do
    {
    if(i > 0)
    {
    cout << "Please enter a valid file name. No spaces and must ";
    cout << "include a dot." << endl;
    }

    cout << "Enter file name: ";
    getline(cin, FN);

    //Check to see if that file name is allowed
    ValidName = tmpFile->ValidName(FN);
    i++;
    }while(FN.empty() || ValidName == false);

    if(NumFiles > 0 && FindFile(Files, 0, NumFiles, FN)< 0)
    {
    // this would be a unique file
    Files[NumFiles] = tmpFile;
    if(NumFiles == MaxFiles -1)
    {
    DoubleFiles(); // double the size of the files array
    }
    NumFiles++;
    QuickSort (Files, 0, NumFiles -1 );
    }
    else if(NumFiles == 0)
    {
    // this would be a unique file
    Files[NumFiles] = tmpFile;
    if(NumFiles == MaxFiles -1)
    {
    DoubleFiles(); // double the size of the files array
    }
    NumFiles++;
    }
    else
    {
    // Error checking
    //cout << "NumFiles: " << NumFiles << endl;
    //cout << "FindFiles = " << FindFile(Files, 0, NumFiles, FN);
    delete tmpFile;
    cout << "** Error: File already exists. Aborted." << endl;
    system("PAUSE");
    }
    }

    bool Directory::MKDir()
    {
    string DN; // directory name
    int i = 0; // a counter
    bool result;

    //Get the name of the new file.
    do
    {
    if(i > 0)
    {
    cout << "Please enter a valid Directory name. No spaces and
    must ";
    cout << "not include a dot." << endl;
    }

    cout << "Enter directory name: ";
    getline(cin, DN);

    //Check to see if that Directory name is allowed
    //ValidName = tmpFile->ValidName(FN);
    i++;
    }while(DN.empty()); //|| ValidName == false

    //create the directory
    result = Create(DN);
    }

    bool Directory::Create(string DN)
    {
    Directory *ND = new Directory(this, DN);
    Directories.push_back(ND);
    NumSubDirs++;

    std::sort(Directories.begin(), Directories.end());
    return true;
    }

    bool Directory::Delete()
    {
    int index, i;
    string Item;
    bool result;

    system("cls");

    //SMPrint();

    do
    {
    if(i > 0)
    {
    cout << "Enter the name of the item you wish to delete: " <<
    endl;
    cout << "->";
    }
    getline(cin, Item);

    i++;
    }while(Item == "");

    //search for a file with that name
    index = FindFile(Files, 0, NumFiles, Item);

    //cout << "FindFile index = " << index << endl;

    if(index > -1)
    {
    result = DeleteFile(index);
    cout << "Deleted." << endl;
    system("PAUSE");
    }

    }

    bool Directory::DeleteFile(int i)
    {
    int j;

    //create a new array and copy all elements to it except the one to be
    // deleted
    File * OldArray = Files;
    *Files = new File[MaxFiles];
    for(j = 0; j <= NumFiles -1; j++)
    {
    //cout << "j = " << j << endl;
    if(j < i)
    {
    Files[j] = new File(OldArray[j].GetFileName());
    //cout << "Moved " << OldArray[j].GetFileName() << " to Files"
    << endl;
    }
    else
    {
    Files[j] = new File(OldArray[j+1].GetFileName());
    //cout << "Moved " << OldArray[j+1].GetFileName() << " to
    Files" << endl;
    }
    }
    NumFiles--; //decriment NumFiles
    delete [] OldArray;

    return true;
    }


    //GetNumFiles
    int Directory::GetNumFiles()
    {
    return NumFiles;
    }

    //SMPrint (Small Print)
    void Directory::SMPrint()
    {
    //cout << NumFiles;
    if( NumFiles > 0)
    {
    for(int i = 0; i <= NumFiles -1; i++)
    {
    Files.Print();
    cout << endl;
    }
    }

    if(Directories.size() > 0)
    {
    try
    {
    for(size_t i(0); i < Directories.size(); ++i)
    {
    cout << Directories.at( i )->GetName()<< endl;
    } // for(i)
    } // try
    catch( std::eek:ut_of_range &Oor )
    {
    std::cerr<<" caught: "<<Oor.what()<<std::endl;
    }
    catch(...)
    {
    std::cerr<<" caught: some other error."<<std::endl;
    }
    }

    cout << NumFiles << " Files and " << Directories.size() << "
    Directories" << endl;
    }

    void Directory::insertionSort ( File A [ ], int low, int high )
    {
    for ( int p = low+1; p <= high; p++ )
    {
    File tmp = A [ p ];
    int j;

    for ( j = p; j > low && tmp < A [ j-1 ]; j-- )
    A [ j ] = A [ j-1 ];

    A [ j ] = tmp;
    }
    }

    /*
    void Directory::insertionSort ( vector<Directory*> A , int low, int
    high )
    {
    for ( int p = low+1; p <= high; p++ )
    {
    Directory *tmp = A [ p ];
    int j;

    for ( j = p; j > low && tmp < A [ j-1 ]; j-- )
    A [ j ] = A [ j-1 ];

    A [ j ] = tmp;
    }
    }
    */
    inline void Directory::swap ( File & x, File & y )
    {
    File temp = x;
    x = y;
    y = temp;
    }
    /*
    inline void Directory::swap (Directory &x, Directory &y)
    {
    Directory temp = x;
    x = y;
    y = temp;
    }
    */

    //QuickSort
    // Best and average case time complexity of quickSort : O(n log n )
    // Worst case time complexity of quickSort : O(n^2)
    //QuickSort
    // Best and average case time complexity of quickSort : O(n log n )
    // Worst case time complexity of quickSort : O(n^2)
    void Directory::QuickSort ( File A [ ], int low, int high )
    {
    if ( low + 10 > high )
    insertionSort ( A, low, high );
    else
    {
    // Sort low, middle and high
    int middle = ( low + high ) / 2;
    if ( A [ middle ] < A [ low ] )
    swap ( A [ low ], A [ middle ] );

    if ( A [ high ] < A [ low ] )
    swap ( A [ low ], A [ high ] );

    if ( A [ high ] < A [ middle ] )
    swap ( A [ middle ], A [ high ] );

    // Place pivot at position high - 1
    File pivot = A [ middle ];
    swap ( A [ middle ], A [ high-1 ] );

    // Partition around the pivot
    int i, j;
    for ( i = low, j = high-1; ; )
    {
    while ( A [ ++i ] < pivot ) { }
    while ( pivot < A [ --j ] ) { }
    if ( i < j )
    swap ( A [ i ], A [ j ] );
    else
    break;
    }

    swap ( A [ i ], A [ high-1 ] );

    QuickSort ( A, low, i-1 );
    QuickSort ( A, i+1, high );
    }
    }

    /*
    FindFile
    */

    int Directory::FindFile(File sortedArray[], int first, int last, string
    key)
    {
    while (first <= last) {
    int mid = (first + last) / 2; // compute mid point.
    if (sortedArray[mid] < key)
    first = mid + 1; // repeat search in top half.
    else if (sortedArray[mid] > key)
    last = mid - 1; // repeat search in bottom half.
    else
    return mid; // found it. return position /////
    }
    return -(first + 1); // failed to find key
    }

    int Directory::FileCount()
    {
    return NumFiles;
    }

    bool Directory::FileExists(File &F)
    {
    if(FindFile(Files, 0, NumFiles, F.GetFileName()) > -1)
    return true;
    else
    return false;
    }

    string Directory::GetName()
    {
    return Name;
    }

    void Directory::print()
    {
    cout << Name;
    }

    ************************************************

    Not that I want to over do it, but here's the 'controlling' app called
    FileSystem:

    header:
    ************************************************
    #ifndef FileSystem_h
    #define FileSystem_h

    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include "Directory.h"

    using namespace std;

    class FileSystem
    {
    private:
    Directory *CurrentDir, *RootDir;

    public:

    /*
    constructor
    */
    FileSystem();

    /*
    Destructor
    */
    ~FileSystem();

    /*
    main

    inputs: none
    outputs: none

    Note: used start the application process.
    */
    void main();

    /*
    mkdir

    inputs: none
    output: none

    Note: used to make a new sub-directory of the current directory.
    */
    void mkdir();

    /*
    mkfile

    input: none
    output: none

    Note: used to make a new file
    */
    void mkfile();

    /*
    del

    input: none
    output: none

    Note: used to delete BOTH files and directories. Will search for a

    matching file, if none is found will search for a directory
    to delete.
    */
    void del();

    /*
    dir

    input: none
    output: none

    Note: used to list the contents of the current directory.
    */
    void dir();

    /*
    move

    input: none
    output: none

    Note: used to either move to the parent directory or to a subdir.
    */
    void move();

    /*
    print

    input: none
    output: none

    Note: used to list the contents of the current directory and
    subdirectories.
    */
    void print();

    /*
    count

    intput: none
    output: none

    Note: used to return a count of all of the files in the system
    from the current directory to it's lowest child.
    */
    void count();

    /*
    help

    input: none
    output: none

    Note: Help
    */
    void help();

    /*
    ShowCursor

    input: none
    output: none

    Note: creates the cursor (->) on the screen.
    */
    void ShowCursor();

    /*
    toupper

    input: string
    output: string

    Note: I found that toupper only works for characters, so I wrote
    one for strings. (WHY ISN"T THERE ONE???)
    */
    string toupper(string S);


    /******************** used for testing ********/
    // loads an array from a text file
    void openInFile();

    // list test array contents
    void ListTestArray();

    void FileSystem::TestMakeDirs()

    };

    #endif
    ******************************************

    Code:

    *******************************************

    #include "FileSystem.h"
    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <iomanip>
    #include <fstream>


    // An array used for testing only
    int AS = 50; //Size of Array, Array Size
    int CS = 0; // current size (in use)
    string Words[50];


    using namespace std;

    FileSystem::FileSystem()
    {
    RootDir = new Directory(NULL, "/");
    CurrentDir = RootDir;
    }

    FileSystem::~FileSystem()
    {

    }


    void FileSystem::ShowCursor()
    {
    cout << "-> ";
    }

    void FileSystem::help()
    {
    cout << "The following commands are available." << endl;

    cout << "COUNT";
    cout.width(10);
    cout << "DEL";
    cout.width(10);
    cout << "DIR";
    cout.width(10);
    cout << "HELP";
    cout << endl;
    cout << "MKDIR";
    cout.width(10);
    cout << "MKFILE";
    cout.width(10);
    cout << "MOVE";
    cout.width(10);
    cout << "PRINT";
    cout << endl;
    cout << "QUIT" << endl << "Type 'HELP' to see this list again.";
    cout << endl;
    }

    void FileSystem::main()
    {
    string command;
    help();
    //ShowCursor();
    //getline(cin, command);

    do
    {
    ShowCursor();
    getline(cin, command);
    command = toupper(command);

    //Can't use switch with a string... if then else I guess...
    // help menu
    if(command == "HELP")
    {
    system("cls");
    help();
    } // make a file
    else if(command == "MKFILE")
    {
    system("cls");
    CurrentDir->MKFile();
    } // make a directory
    else if(command == "MKDIR")
    {
    system("cls");
    CurrentDir->MKDir();
    } // show files and subdirs for current directory
    else if(command == "DIR")
    {
    system("cls");
    CurrentDir->SMPrint();
    } // delete (a file or directory)
    else if(command == "DEL")
    {
    system("cls");
    CurrentDir->Delete();
    } // Quit
    else if(command == "QUIT")
    {
    system("cls");
    cout << "Quiting" << endl;
    }
    else if (command == "LOADARRAY")
    {
    openInFile();
    }
    else if(command == "SHOWARRAY")
    {
    ListTestArray();
    }
    else if(command == "TESTMKDIR")
    {
    TestMakeDirs();
    }
    else
    {
    cout << "Un-recognized command" << endl;
    }

    }while(command != "QUIT");
    }


    string FileSystem::toupper(string S)
    {
    for (int j=0; j<S.length(); ++j)
    {
    S[j]=std::toupper(S[j]);
    }

    return S;
    }


    /************************ Code for Testing only ********/
    void FileSystem::eek:penInFile()
    {
    int charLoc;

    string currentWords;
    CS = 0;
    //bool newLine = false;

    // open the input file Input.txt
    ifstream inFile("Input.txt");
    // if the file failed to open, notify the user.
    if(inFile.is_open())
    {
    getline(inFile, currentWords);
    if(currentWords.empty() == false)
    {
    do
    {
    charLoc = currentWords.find(",");
    Words[CS] = currentWords.substr(0, charLoc);
    currentWords = currentWords.substr(charLoc + 1,
    currentWords.length());
    CS++;
    }while(CS < AS && currentWords.length() > 3);

    }
    /* // as long as there is a 'word' to read from the file, loop.
    while(inFile >> currentWord && CS < AS -1)
    {

    cout << currentWord;
    CS++;
    } */

    // Close the input file
    inFile.close();
    }
    else //if the file did open, process the file.
    {
    cout << "error opening file";
    }
    }

    void FileSystem::ListTestArray()
    {
    system("cls");
    for(int i = 0; i < CS; i++)
    {
    cout << i << " " << Words << endl;
    }
    system("PAUSE");
    system("cls");
    }

    void FileSystem::TestMakeDirs()
    {
    //load the array with random words
    openInFile();
    if(CS > 0)
    {
    // make a directory for each random word
    for(int i = 0; i <=CS; i++)
    {
    cout << "Creating dir: " << Words << endl;
    CurrentDir->Create(Words);
    }
    }
    // display the directories and files
    CurrentDir->SMPrint();
    }

    ************************************

    File header:

    **************************************

    #ifndef File_h
    #define File_h

    #include <cstdlib>
    #include <iostream>
    #include <string>

    //using namespace std;

    class File
    {

    private:
    std::string Name, Extension;

    /*
    SplitName

    Inputs: FN (String)
    Output: None

    Notes: Used to split a string based on the '.' character. This
    allows the Name and Extension to be found.
    */
    void SplitName(string FN);

    public:

    /*
    Constructor

    Inputs: FullName
    Outputs: None

    Notes: Takes in the full name (name + extension) splits it.
    */
    File(string FullName);

    /*
    Constructor

    Inputs: FullName
    Outputs: None

    Notes: Takes in the full name (name + extension) splits it.
    */
    File();

    /*
    Copy Constructor
    Due to the requirement that no files in the same directory can
    have
    the same name, and the fact there is no copy required for this
    assignment the copy constructor is not required.
    */

    /*
    Copy Assignment

    Inputs: F (file)
    Outputs: bool
    */
    bool operator=(const File *F);
    File & File::eek:perator=(const File & F);

    /*
    Destructor
    Because there are no pointers used the default destructor is
    fine.
    No destructor was created for 'file'
    */

    /*
    GetName

    Inputs: None
    Outputs Name (minus extension)
    */
    string GetName();

    /*
    GetExtension

    Inputs: None
    Outputs: File Extension
    */
    string GetExtension();

    /*
    GetFileName

    Inputs: None
    Output: full file name (name and extension)
    */
    string GetFileName();

    /*
    Print

    Inputs: None
    Outputs: prints to screen full file name (name and extension)
    */
    void Print();

    /*
    operator ==

    Inputs: File F
    Outputs: bool

    Notes: If the file.Name and file.Extension are equal the files
    are equal if either is not equal, the files are not equal.
    */
    bool operator==(const File & F);

    /*
    operator==

    Input: FN (string file name)
    Output: bool

    Notes: returns true if the file uses the same name as FN
    */
    bool operator==(string FN);

    /*
    operator <

    Inputs: File F
    Outputs: bool

    Notes: If the full file name is < the 'other' file name True.
    */
    bool operator<(const File & F);

    /*
    operator <

    Inputs: FN (string file name)
    Outputs: bool

    Notes: If the full file name is < the 'other' file name True.
    */
    bool operator<(string FN);

    /*
    operator >

    Inputs: File F
    Outputs: bool
    */
    bool operator>(const File & F);

    /*
    operator >

    Inputs: FN (string file name)
    Outputs: bool
    */
    bool operator>(string FN);

    /*
    ValidName

    Input: N (name)
    Output: bool

    Note: used to determine if a name is valid for a file.
    No spaces and a dot.
    */
    bool ValidName(string &N);
    };

    #endif


    ************************

    File Code:

    ****************************

    #include "File.h"
    #include <iostream>
    #include <cstdlib>
    #include <string>

    //using namespace std;

    /*
    Constructor
    */
    File::File(string FullName)
    {
    SplitName(FullName);
    }

    File::File()
    {
    Name = "";
    Extension = "";
    }

    //GetFileName
    string File::GetFileName()
    {
    return (Name + "." + Extension);
    }

    // Copy Assignment
    bool File::eek:perator=(const File *F)
    {
    if(F->Name != "" && F->Extension != "")
    {
    Name = F->Name;
    Extension = F->Extension;

    return true;
    }
    else
    return false;
    }

    File & File::eek:perator=(const File & F)
    {
    if(F.Name != "" && F.Extension != "")
    {
    Name = F.Name;
    Extension = F.Extension;
    }
    }

    /*
    SplitName
    */
    void File::SplitName(string FN)
    {
    int charLoc; // character location
    charLoc = FN.find('.');

    // if there is no 'dot' then the Name is the Fullname (no extension)
    if(charLoc == -1)
    {
    Name = FN;
    Extension = "";
    }
    else //There is a dot so set the Name and Extension values
    {
    Name = FN.substr(0, charLoc);
    Extension = FN.substr(charLoc + 1, FN.length());
    }
    }

    bool File::ValidName(string &N)
    {
    int charLoc; // character location
    SplitName(N);

    // there must be a 'name' portion
    if(Name == "")
    return false;

    if(Extension == "")
    return false;

    charLoc = N.find(' '); // search for a space in the name anywhere
    if(charLoc == -1) // no spaces
    return true;
    else
    return false;
    }

    /*
    GetName
    */
    string File::GetName()
    {
    return Name;
    }

    /*
    GetExtension
    */
    string File::GetExtension()
    {
    return Extension;
    }

    /*
    Print
    */
    void File::print()
    {
    cout << Name << '.' << Extension;
    }

    /*
    operator==
    */
    bool File::eek:perator==(const File & F)
    {
    if(Name != F.Name)
    return false;

    if(Extension != F.Extension)
    {
    return false;
    }
    else
    {
    return true;
    }
    }


    /*
    operator<
    */
    bool File::eek:perator<(const File & F)
    {

    //if the file Name is >, then false
    if(Name > F.Name)
    return false;

    //if the file Name is <, then true
    if(Name < F.Name)
    return true;

    //if we got to here then the file Name properties are equal
    if(Extension < F.Extension) // this extension is < other, then
    true
    {
    return true;
    }
    else // this extension is NOT < other, then false
    {
    return false;
    }
    }

    bool File::eek:perator<(string FN)
    {
    if(GetFileName() > FN)
    return false;

    if(GetFileName() == FN)
    return false;

    if(GetFileName() < FN)
    return true;
    }


    /*
    operator>
    */
    bool File::eek:perator>(const File & F)
    {
    if(Name < F.Name)
    return false;

    if(Name > F.Name)
    return true;

    // if we got to here the names are equal
    if(Extension > F.Extension)
    return true;
    else
    return false;
    }

    bool File::eek:perator>(string FN)
    {
    if(GetFileName() < FN)
    return false;

    if(GetFileName() == FN)
    return false;

    if(GetFileName() > FN)
    return true;
    }


    **************************

    Main:

    ******************************

    #include <cstdlib>
    #include <iostream>
    //#include "File.h"
    //#include "Directory.h"
    #include "FileSystem.h"

    using namespace std;

    int main(int argc, char *argv[])
    {
    /*string FN;
    Directory dir("/");
    bool result;

    for(int i = 0; i <= 6; i++)
    {
    result = dir.MKFile();
    }
    dir.SMPrint();
    */
    FileSystem FS;
    FS.main();

    // cout << "Find a file position; enter file name: ";
    //getline(cin, FN);
    //dir.FindFile(dir.Files, 0, dir.FileCount -1);
    system("PAUSE");
    return EXIT_SUCCESS;
    }


    **************************

    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.

    By the way... are you independantly wealthy or just very generous with
    your time?? ;)

    Also; is there a way to get the system to email me if there is a reply?

    > Work on those things a little, and come back.
    >
    > Nobody ever said C++ was easy! Hang in there!
    > --
    > Bob R
    > POVrookie
     
    , Dec 1, 2006
    #16
  17. Guest

    wrote:
    > BobR wrote:
    > Directory::~Directory(){
    > delete[] Files;
    > // and since your vector holds pointers to 'new' objects.
    > for( size_t i(0); i < Directories.size(); ++i ){
    > delete Directories.at( i );
    > }
    > } // Dtor


    This one is much shorter.

    I have noticed in code on the net a lot of people use 'size_t' with
    their vector. Is that a specific command or is it the same as: for(int
    i = 0; i < Directories.size(); i++)

    if so, why do people use the size_t?

    (I used int i and it SEEMS to work)
     
    , Dec 1, 2006
    #17
  18. BobR Guest

    wrote in message ...
    >
    >> BobR wrote:
    >> Directory::~Directory(){
    >> delete[] Files;
    >> // and since your vector holds pointers to 'new' objects.
    >> for( size_t i(0); i < Directories.size(); ++i ){
    >> delete Directories.at( i );
    >> }
    >> } // Dtor

    >
    >This one is much shorter.


    Checking out your other post. It'll get shorter. Post later.

    >
    >I have noticed in code on the net a lot of people use 'size_t' with
    >their vector. Is that a specific command or is it the same as: for(int
    >i = 0; i < Directories.size(); i++)
    >
    >if so, why do people use the size_t?


    std::size_t is a typedef of an unsigned integral. std::vector::size_type
    (returned by .size() ) is also an unsigned type.

    >
    >(I used int i and it SEEMS to work)


    You don't have your compiler warning level up high enough or you would be
    seeing warnings like "comparing signed with unsigned". Why compare red dogs
    with blue dogs?
    If you are using Dev-C++(MinGW), put -Wall -W in the compiler flags.
    (many more in the GCC docs "GCC Command Options" sub"Options to Request or
    Suppress Warnings".).

    Are you brave?
    {
    int sz(-1);
    std::vector<int> BigV( sz );

    std::cout<<BigV.size();
    } // don't want to keep that puppy around long!

    --
    Bob R
    POVrookie
     
    BobR, Dec 1, 2006
    #18
  19. Guest

    BobR wrote:
    > wrote in message ...
    > >
    > >> BobR wrote:
    > >> Directory::~Directory(){
    > >> delete[] Files;
    > >> // and since your vector holds pointers to 'new' objects.
    > >> for( size_t i(0); i < Directories.size(); ++i ){
    > >> delete Directories.at( i );
    > >> }
    > >> } // Dtor

    > >


    Actually I had envisioned having to write something that would make
    calls on each sub-directory and it's subdirectories etc. to cascade
    through calling the destructor; but of course I don't. Since this
    destroys an instance of a Directory, that destruction calls that
    instance's destructor. It is pretty simple. (much better than what I
    had thought.)

    I tend to try to get my code working first, then try to figure out the
    destructors etc. I sort of 'build as I need' for things like copy
    constructors etc. Then if I run out of time I can hand in a working
    program with problems, not a non-working program.


    > >This one is much shorter.


    Yes; I have started some of that myself already. My overloaded
    operators are now shorter, those based on string compares are now just
    like this:

    bool Directory::eek:perator<(const Directory & D)
    {
    return Name < D.Name;

    }

    rather than with if then statements etc.

    >
    > Checking out your other post. It'll get shorter. Post later.
    >
    > >
    > >I have noticed in code on the net a lot of people use 'size_t' with
    > >their vector. Is that a specific command or is it the same as: for(int
    > >i = 0; i < Directories.size(); i++)
    > >
    > >if so, why do people use the size_t?

    >
    > std::size_t is a typedef of an unsigned integral. std::vector::size_type
    > (returned by .size() ) is also an unsigned type.
    >

    Hmmm... Okay. I will stick with the convention.
    > >
    > >(I used int i and it SEEMS to work)

    >
    > You don't have your compiler warning level up high enough or you would be
    > seeing warnings like "comparing signed with unsigned". Why compare red dogs
    > with blue dogs?
    > If you are using Dev-C++(MinGW), put -Wall -W in the compiler flags.
    > (many more in the GCC docs "GCC Command Options" sub"Options to Request or
    > Suppress Warnings".).
    >
    > Are you brave?
    > {
    > int sz(-1);
    > std::vector<int> BigV( sz );
    >
    > std::cout<<BigV.size();
    > } // don't want to keep that puppy around long!
    >
    > --
    > Bob R
    > POVrookie
     
    , Dec 1, 2006
    #19
  20. Guest

    Just wanted to let you know that I created a new, shorter specific
    posting about sorting the vector elsewhere.

    Sort a Vector of Pointers to an object, based on objects properties

    It wasn't really this topic/thread even though it's still my problem.

    I think that was the correct thing to do!
     
    , Dec 1, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    27,549
    Mike Schilling
    Mar 29, 2006
  2. Peter B. Steiger

    Can a static array contain a dynamic array of pointers?

    Peter B. Steiger, Apr 19, 2004, in forum: C Programming
    Replies:
    8
    Views:
    2,134
    Dave Thompson
    Apr 26, 2004
  3. Replies:
    2
    Views:
    587
    Victor Bazarov
    May 20, 2006
  4. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    732
  5. Craig M. Votava

    Unexpected initial null in return from split()

    Craig M. Votava, Jan 30, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    99
    Glenn Jackman
    Jan 30, 2004
Loading...

Share This Page