load std::map from text file - c++

This is a very simple thing, so I want to keep it as simple as it sounds. All I want is to load a bunch of key-value paires from a file, and populate them in to a map. I do not really care how the text is structured, as long as it is easy to read.
What i have now is:
xml with xsd generated code (overkill)
Protocol buffer (also overkill)
INI style text file
I like the syntax of the INI file, but I not want to write a parser for that. It sounds to me like I would be doing something lots of people have done before me. Is there not some sort of library to read simple structured files like this?

Since you seem to want the simplest thing humanly possible, I'm going to suggest something incredibly simple that may or may not work based on your map contents. If your map data values are strings that include spaces, this wont work. If they're strings without spaces, or numeric, you're set.
This isn't tested code, but it's close and simple so you should be fine even if it doesn't quite compile. Just change KeyType and ValueType to int, string, float, or whatever you're actually using in the file.
Set up file like:
key value
key2 value2
key3 value3
key4 value4
Read like:
KeyType key;
ValueType value;
std::map<KeyType, ValueType> myMap;
while (infile >> key >> value)
myMap[key] = value;

If you are in the MS world you can use
GetPrivateProfileSectionNames
GetPrivateProfileString
WritePrivateProfileString
to read from ini file or regestry. If you want to write Unicode make sure a newly created file gets the BOM of UTF16.

Related

Get Non Indented string from Json Object

I have a json object in c++. I am using json_cpp library.
I want to get the string from the Json::Value object. I am using it like below.
Json::Value obj;
....
....
....
string str = obj.toStyledString();
This returns the string in the pretty print format. But I want the string without any indentation. How can I do that as there are no other functions provided in the class?
You could use Json::FastWriter it does not have any indentation and formatting since it outputs everything on a single line. it is normally not suitable for 'human' consumption.
std::string toUnStyledString(const Json::Value& value)
{
Json::FastWriter writer;
return writer.write( value );
}
The function toStyledString also simply uses a Json::StyledWriter if you look into the definition of Json::Value::toStyledString.
Well, if this library doesn't provide appropriate methods then you could write them yourself. The JSON format is rather simple, so I don't think that it will take a lot of work.
Here you can find a good graphical representation of JSON format:
http://json.org
P.S. I've never worked with this particular library, so I propose sort of a general solution.
UPDATE: another option is to get a string returned by toStyledString() and remove indentation. But it requires string processing and will probably be resource consuming. Note that you can't just remove tabs/spaces/new line symbols, because they can be a part of JSON object.
Why do you want unindented string again?

Looping through all items of the JSON with text index on JsonCPP

{
"80550560": {"name":" HAdailton Cesar", "name2": "T-Max"},
"5987810": {"name": "Adnax", "name2": "Adna Zaza"}
}
I have this input and I need to output all the names that comes in the input, but the problem is that i don't have integer organized index, I would have to get the string number and also I don't know what the string text index is going to be.
I would imagine something like this, but I don't know how to get the 'string_text' from JsonCPP
res[string_text]["name"];
Use getMemberNames to get a list.
I'm pretty sure it is possible to iterate through too, but I have always opted to use `getMemberNames'
Reading the documentation for the Json::Value class, it have iterator capabilities like begin and end, so it should be possible to iterate the values like a standard container.

Search HTML lines and remove lines that don't start with </form></td><td><a

I have an HTML file with very bad formatted code that I get from a website, I want to extract some very small pieces of information.
I am only interested in lines that start like this:
</form></td><td> <b>user897</b></td></tr><tr><td>HouseA</td><td>2</td><td class="entriesTableRow-gamename">HouseA Type12 <span class="entriesTableRow-moredetails"></span></td><td>1 of 2</td><td>user123</td><td>10</td><td>
and I want to extract 3 fields:
A:HouseA
B:HouseA Type12
C:user123
D:10
I know I've seen people recommend HTML Agility Pack and lib2xml but I really don't think I need all that. My app is in C/C++.
I am already using getline to start reading lines, I am just not sure what's the best way to proceed. Thanks!
std::ifstream data("Home.html");
std::string line;
while(std::getline(data,line))
{
linenum++;
std::stringstream lineStream(line);
std::string user;
if (strncmp(line.c_str(), "</form></td><td>",strlen("</form></td><td>")) == 0)
{
printf("found a wanted line in line:%d\n", linenum);
}
}
In the general case, an XML/HTML parser is likely the best way here, as it will be robust against differing input. (Whatever you do, don't use regexps!)
Update
However, if you're targetting specific input, as it seems that you're doing, you can use sscanf (as you suggest) or cin.read() or regexp to scan manually.
Just beware that this code can break at any moment that the HTML changes (even just with whitespace).
Therefore, my/our recommendation is to use a proper tool for the job. XML/HTML is not raw text, and should not be treated as such.
How about writing a python script instead? :)

Which of the C++ INI (or any other format) loading libraries support multiple keys?

I'm currently using SimpleINI and I'm not sure if I can do it with this but my configuration file is going to look like this
name = someone
service = something
match = blahblahblah
match = something
match = some more junk
I know in advance which of the keys support multiple values and I want those values to be stored in an array or something so I can loop through them later (order doesn't matter).
If not SimpleIni then which other library will support this? I'm a beginner to C++ so I'm looking for something easy to use. I have boost libraries but not sure if I should use it (seems complicated).
My application is windows specific so I don't need a cross platform solution in this case.
I've already seen this question - What is the easiest way to parse an INI File in C++? but not sure which of them I can use to accomplish this.
Any suggestions?
Do you not have an option to change the names to something like match1, match2, match3, etc? That would seem to be the most straight forward way.
Beyond that, I've done things like this all the time. I simply wrote a few lines of code to parse the text file myself. It's not a complex task. But if you'd prefer to work with regular INI files, you need to look at changing the value names in the INI file.
Given you're on windows, you may not need a library at all.
You would never know it by just browsing the documentation, but GetPrivateProfileString() in the WINAPI may do exactly what you want.
My Qt solution on the other SO thread applies. It is better because
Cross platform
Easy conversion to values other than strings
Simple
If you have an ini file like this (can be auto-generated from your list of objects using Qt API)
[Matches]
1\match=1
2\match=2
3\match=3
size=3
Here is the code that read them back
QSettings settings("test.ini", QSettings::IniFormat);
int size = settings.beginReadArray("Matches");
for (int i = 0; i < size; ++i) {
settings.setArrayIndex(i);
std::cout << settings.value("match").toInt() << std::endl;
}
settings.endArray();
Of course, another obvious option will be to use comma separated string as your value and use QString::split()
SimpleINI accepts multiKey.
/** Are multiple values permitted for the same key? */
bool m_bAllowMultiKey;
[section]
name = someone
service = something
match = value1
match = othervalue
match = anotherValue
match = value4
Just create the CSimpleIniA with the second parameter as true.
// CSimpleIniA(bool a_bIsUtf8, bool a_bAllowMultiKey, bool a_bAllowMultiLine)
CSimpleIniA myINI{ false,true,false };
Use GetAllValues to get a list with all the values.
// from SimpleIni.h => typedef std::list<Entry> TNamesDepend;
CSimpleIniA::TNamesDepend values;
myINI.GetAllValues("section", "match", values);
Header file: SimpleIni.h

wistringstream from an xml file to an integer?

const XMLDataNode *pointsNode = node->GetChildren().at(0);
std::wistringstream pointsstrm(*pointsNode->GetInnerText());
pointsstrm >> loadedGame.points;
This is code I've written to pull an int from an XML file and pass it into loadedGame.points (an int). However, this isn't working. It compiles but doens't give the right value. Why is that? XMLDataNode is a class that manipulates xmllite.dll.
Time for some wild guesses!
I'll bet you that the text you get from *pointsNode->GetInnerText() isn't what you think it is. Have you checked that it is indeed exactly the text you want? In particular, could it contain whitespace? Parsing a nicely formatted (i.e. indented, broken into lines, etc) XML file without a schema to reference ends up meaning that all sorts text nodes involving whitespace will end up in your DOM tree.