Error Line Numbers

When we encounter an error parsing a file, how can we output an error message that includes where the error occurred - for example, the line number within the file?

To include the line number in error messages during parsing, we need to keep track of the current line number as we process the file. We can modify the ParseConfig() method to do this and pass the line number to ProcessLine().

Tracking the Line Number

Here's how we can modify ParseConfig() and ProcessLine() to track and use the line number:

// config.txt
WINDOW_TITLE: My Game
INVALID_FORMAT
WINDOW_WIDTH: 800
INVALID_KEY: 123
#include <SDL.h>

#include <iostream>
#include <string>
#include <vector>

class Config {
 public:
void ParseConfig(const std::string& Content) { size_t Start{0}; size_t End{Content.find('\n', Start)}; int LineNumber{1}; while (End != std::string::npos) { ProcessLine(Content.substr( Start, End - Start), LineNumber); Start = End + 1; End = Content.find('\n', Start); LineNumber++; } ProcessLine( Content.substr(Start), LineNumber); } void ProcessLine( const std::string& Line, int LineNumber ) { size_t Delim{Line.find(": ")}; if (Delim == std::string::npos) { std::cout << "Error: Invalid format on " "line " << LineNumber << "\n"; return; } std::string Key{Line.substr(0, Delim)}; std::string Value{Line.substr(Delim + 2)}; if (Key == "WINDOW_TITLE") { WindowTitle = Value; } else if (Key == "WINDOW_WIDTH") { WindowWidth = std::stoi(Value); } else if (Key == "WINDOW_HEIGHT") { WindowHeight = std::stoi(Value); } else if (Key == "LEVELS") { ParseLevels(Value); } else { std::cout << "Error: Unknown key '" << Key << "' on line " << LineNumber << "\n"; } }
}; int main() { Config MyConfig; MyConfig.Load("config.txt"); }
Error: Invalid format on line 2
Error: Unknown key 'INVALID_KEY' on line 4

Explanation

  1. LineNumber in ParseConfig(): We initialize LineNumber to 1 and increment it each time we process a line.
  2. Passing LineNumber to ProcessLine(): We pass the LineNumber as an argument to ProcessLine().
  3. Using LineNumber in Error Messages: In ProcessLine(), we can now include the LineNumber in any error messages we output.

Further Improvements

  • Error Handling in ParseLevels(): You could add similar line number tracking to ParseLevels() to provide more specific error locations if there are issues parsing the LEVELS data.
  • Error Reporting Class/Structure: For more complex error handling, you might create a dedicated class or structure to store error information (line number, error type, message, etc.) and pass it around as needed.
  • Throwing Exceptions: Instead of just printing error messages, you could throw exceptions when errors occur. This would allow you to handle errors in a more structured way (e.g., using try-catch blocks).

Parsing Data using std::string

Learn how to read, parse, and use config files in your game using std::string and SDL_RWops

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Moving Past Delimiters
Why do we use Start = End + 1 to move to the next position after finding a delimiter (like \n or ,)?
Trimming Extra Spaces
What if a key in our config file has multiple spaces before or after it, such as " KEY : VALUE"? How can we trim leading/trailing spaces from the key and value?
Config from Network Stream
What changes would be needed to load the config from a different source, like a network stream, instead of a file?
Saving Config Changes
How could we extend the Config class to allow writing the configuration back to a file, effectively saving changes made in-game?
Implementing a Default Config
How could we implement a default configuration that is used if the config file is missing or invalid?
Or Ask your Own Question
Purchase the course to ask your own questions