INI files are a frequently used system configuration method by technicians. It is cumbersome to read and quickly identify the content in ini files. The powerful feature of STL is its ability to quickly implement sorting, searching, recognition, and other functions. In this article, map, string, vector, ifstream, and so on in STL are used to quickly implement the class IniFile? For INI file recognition ?. IniFile provides common search functions and complete source code.
1. design requirements:
The INI file format is generally as follows:
[Section1]
Key1 = value1
Key2 = value2
......
[Section2]
Key1 = value1
Key2 = value2 # comment
......
The actual example is:
# Ini for path
[Path]
Dictfile =/home/tmp/dict. dat
Inputfile =/home/tmp/input.txt
Outputfile =/home/tmp/output.txt
# Ini for exe
[Exe]
User = winter // user name
Passwd = 1234567 # pass word
Database = mydatabase
There are five elements: section name, Key name, value, comment # Or //, starting with the flag "[" "]" "= ". The relationship between search items is sectiong-key and value. The value must be obtained. Class IniFile? Two functions are implemented: Read the INI file and read the value corresponding to the sect-key. The following interface is implemented:
Class IniFile {
Public:
IniFile ();
// Open the INI File
Bool open (const char * pinipath );
// Read the value
Const char * read (const char * expect CT, const char * pkey );
};
2. Design implementation:
Use ifstream to read the content of the INI file by row
Identify the strings in each row and analyze the sectiong, key, value, and comments.
Use map> to record all sectiong-key and value.
Redefinition of class IniFile?
Typedef map <string, string, less <string> strMap;
Typedef strMap: iterator strMapIt;
Const char * const MIDDLESTRING = "_____***_______";
Class IniFile
{
Public:
IniFile (){};
~ IniFile (){};
Bool open (const char * pinipath)
{
Return do_open (pinipath );
}
String read (const char * expect CT, const char * pkey)
{
String mapkey = Country CT;
Mapkey + = MIDDLESTRING;
Mapkey + = pkey;
StrMapIt it = c_inimap.find (mapkey );
If (it = c_inimap.end ())
Return "";
Else
Return it-> second;
}
Protected:
Bool do_open (const char * pinipath)
{
Ifstream fin (pinipath );
If (! Fin. is_open ())
Return false;
Vector <string> strvect;
While (! Fin. eof ())
{
String inbuf;
Getline (fin, inbuf, '/N ');
Strvect. push_back (inbuf );
}
If (strvect. Empty ())
Return false;
For_each (strvect. Begin (), strvect. End (), analyzeini (c_inimap ));
Return! C_inimap.empty ();
}
Strmap c_inimap;
};
Do_open is a function used to initialize ini content. Use ifstream fin to open a file, and then use is_open to determine whether the file is opened normally. When reading files sequentially, use EOF () to determine whether the file is at the end of the file. Getline is a character processing function that reads a row from fin directly. Then, use the while loop to filter characters such as spaces at the end of a row. Finally, it is saved to a vector to complete text reading. Which of the following is worth noting: Do you know why?
Use ifstream and Getline instead of fopen and fread.
Use is_open to determine whether to enable it, rather than directly reading it.
Use push_pack of vector instead of insert.
Use empty to determine whether it is null, instead of using size () = 0.
Next, use the for_each function to extract the string content. Declare a structure to overload the operator. The Code is as follows:
Struct analyzeini {
String strsect;
StrMap * pmap;
Analyzeini (strMap & strmap): pmap (& strmap ){}
Void operator () (const string & strini)
{
Int first = strini. find ('[');
Int last = strini. rfind (']');
If (first! = String: npos & last! = String: npos & first! = Last + 1)
{
Strsect = Strini. substr (first + 1, last-first-1 );
Return;
}
If (strsect. Empty ())
Return;
If (first = Strini. Find ('=') = string: NPOs)
Return;
String strtmp1 = Strini. substr (0, first );
String strtmp2 = Strini. substr (first + 1, string: NPOs );
First = strtmp1.find _ first_not_of ("/t ");
Last = strtmp1.find _ last_not_of ("/t ");
If (first = string: npos | last = string: npos)
Return;
String strkey = strtmp1.substr (first, last-first + 1 );
First = strtmp2.find _ first_not_of ("/t ");
If (last = strtmp2.find ("/t #", first ))! = String: npos) |
(Last = strtmp2.find ("#", first ))! = String: npos) |
(Last = strtmp2.find ("/t //", first ))! = String: npos) |
(Last = strtmp2.find ("//", first ))! = String: npos ))
{
Strtmp2 = strtmp2.substr (0, last-first );
}
Last = strtmp2.find _ last_not_of ("/t ");
If (first = string: npos | last = string: npos)
Return;
String value = strtmp2.substr (first, last-first + 1 );
String mapkey = strsect + MIDDLESTRING;
Mapkey + = strkey;
(* Pmap) [mapkey] = value;
Return;
}
};
The string search and string functions are widely used here. String's find_last_of series and find series are indeed very powerful. If none of the strings are found, a variable string: npos is returned.
The function first looks for sectiong, and then separates the key and value values. If yes, add the section and key values to the middlestring to form a new string and insert it into the map. It is worth noting that:
* If for_each is used, parameters can be passed in the structure. * String search function and return value * string link and Merge function. * Use of map subscript operators.
3. Specific Use
Put all the code in a header file. When others use it in the future, they only need to include the header file. Click to view the INIFILE. h file. In the process of use, pay attention to determine the return value. The Code is as follows:
# Include <iostream>
# Include "INIFILE. H"
Using namespace STD;
Int main ()
{
INIFILE ini;
If (! INI. Open ("test. ini "))
Return-1;
String strvalue = ini. Read ("sect1", "key1 ");
If (strvalue. Empty ())
Return-1;
Else
Cout <"value =" <strvalue <endl;
Return 0;
}