9

I have the following chunk of code in my constructor (This is just an example, the question isn't about split, rather about throwing a generic exception. Also, Boost library can't be used.

Transfer::Transfer(const string &dest){
  try{
    struct stat st;
    char * token;
    std::string path(PATH_SEPARATOR) // if it is \ or / this macro will solve it
    token = strtok((char*)dest.c_str(), PATH_SEPARATOR) // 
    while(token != NULL){
        path += token;
        if(stat(path.c_str(), &st) != 0){
            if(mkdir(path.c_str()) != 0){
                 std:string msg("Error creating the directory\n");
                 throw exception // here is where this question lies
            }
        }

        token = strtok(NULL, PATH_SEPARATOR);
        path += PATH_SEPARATOR;

    }
  }catch(std::exception &e){
       //catch an exception which kills the program
       // the program shall not continue working.
  }

}

What I want is to throw an exception if the directory does not exist and it can't be created. I want to throw a generic exception, how could I do it in C++? PS: dest has the following format:

dest = /usr/var/temp/current/tree
cybertextron
  • 10,547
  • 28
  • 104
  • 208

2 Answers2

16

Please check this answer. This explains how to use your own exception class

class myException: public std::runtime_error
{
    public:
        myException(std::string const& msg):
            std::runtime_error(msg)
        {}
};

void Transfer(){
  try{
          throw myException("Error creating the directory\n");
  }catch(std::exception &e){
      cout << "Exception " << e.what() << endl;
       //catch an exception which kills the program
       // the program shall not continue working.
  }

}

Also, if you don't want your own class, you can do this simply by

 throw std::runtime_error("Error creating the directory\n");
Community
  • 1
  • 1
PermanentGuest
  • 5,213
  • 2
  • 27
  • 36
  • 7
    It is a good rule of thumb to catch exceptions by constant reference. –  Jul 24 '12 at 16:45
  • 1
    I would add that it's not very scalable to exit the program in various places. This certainly shouldn't be done in code that will become part of a library. It's better to just throw and have the catch in as few places as possible (e.g. main). – Anon Mail Jul 24 '12 at 16:55
6

Your usage of strtok is incorrect - it needs a char* because it modifies the string, but it is not permitted to modify the results of a .c_str() on a std::string. The need to use a C style cast (which here is performing like a const_cast) is a big warning.

You can neatly sidestep this and the path separator portability stuff by using boost filesystem, which is likely to appear in TR2 whenever that's release. For example:

#include <iostream>
#include <boost/filesystem.hpp>

int main() {
  boost::filesystem::path path ("/tmp/foo/bar/test");
  try {
    boost::filesystem::create_directories(path);
  }
  catch (const boost::filesystem::filesystem_error& ex) {
    std::cout << "Ooops\n";
  }
}

Splits the path on the platform's separator, makes the directories if needed or throws an exception if it fails.

Community
  • 1
  • 1
Flexo
  • 87,323
  • 22
  • 191
  • 272