How to parse a simple config file in C++

This article explains how to parse a config file in the form name=value similar to the windows .ini files. The code removes all whitespaces from the lines and skips empty lines and lines containing comments.

The code explained in this article can parse a file in this form:

# config parameters of an example file
generates_output=true
file_format=txt

but also in this disordered form:

  # config parameters of an example file

generates_output  =  false
  file_format=doc

The code below parses the config files. After we successfully load the file, we read it line by line. We remove all the whitespaces from the line and skip the line if it is empty or contains a comment (indicated by "#"). After that, we split the string "name=value" at the delimiter "=" and print the name and the value.

#include<iostream>
#include<fstream>
#include<algorithm>

int main()
{
    std::ifstream cFile ("config2.txt");
    if (cFile.is_open())
    {
        std::string line;
        while(getline(cFile, line)){
            line.erase(remove_if(line.begin(), line.end(), isspace),
                                 line.end());
            if(line[0] == '#' || line.empty())
                continue;
            auto delimiterPos = line.find("=");
            auto name = line.substr(0, delimiterPos);
            auto value = line.substr(delimiterPos + 1);
            std::cout << name << " " << value << '\n';
        }
        cFile.close();
    }
    else
        std::cout << "Unable to open config file." << '\n';
    return 0;
}

Warning: If you added using namespace std at the top of your source code, you have to use ::isspace rather than isspace. This is because we want to use ::isspace from the global namespace (indicated by the scope operator ::) rather than std::isspace from what would be the current namespace (std).

line.erase(remove_if(line.begin(), line.end(), ::isspace), line.end());   

The following paragraphs explain the details of the implementation.

Removing whitespaces from a line

Before doing any further processing we remove all the whitespaces from the line. This is accomplished with the help of several functions, namely erase(), remove_if() and isspace.

line.erase(remove_if(line.begin(), line.end(), isspace), line.end());          

remove_if()

The function remove_if() takes a sequence (i.e. the line) and transforms it into a sequence without the undesired characters (i.e. the whitespaces). The length of the sequence does not get altered, however the elements representing the undesired characters are moved to the end of the sequence and remain in an unspecified state. The function returns an iterator to the new end of the sequence. This is illustrated below. remove_if() takes three arguments. The first two arguments are forward iterators to the initial and final positions in the sequence. The last argument is a function pointer or a function object (in our case the address of the function isspace).

line.erase(remove_if(line.begin(), line.end(), isspace), line.end());          

isspace

The function isspace checks whether an individual character is a whitespace character. Behind the scenes, isspace accepts a single element of the sequence as an argument and returns a value convertible to bool, i.e. true or false.

line.erase(remove_if(line.begin(), line.end(), isspace), line.end());          
Note: In "C" locale whitespace characters include the space (’ ’), form feed (’\f’), line feed (’\n’), carriage return (’\r’), horizontal tab (’\t’), and vertical tab (’\v’). The backspace character (’\b’) is not a whitespace character in "C" locale. Different locales might define other whitespace characters. From C++ In a Nutshell: A Desktop Quick Reference By Ray Lischner.

string::erase()

The method std::string::erase() erases the sequence of characters in the range (first, last). In our case, it removes the part between the new end of the sequence returned by remove_if and the original end of the sequence. This can be seen in the figure below.

line.erase(remove_if(line.begin(), line.end(), isspace), line.end());        

Splitting a string at the delimiter

The code below splits the line at the delimiter =. Notice, that we are processing the line under the assumption that there are no whitespace characters, as they have all been removed in the previous step. We firstly find the position of the delimiter = with std::string::find(). After that, we use the method std::string::substr(pos, len) to extract the name and the value. The method substr(pos,len) creates a substring starting at the position pos and spans len characters (or until the end of the string, whichever comes first). Notice, that in the second case we pass only the first parameter, i.e. the position. The default value, i.e. all characters until the end of the string, is used as the second parameter.

auto delimiterPos = line.find("=");
auto name = line.substr(0, delimiterPos);
auto value = line.substr(delimiterPos + 1);


Latest update: 20.04.2016
Created: 2015
© Walletfox.com, 2017