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
LineNumber
inParseConfig()
: We initializeLineNumber
to1
and increment it each time we process a line.- Passing
LineNumber
toProcessLine()
: We pass theLineNumber
as an argument toProcessLine()
. - Using
LineNumber
in Error Messages: InProcessLine()
, we can now include theLineNumber
in any error messages we output.
Further Improvements
- Error Handling in
ParseLevels()
: You could add similar line number tracking toParseLevels()
to provide more specific error locations if there are issues parsing theLEVELS
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