Challenge 44

Description

The purpose of this challenge is to use exception handling constructs.

The goal is to verify that a config file is properly formatted and contains valid data and structure. Think of a game that loads all the game settings when the game is started or loaded. If the settings file is corrupted, the game probably shouldn’t attempt to load. Only when the settings file is completely loaded will the game be loaded and played (the happy path).

Requirements

  1. Write an exception class that inherits from C++ exception class
    class ConfigFileError : public exception
    {
      public:
        const char * what() const throw()
        {
          return "Configuration file is badly formed";
        }
    };
    
  2. Write a class ConfigFileMissingKey, that inherits from ConfigFileError. This class will have a what() function that returns “Missing key”
  3. Write a class ConfigFileBadKey, that inherits from ConfigFileError. This class will have a what() function that returns “Bad key specification”
  4. Write a class ConfigFileMissingSeparator, that inherits from ConfigFileError. This class will have a what() function that returns “Missing separator”
  5. Write a class ConfigFile. This class does not inherit from any  other class.In this class,
    1. create a private function bool contains_separator(string line, char sep = ‘=’). This function will examine line for the presence of sep. Note that, by default, sep contains an equal sign. Do not have the code specifically check for an equal sign. This function returns true if line contains sep, and false otherwise.
    2. create a private function bool is_name_valid(string name). This function returns true if name is a valid name that follows C++ basic variable naming requirements (starts with a letter or underscore) and false otherwise.
    3. create a private function bool is_comment(string line). This function returns true if the first character of line is a semi-colon, and false otherwise.
    4. create a private function bool is_missing_key(string line). This function will return true if line begins with an equal sign, and false otherwise.
    5. create a public function bool load(string filename). This function will read all lines out of filename. The lines of the configuration file passed in filename will be evaluated. Each entry in the file will be checked for correctness and the function will throw exceptions for each failed validation.
      bool load(string filename)
      {
         string line;     // stores a line of text from the file
         
         // code to read lines of text from a file
         ifstream fin;    // don't forget to include fstream
         fin.open(filename);
         while (getline(fin, line)) 
         {
           // at this point, line contains a line of text from the file
      
           // remember to check for comments and blank lines -- these 
           // should not trigger exceptions
           // one exception check
           if (!is_name_valid(line))
             throw ConfigFileBadKey();
           
           // throw the other exceptions calling the exceptions defined earlier
         }
         fin.close();
      
         return true;
      }
      

Notes

Remember that when an exception is triggered, the code will stop running and the rest of the exception handlers will not be able to run. When testing, after you prove that your code can catch a particular exception, you should fix that offending line of text in the config file. This will allow the code to continue (since that line no longer triggers an exception) to test the other lines, and possibly catch other exceptions.

Sample main()

int main()
{
  ConfigFile config;

  try
  {
    if (config.load("config.ini"))
      cout << "Config file verified" << endl;
  }
  catch (ConfigFileMissingKey & ex)
  {
    cerr << ex.what() << endl;
  }
  // add more exception handlers for all exceptions 
  // also add a catch-all handler

  return 0;
}

CATALOG ID: CPP-CHAL00044

Print Requirements