I'm new to C++ and have had some help with my program to compare two XML files. This is the code I have:
#include "pugixml.hpp"
#include <iostream>
#include <unordered_map>
int main() {
pugi::xml_document doca, docb;
std::map<string, pugi::xml_node> mapa, mapb;
if (!doca.load_file("a.xml") || !docb.load_file("b.xml"))
return 1;
for (auto& node: doca.child("site_entries").children("entry")) {
const char* id = node.child_value("id");
mapa[new std::string(id, strlen(id))] = node;
}
for (auto& node: docb.child("site_entries").children("entry"))
const char* idcs = node.child_value("id");
std::string id = new std::string(idcs, strlen(idcs));
if (!mapa.erase(id)) {
mapb[id] = node;
}
}
}
I seem to get a lot of errors when I try and compile it.
The first one I get is this:
src/main.cpp:10:14: error: unknown type name 'string'; did you mean 'std::string'?
std::map<string, pugi::xml_node> mapa, mapb;
~~~~~^~~
From what I understand, I have specified it correctly. Should I change it as it requests or is something else a-miss?
You need to include the string library in order to use std::string.
Since you mentioned a lot of errors, I suspect you forgot to include <cstring> in order to use strlen().
#include <string>
#include <cstring>
You have to include the string library:
#include <string>
Use the following way:
std::string varName = "var value";
I'm using Clion IDE and it worked for me.
Related
This works in VS2018, but not in 2008, and i'm not sure how to fix it.
#include <map>
#include <string>
int main() {
std::map<std::string, std::string> myMap = {
{"Code", "Test"},
{"Code", "Test1"},
{"Code", "Test2"},
};
}
This is the error :
Error 2 error C2552: 'myMap' : non-aggregates cannot be initialized with initializer list
VS2008 is an old compiler that doesn't support C++11 which is needed for this.
You can insert each element:
int main() {
std::map<std::string, std::string> myMap;
myMap["Code"] = "Test";
myMap["Code"] = "Test1";
myMap["Code"] = "Test2";
}
Or you can use boost:
#include "boost/assign.hpp"
int main() {
std::map<std::string, std::string> myMap = boost::assign::map_list_of
("Code", "Test")
("Code", "Test1")
("Code", "Test2");
}
Option 1: Use a compiler that supports C++11 or a later version of the standard where extended list initialisation is well-formed. (I.e. give up on VS2008)
Option 2: Write the program in C++03 (or older if necessary) compliant dialect. An example:
typedef std::map<std::string, std::string> Map;
typedef Map::value_type Pair;
Pair elements[] = {
Pair("Code", "Test"),
Pair("Code", "Test1"),
Pair("Code", "Test2"),
};
const std::size_t length = sizeof(elements)/sizeof(*elements);
Map myMap(elements, elements + length);
To fix it you have to make it C++03 compliant (this is what vs2008 supports), so basically:
#include <map>
#include <string>
int main() {
std::map<std::string, std::string> myMap;
myMap["Code0"] = "Test0";
myMap["Code1"] = "Test1";
myMap["Code2"] = "Test2";
}
Boost.Assign can greatly simplify life:
#include <boost/assign.hpp>
#include <map>
#include <string>
int main()
{
::std::map< ::std::string, ::std::string > items;
::boost::assign::insert(items)
("Code", "Test")
("Code", "Test1")
("Code", "Test2");
}
I am trying to write Json data to a string using Boost library but I am facing a compilation error:
error: no matching function for call to ‘boost::property_tree::basic_ptree<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::push_back(std::pair<const char*, const char*>)
My c++ code is
#include <fstream>
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
namespace pt = boost::property_tree;
int main()
{
std::string enc = "Enoded data";
pt::ptree root;
pt::write_json(std::cout, root);
pt::ptree image_node;
image_node.push_back(std::make_pair("content", enc));
root.add_child("image", image_node);
pt::ptree features_node;
features_node.push_back(std::make_pair("type", "LABEL_DETECTION"));
features_node.push_back(std::make_pair("maxResults", 1));
root.add_child("features", features_node);
pt::write_json(std::cout, root);
return 0;
}
boost::property_tree::ptree::push_back takes a boost::property_tree::ptree::value_type as parameter, which is not the same as std::pair<const char*, const char*>. So, you'd need eg. :
features_node.push_back(pt::ptree::value_type("type", pt::ptree("LABEL_DETECTION")));
Or better yet, just use boost::property_tree::ptree::put :
pt::ptree root;
root.put("image.content", enc);
root.put("features.type", "LABEL_DETECTION");
root.put("features.maxResults", 1);
pt::write_json(std::cout, root);
Im trying to use the Boost library, I copied the entire boost folder except for the docs, libs, more, status, tools folders.
When I try to use the code block below, my compiler can't identify 2 things.
vector<string>* read(string & filename)
{
// populate tree structure pt
using boost::property_tree::ptree;
ptree pt;
read_xml(filename, pt);
ptree tree;
vector<string> *ans = new vector<string>();
BOOST_FOREACH( ptree::value_type &v, pt.get_child("computer"))
{
string name = v.first.get<string>("name");
string OS = v.first.get<string>("OS");
ans->push_back(name);
ans->push_back(OS);
}
return ans;
}
'BOOST_FOREACH' was not declared in this scope
Can't resolve struct member 'value_type'
I know the following include lines should be enough:
#include <iostream>
#include <vector>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
If you need more info, please ask.
TIA
EDIT
after adding the include foreach.hpp, im getting:
I know the following include lines should be enough:
Clearly they're not. Add
#include <boost/foreach.hpp>
Fixed code:
Live On Coliru
#include <iostream>
#include <vector>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
std::vector<std::string> read(std::string & filename)
{
// populate tree structure pt
using boost::property_tree::ptree;
ptree pt;
read_xml(filename, pt);
ptree tree;
std::vector<std::string> ans;
BOOST_FOREACH(ptree::value_type &v, pt.get_child("computer"))
{
std::string name = v.second.get<std::string>("name");
std::string OS = v.second.get<std::string>("OS");
ans.push_back(name);
ans.push_back(OS);
}
return ans;
}
int main()
{
}
I had some help on a previous topic, where I had to change my map to use int in combination with strings. When I have done this it gives me a different issue. This is the issue:
src/main.cpp:11:29: error: no matching constructor for initialization of
'std::map<int, std::string>'
...tagMap {{"1", "data"}, {"2", "entry"}, {"3", "id"}, {"4", "content"}};
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It seems like the issue (which I looked up on another topic) seems to allude to the fact that the issue is to do with making your constructor take const references? I don't really understand how to implement this.
#include "pugi/pugixml.hpp"
#include <iostream>
#include <string>
#include <map>
int main()
{
pugi::xml_document doca, docb;
std::map<std::string, pugi::xml_node> mapa, mapb;
std::map<int, std::string> tagMap {{"1", "data"}, {"2", "entry"}, {"3", "id"}, {"4", "content"}};
if (!doca.load_file("a.xml") || !docb.load_file("b.xml")) {
std::cout << "Can't find input files";
return 1;
}
for (auto& node: doca.child(tagMap[1]).children(tagMap[2])) {
const char* id = node.child_value(tagMap[3]);
mapa[id] = node;
}
for (auto& node: docb.child(tagMap[1]).children(tagMap[2])) {
const char* idcs = node.child_value(tagMap[3]);
if (!mapa.erase(idcs)) {
mapb[idcs] = node;
}
}
}
Any help would be appreciated.
Try sth like:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
std::map<int, std::string> tagMap {make_pair(1, "data"), make_pair(2, "entry")};
}
Edit: The version without make_pair function is also valid:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
std::map<int, std::string> tagMap {{1, "data"}, {2, "entry"}};
}
The only thing you need to remember is that you shouldn't rely on compiler const string literal to number cast...
// BOOST Includes
#include <boost/assign.hpp> // Boost::Assign
#include <boost/assign/list_of.hpp> // Boost::Assign::List_Of
#include <boost/assign/std/map.hpp> // Boost::Assign::Map_List_Of
#include <boost/tuple/tuple.hpp> // Boost::Tuples
// STD Includes
#include <map>
#include <vector>
#include <string>
// Using namespaces
using namespace std;
using namespace boost;
using namespace boost::assign;
// Consts
const map<string, string> query_map = map_list_of<string, string>
("4556_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 4556")
("7552_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 7552")
("234x_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 2344 OR PMU_ID = 2345 OR PMU_ID = 2346 OR PMU_ID = 2347 OR PMU_ID = 2348")
("813x_SELECT_FILENAME", "SELECT FILENAME FROM Files WHERE PMU_ID = 8132 OR PMU_ID = 8133 OR PMU_ID = 8134 OR PMU_ID = 8135 OR PMU_ID = 8136");
const map<string, std::vector<int>> vector_map = map_list_of<string, std::vector<int>>
("4556", list_of(4556))
("7552", list_of(7552))
("234x", list_of(2344)(2345)(2346)(2347)(2348))
("813x", list_of(8132)(8133)(8134)(8135)(8136));
Using boost - it's possible to init const std::containers for testing etc.
making a const std::map or std::map is pretty easy as the above code shows. Creating a const map<string, std::vector<int>> is a bit more complex - but still fairly easy.
I'm trying to come up with a const std::map<boost::tuples::tuple<string, string, string>, string> but I'm failing to initialize it. Has anyone else had any luck with it ?
// Typedefs
typedef boost::tuples::tuple<string, string, string> x3_string_tuple;
// Constants
const map<x3_string_tuple, string> query_selector_map = map_list_of<x3_string_tuple, string>
("4556", "SELECT", "FILENAME"), "4556_SELECT_FILENAME"); // ETC.
I tried this, and it fails because the keys of the map need to be comparable (with std::less, thus there needs to be an operator< defined). boost::tuple's comparison operators are defined in the header boost/tuple/tuple_comparison.hpp.
Having included that, this code works fine:
#include <boost/assign/list_of.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <map>
#include <string>
using std::string;
typedef boost::tuple<string, string, string> tpl_t;
int main() {
using boost::assign::map_list_of;
std::map<tpl_t, string> const m =
map_list_of(tpl_t("a","b","c"), "c")(tpl_t("x","y","c"), "z");
}
I would try
const map<x3_string_tuple, string> query_selector_map = map_list_of<x3_string_tuple, string>
(x3_string_tuple("4556", "SELECT", "FILENAME"), "4556_SELECT_FILENAME");
But, honestly, maybe it's easier just to have 3 separate lists of strings, and then one-by-one combine them into a tuple and add that to a map.