<p>I'm trying to parse an INI file using C++. Any tips on what is the best way to achieve this? Should I use the Windows API tools for INI file processing (with which I am totally unfamiliar), an open-source solution or attempt to parse it manually?</p>

[{'answer_id': 12636, 'author': 'Lars Mæhlum', 'author_id': 960, 'author_profile': 'https://Stackoverflow.com/users/960', 'pm_score': 5, 'selected': False, 'text': '<p>I have never parsed ini files, so I can\'t be too specific on this issue.<br>\nBut i have one advice:<br>\n<strong>Don\'t reinvent the wheel as long as an existing one meets your requirements</strong></p>\n\n<p><a href="http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files" rel="noreferrer">http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files</a><br>\n<a href="http://sdl-cfg.sourceforge.net/" rel="noreferrer">http://sdl-cfg.sourceforge.net/</a><br>\n<a href="http://sourceforge.net/projects/libini/" rel="noreferrer">http://sourceforge.net/projects/libini/</a><br>\n<a href="http://www.codeproject.com/KB/files/config-file-parser.aspx" rel="noreferrer">http://www.codeproject.com/KB/files/config-file-parser.aspx</a></p>\n\n<p>Good luck :)</p>\n'}, {'answer_id': 12677, 'author': 'Joel Spolsky', 'author_id': 4, 'author_profile': 'https://Stackoverflow.com/users/4', 'pm_score': 8, 'selected': True, 'text': '<p>You can use the Windows API functions, such as <a href="https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprivateprofilestring" rel="noreferrer">GetPrivateProfileString()</a> and <a href="https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprivateprofileint" rel="noreferrer">GetPrivateProfileInt()</a>.</p>\n'}, {'answer_id': 12684, 'author': 'crashmstr', 'author_id': 1441, 'author_profile': 'https://Stackoverflow.com/users/1441', 'pm_score': 2, 'selected': False, 'text': '<p>Unless you plan on making the app cross-platform, using the Windows API calls would be the best way to go. Just ignore the note in the API documentation about being provided only for 16-bit app compatibility.</p>\n'}, {'answer_id': 23820, 'author': 'Adam Mitz', 'author_id': 2574, 'author_profile': 'https://Stackoverflow.com/users/2574', 'pm_score': 7, 'selected': False, 'text': '<p>If you need a cross-platform solution, try Boost\'s <a href="http://www.boost.org/doc/libs/1_36_0/doc/html/program_options.html" rel="noreferrer">Program Options</a> library.</p>\n'}, {'answer_id': 116413, 'author': 'Harold Ekstrom', 'author_id': 8429, 'author_profile': 'https://Stackoverflow.com/users/8429', 'pm_score': 4, 'selected': False, 'text': '<p>I use <a href="https://github.com/brofield/simpleini" rel="noreferrer">SimpleIni</a>. It\'s cross-platform.</p>\n'}, {'answer_id': 371977, 'author': 'Christopher Lightfoot', 'author_id': 24525, 'author_profile': 'https://Stackoverflow.com/users/24525', 'pm_score': 2, 'selected': False, 'text': '<p>Have you tried <a href="http://www.hyperrealm.com/libconfig/" rel="nofollow noreferrer">libconfig</a>; very JSON-like syntax. I prefer it over XML configuration files.</p>\n'}, {'answer_id': 1964505, 'author': 'Mike', 'author_id': 124476, 'author_profile': 'https://Stackoverflow.com/users/124476', 'pm_score': 3, 'selected': False, 'text': '<p>this question is a bit old, but I will post my answer. I have tested various INI classes (you can see them on my <a href="http://www.24hsoftware.com/DevelopersForum/CrossPlatform-C-Library.html#comment-1400" rel="noreferrer">website</a>) and I also use simpleIni because I want to work with INI files on both windows and winCE.\nWindow\'s GetPrivateProfileString() works only with the registry on winCE.</p>\n\n<p>It is very easy to read with simpleIni. Here is an example:</p>\n\n<pre><code>#include "SimpleIni\\SimpleIni.h"    \nCSimpleIniA ini;\nini.SetUnicode();\nini.LoadFile(FileName);\nconst char * pVal = ini.GetValue(section, entry, DefaultStr);\n</code></pre>\n'}, {'answer_id': 4343216, 'author': 'Dat Chu', 'author_id': 82159, 'author_profile': 'https://Stackoverflow.com/users/82159', 'pm_score': 4, 'selected': False, 'text': '<p>If you are already using Qt</p>\n\n<pre><code>QSettings my_settings("filename.ini", QSettings::IniFormat);\n</code></pre>\n\n<p>Then read a value</p>\n\n<pre><code>my_settings.value("GroupName/ValueName", &lt;&lt;DEFAULT_VAL&gt;&gt;).toInt()\n</code></pre>\n\n<p>There are a bunch of other converter that convert your INI values into both standard types and Qt types. See Qt documentation on QSettings for more information.</p>\n'}, {'answer_id': 15485446, 'author': 'gast128', 'author_id': 1079347, 'author_profile': 'https://Stackoverflow.com/users/1079347', 'pm_score': 2, 'selected': False, 'text': '<p>If you are interested in platform portability, you can also try Boost.PropertyTree. It supports ini as persistancy format, though the property tree my be 1 level deep only.</p>\n'}, {'answer_id': 18209017, 'author': 'nimcap', 'author_id': 87987, 'author_profile': 'https://Stackoverflow.com/users/87987', 'pm_score': 3, 'selected': False, 'text': '<p><a href="https://code.google.com/p/inih/" rel="noreferrer">inih</a> is a simple ini parser written in C, it comes with a C++ wrapper too. Example usage:</p>\n\n<pre><code>#include "INIReader.h"    \n\nINIReader reader("test.ini");\n\nstd::cout &lt;&lt; "version="\n          &lt;&lt; reader.GetInteger("protocol", "version", -1) &lt;&lt; ", name="\n          &lt;&lt; reader.Get("user", "name", "UNKNOWN") &lt;&lt; ", active="\n          &lt;&lt; reader.GetBoolean("user", "active", true) &lt;&lt; "\\n";\n</code></pre>\n\n<p>The author has also a list of existing libraries <a href="http://blog.brush.co.nz/2009/02/inih/" rel="noreferrer">here</a>.</p>\n'}, {'answer_id': 28415806, 'author': 'Ragav', 'author_id': 1153349, 'author_profile': 'https://Stackoverflow.com/users/1153349', 'pm_score': 1, 'selected': False, 'text': '<p>Maybe a late answer..But, worth knowing options..If you need a cross-platform solution , definitely you can try GLIB,, its interesting.. (<a href="https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html" rel="nofollow">https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html</a>)</p>\n'}, {'answer_id': 48179083, 'author': '12oclocker', 'author_id': 8936790, 'author_profile': 'https://Stackoverflow.com/users/8936790', 'pm_score': 2, 'selected': False, 'text': '<p>I know this question is very old, but I came upon it because I needed something cross platform for linux, win32... I wrote the function below, it is a single function that can parse INI files, hopefully others will find it useful.</p>\n\n<p>rules &amp; caveats: \nbuf to parse must be a NULL terminated string. Load your ini file into a char array string and call this function to parse it.\nsection names must have [] brackets around them, such as this [MySection], also values and sections must begin on a line without leading spaces. It will parse files with Windows \\r\\n or with Linux \\n line endings. Comments should use # or // and begin at the top of the file, no comments should be mixed with INI entry data. Quotes and ticks are trimmed from both ends of the return string. Spaces are only trimmed if they are outside of the quote. Strings are not required to have quotes, and whitespaces are trimmed if quotes are missing. You can also extract numbers or other data, for example if you have a float just perform a atof(ret) on the ret buffer.</p>\n\n<pre><code>//  -----note: no escape is nessesary for inner quotes or ticks-----\n//  -----------------------------example----------------------------\n//  [Entry2]\n//  Alignment   = 1\n//  LightLvl=128\n//  Library     = 5555\n//  StrValA =  Inner "quoted" or \'quoted\' strings are ok to use\n//  StrValB =  "This a "quoted" or \'quoted\' String Value"\n//  StrValC =  \'This a "tick" or \'tick\' String Value\'\n//  StrValD =  "Missing quote at end will still work\n//  StrValE =  This is another "quote" example\n//  StrValF =  "  Spaces inside the quote are preserved "\n//  StrValG =  This works too and spaces are trimmed away\n//  StrValH =\n//  ----------------------------------------------------------------\n//12oClocker super lean and mean INI file parser (with section support)\n//set section to 0 to disable section support\n//returns TRUE if we were able to extract a string into ret value\n//NextSection is a char* pointer, will be set to zero if no next section is found\n//will be set to pointer of next section if it was found.\n//use it like this... char* NextSection = 0;  GrabIniValue(X,X,X,X,X,&amp;NextSection);\n//buf is data to parse, ret is the user supplied return buffer\nBOOL GrabIniValue(char* buf, const char* section, const char* valname, char* ret, int retbuflen, char** NextSection)\n{\n    if(!buf){*ret=0; return FALSE;}\n\n    char* s = buf; //search starts at "s" pointer\n    char* e = 0;   //end of section pointer\n\n    //find section\n    if(section)\n    {\n        int L = strlen(section);\n        SearchAgain1:\n        s = strstr(s,section); if(!s){*ret=0; return FALSE;}    //find section\n        if(s &gt; buf &amp;&amp; (*(s-1))!=\'\\n\'){s+=L; goto SearchAgain1;} //section must be at begining of a line!\n        s+=L;                                                   //found section, skip past section name\n        while(*s!=\'\\n\'){s++;} s++;                              //spin until next line, s is now begining of section data\n        e = strstr(s,"\\n[");                                    //find begining of next section or end of file\n        if(e){*e=0;}                                            //if we found begining of next section, null the \\n so we don\'t search past section\n        if(NextSection)                                         //user passed in a NextSection pointer\n        { if(e){*NextSection=(e+1);}else{*NextSection=0;} }     //set pointer to next section\n    }\n\n    //restore char at end of section, ret=empty_string, return FALSE\n    #define RESTORE_E     if(e){*e=\'\\n\';}\n    #define SAFE_RETURN   RESTORE_E;  (*ret)=0;  return FALSE\n\n    //find valname\n    int L = strlen(valname);\n    SearchAgain2:\n    s = strstr(s,valname); if(!s){SAFE_RETURN;}             //find valname\n    if(s &gt; buf &amp;&amp; (*(s-1))!=\'\\n\'){s+=L; goto SearchAgain2;} //valname must be at begining of a line!\n    s+=L;                                                   //found valname match, skip past it\n    while(*s==\' \' || *s == \'\\t\'){s++;}                      //skip spaces and tabs\n    if(!(*s)){SAFE_RETURN;}                                 //if NULL encounted do safe return\n    if(*s != \'=\'){goto SearchAgain2;}                       //no equal sign found after valname, search again\n    s++;                                                    //skip past the equal sign\n    while(*s==\' \'  || *s==\'\\t\'){s++;}                       //skip spaces and tabs\n    while(*s==\'\\"\' || *s==\'\\\'\'){s++;}                       //skip past quotes and ticks\n    if(!(*s)){SAFE_RETURN;}                                 //if NULL encounted do safe return\n    char* E = s;                                            //s is now the begining of the valname data\n    while(*E!=\'\\r\' &amp;&amp; *E!=\'\\n\' &amp;&amp; *E!=0){E++;} E--;         //find end of line or end of string, then backup 1 char\n    while(E &gt; s &amp;&amp; (*E==\' \' || *E==\'\\t\')){E--;}             //move backwards past spaces and tabs\n    while(E &gt; s &amp;&amp; (*E==\'\\"\' || *E==\'\\\'\')){E--;}            //move backwards past quotes and ticks\n    L = E-s+1;                                              //length of string to extract NOT including NULL\n    if(L&lt;1 || L+1 &gt; retbuflen){SAFE_RETURN;}                //empty string or buffer size too small\n    strncpy(ret,s,L);                                       //copy the string\n    ret[L]=0;                                               //null last char on return buffer\n    RESTORE_E;\n    return TRUE;\n\n    #undef RESTORE_E\n    #undef SAFE_RETURN\n}\n</code></pre>\n\n<p>How to use... example....</p>\n\n<pre><code>char sFileData[] = "[MySection]\\r\\n"\n"MyValue1 = 123\\r\\n"\n"MyValue2 = 456\\r\\n"\n"MyValue3 = 789\\r\\n"\n"\\r\\n"\n"[MySection]\\r\\n"\n"MyValue1 = Hello1\\r\\n"\n"MyValue2 = Hello2\\r\\n"\n"MyValue3 = Hello3\\r\\n"\n"\\r\\n";\nchar str[256];\nchar* sSec = sFileData;\nchar secName[] = "[MySection]"; //we support sections with same name\nwhile(sSec)//while we have a valid sNextSec\n{\n    //print values of the sections\n    char* next=0;//in case we dont have any sucessful grabs\n    if(GrabIniValue(sSec,secName,"MyValue1",str,sizeof(str),&amp;next)) { printf("MyValue1 = [%s]\\n",str); }\n    if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0))     { printf("MyValue2 = [%s]\\n",str); }\n    if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0))     { printf("MyValue3 = [%s]\\n",str); }\n    printf("\\n");\n    sSec = next; //parse next section, next will be null if no more sections to parse\n}\n</code></pre>\n'}, {'answer_id': 55581055, 'author': 'user1867382', 'author_id': 1867382, 'author_profile': 'https://Stackoverflow.com/users/1867382', 'pm_score': 2, 'selected': False, 'text': '<p>I ended up using inipp which is not mentioned in this thread.</p>\n\n<p><a href="https://github.com/mcmtroffaes/inipp" rel="nofollow noreferrer">https://github.com/mcmtroffaes/inipp</a></p>\n\n<p>Was a MIT licensed header only implementation which was simple enough to add to a project and 4 lines to use.</p>\n'}]
['https://Stackoverflow.com/questions/12633', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1467/']