I am using RapidXML to parse a string of xml.
There is my string:
std::string str("<?xml version=\"1.0\" encoding=\"UTF-8\"
standalone=\"yes\"?><protocol version=\"1.5\"><srvResponse>
<dateTime>2016-10-18T08:51:50.657+01:00</dateTime><responseFrom ag=\"1\"
/><idMessage>0</idMessage><rejectionCode>0</rejectionCode>
</srvResponse></protocol>");
And here is how I try to parse:
XML::xml_document<> doc;
doc.parse<0>((char*) str.c_str());
XML::xml_node<>* firstNode = doc.first_node();
However, what I get is that it is parsed as with just one node: protocol, ie, siblings, children of protocol are null, simply it does not have.
I think I am missing one principal thing.
Could you find and tell me?
Thank you.
You can save XML data to file, such as "1.xml", then you can do as following:
<?xml version="1.0" encoding="utf-8"?>
<protocol version="1.5">
<srvResponse>
<dateTime>2016-10-18T08:51:50.657+01:00</dateTime>
<responseFrom ag="1"/>
<idMessage>0</idMessage>
<rejectionCode>0</rejectionCode>
</srvResponse>
</protocol>
void ParseWithAtrribute(std::string strFilePath /*= "1.xml"*/)
{
rapidxml::file<> docFile(strFilePath.c_str());
rapidxml::xml_document<> doc;
doc.parse<0>(docFile.data());
rapidxml::xml_node<> *pRootNode = doc.first_node();
if (pRootNode != NULL)
{
std::cout << pRootNode->name() << " " << pRootNode->value()<< std::endl; // protocol
rapidxml::xml_attribute<> *pAttr = pRootNode->first_attribute();
if (pAttr != NULL)
{
std::cout << pAttr->name() << " " << pAttr->value() << std::endl; // version
}
rapidxml::xml_node<> *pChildNode = pRootNode->first_node();
if (pChildNode != NULL)
{
std::cout << pChildNode->name() << " " << pChildNode->value() << std::endl;
rapidxml::xml_node<> * pSonNode = pChildNode->first_node();
for(; pSonNode != NULL; pSonNode = pSonNode->next_sibling())
{
std::cout << pSonNode->name() << " " << pSonNode->value() << std::endl;
rapidxml::xml_attribute<> *pSonAttr = pSonNode->first_attribute();
if (pSonAttr != NULL)
{
std::cout << " " << pSonAttr->name() << ":" << pSonAttr->value() << std::endl;
}
}
}
}
}
Now we do not need to save xml data to file:
void ParseWithAtrribute()
{
std::string str("<?xml version=\"1.0\" encoding=\"utf-8\"?> <protocol version=\"1.5\"> <srvResponse> <dateTime>2016-10-18T08:51:50.657+01:00</dateTime> <responseFrom ag=\"1\"/> <idMessage>0</idMessage> <rejectionCode>0</rejectionCode> </srvResponse> </protocol>");
rapidxml::xml_document<> doc;
doc.parse<0>((char *)(str.c_str()));
rapidxml::xml_node<> *pRootNode = doc.first_node();
if (pRootNode != NULL)
{
std::cout << pRootNode->name() << " " << pRootNode->value() << std::endl; // protocol
rapidxml::xml_attribute<> *pAttr = pRootNode->first_attribute();
if (pAttr != NULL)
{
std::cout << pAttr->name() << " " << pAttr->value() << std::endl; // version
}
rapidxml::xml_node<> *pChildNode = pRootNode->first_node();
if (pChildNode != NULL)
{
std::cout << pChildNode->name() << " " << pChildNode->value() << std::endl;
rapidxml::xml_node<> * pSonNode = pChildNode->first_node();
for (; pSonNode != NULL; pSonNode = pSonNode->next_sibling())
{
std::cout << pSonNode->name() << " " << pSonNode->value() << std::endl;
rapidxml::xml_attribute<> *pSonAttr = pSonNode->first_attribute();
if (pSonAttr != NULL)
{
std::cout << " " << pSonAttr->name() << ":" << pSonAttr->value() << std::endl;
}
}
}
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 days ago.
Improve this question
i am trying to make a program in ns3 with OLSR protocol to drop a packet with 1024bytes size when energy of the node under 500j.but when i tried to compile in 1000s, i got a problem "free(): double free detected in tcache 2 when the node send package 1024 bytes and the energy hit under 500j. Here's the code what i am trying to modify in routeinput method file olsr-routing-protocol.cc in ns3
bool RoutingProtocol::RouteInput (Ptr<const Packet> p,
const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb)
{
NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject<Node> ()->GetId () << " " << header.GetDestination ());
/**/ //rekayasa
std::string deviceName = idev->GetInstanceTypeId ().GetName ();
Ptr<Node> node = m_ipv4->GetObject<Node> ();
Ptr<EnergySourceContainer> energysourcecont = (node)->GetObject<EnergySourceContainer> ();
Ptr<EnergySource> source = energysourcecont->Get(0);
NS_ASSERT(node !=NULL);
NS_LOG_LOGIC (node << " nodes "
<<node->GetId() << " "
<< energysourcecont->Get(0) << " "
<< source->GetRemainingEnergy() << " = "
<< "\n"
);
/**/
Ipv4Address dst = header.GetDestination ();
Ipv4Address origin = header.GetSource ();
// Consume self-originated packets
if (IsMyOwnAddress (origin) == true)
{
return true;
}
// Local delivery
NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);
if (m_ipv4->IsDestinationAddress (dst, iif))
{
if (!lcb.IsNull ())
{
NS_LOG_LOGIC ("Local delivery to " << dst);
if (source->GetRemainingEnergy() > 500.0){
NS_LOG_LOGIC("ENERGY > 500, deliver" << " size payload = "<< p->GetSize() << " id packet= " << p->GetUid() << " Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy() << " from: " << origin << " to: " << dst );
lcb (p, header, iif);
}
else if (source->GetRemainingEnergy()<= 500.0){
if((p->GetSize() - 8) == 1024){
NS_LOG_LOGIC("ENERGY < 500, not deliver " << " size payload = "<< p->GetSize() << " id packet= " << p->GetUid() << " Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy());
}
else{
NS_LOG_LOGIC("ENERGY < 500, deliver " << " size payload = "<< p->GetSize() << " id packet= " << p->GetUid() << " Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy() << " from: " << origin << " to: " << dst );
lcb (p, header, iif);
}
}
return true;
}
else
{
// The local delivery callback is null. This may be a multicast
// or broadcast packet, so return false so that another
// multicast routing protocol can handle it. It should be possible
// to extend this to explicitly check whether it is a unicast
// packet, and invoke the error callback if so
NS_LOG_LOGIC ("Null local delivery callback");
return false;
}
}
NS_LOG_LOGIC ("Forward packet");
// Forwarding
Ptr<Ipv4Route> rtentry;
RoutingTableEntry entry1, entry2;
if (Lookup (header.GetDestination (), entry1))
{
bool foundSendEntry = FindSendEntry (entry1, entry2);
if (!foundSendEntry)
{
NS_FATAL_ERROR ("FindSendEntry failure");
}
rtentry = Create<Ipv4Route> ();
rtentry->SetDestination (header.GetDestination ());
uint32_t interfaceIdx = entry2.interface;
// the source address is the interface address that matches
// the destination address (when multiple are present on the
// outgoing interface, one is selected via scoping rules)
NS_ASSERT (m_ipv4);
uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceIdx);
NS_ASSERT (numOifAddresses > 0);
Ipv4InterfaceAddress ifAddr;
if (numOifAddresses == 1)
{
ifAddr = m_ipv4->GetAddress (interfaceIdx, 0);
}
else
{
/// \todo Implement IP aliasing and OLSR
NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and OLSR");
}
rtentry->SetSource (ifAddr.GetLocal ());
rtentry->SetGateway (entry2.nextAddr);
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
NS_LOG_DEBUG ("Olsr node " << m_mainAddress
<< ": RouteInput for dest=" << header.GetDestination ()
<< " --> nextHop=" << entry2.nextAddr
<< " interface=" << entry2.interface);
if (source->GetRemainingEnergy() > 500.0){
NS_LOG_LOGIC("PACKET FORWARD" << " size payload = "<< p->GetSize() << " id packet= " << p->GetUid() <<" Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy());
ucb (rtentry,p,header);
return true;
}
else if(source->GetRemainingEnergy()<= 500.0){
if((p->GetSize()- 8) == 1024){
NS_LOG_LOGIC("DROP PACKET FORWARD "<< p->GetSize() << " " << p->GetUid()<< " Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy()
);
}
else {
NS_LOG_LOGIC("PACKET FORWARD "<< p->GetSize() << " " << p->GetUid()<<
" Node: " <<node->GetId() << " Energy: " <<source->GetRemainingEnergy()
);
ucb (rtentry,p,header);
return true;
}
}
}
else
{
NS_LOG_LOGIC ("No dynamic route, check network routes");
if (m_hnaRoutingTable->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
{
return true;
}
else
{
#ifdef NS3_LOG_ENABLE
NS_LOG_DEBUG ("Olsr node " << m_mainAddress
<< ": RouteInput for dest=" << header.GetDestination ()
<< " --> NOT FOUND; ** Dumping routing table...");
for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin ();
iter != m_table.end (); iter++)
{
NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr
<< " via interface " << iter->second.interface);
}
NS_LOG_DEBUG ("** Routing table dump end.");
#endif // NS3_LOG_ENABLE
return false;
}
}
}
I'm new to json and trying to use nlohmann library and I'm quite stuck.
config.json file looks like this
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{"0": "india"}, {"1": "usa"}, {"2": "china"}, {"2": "japan"}],
"name": "xxx",
}
I want to get the value of ["Map"]["1"] where "1" is a runtime entity. I have tried several ways but none of them is working.
std::string strRwFilePath = std::string(CONFIG_PATH) + "config.json";
std::ifstream RwFile(strRwFilePath);
if (RwFile.fail())
{
std::cout << "[ReadFileContents]RwFile doesnt exist" << std::endl;
}
else
{
// parsing input
RwFile >> conf_json;
if(!(conf_json.empty()))
{
//METHOD 1
for (auto it = conf_json["Map"].begin(); it != conf_json["Map"].end(); ++it)
{
std::cout << it.key() << " | " << it.value() << "\n";
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = it.key(); //ERROR- [json.exception.invalid_iterator.207] cannot use key() for non-object iterators
std::cout << "for loop: tempKey:" << tempKey << " \n";
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 222" << std::endl;
break;
}
else
{
std::cout << "FAILURE 222" << std::endl;
}
}
//METHOD 2
for(auto& element : conf_json["Map"].items())
{
std::cout << element.key() << " | " << element.value() << "\n";
m_iRegionType = 2;
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = element.key(); //ERROR: [json.exception.type_error.302] type must be string, but is object
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 333" << std::endl;
break;
}
else
{
std::cout << "FAILURE 333" << std::endl;
}
}
//METHOD 3
std::string strTempKey = std::to_string(m_iRegionType);
if(!conf_json["Map"][strTempKey.c_str()].is_null())
{
std::string strName = conf_json["Map"][strTempKey.c_str()]; //ERROR: [json.exception.type_error.305] cannot use operator[] with a string argument with array
std::cout << "key found. RegionName: " << strName << '\n';
}
else
{
std::cout << "key not found" << std::endl;
}
//METHOD 4
// create a JSON object
std::string strKey = "/Map/" + std::to_string(m_iRegionType);
// call find
auto it_two = conf_json.find(strKey.c_str());
if(true == (it_two != conf_json.end()))
{
std::cout << "Region key was found. RegionBucketName: " << *it_two << '\n';
std::string strRegionName = conf_json["Map"][m_iRegionType];
std::string strRegionName2 = *it_two;
std::cout << "strRegionName: " << strRegionName << '\n';
std::cout << "strRegionName2: " << strRegionName2 << '\n';
}
else
{
//getting this as OUTPUT even though key is available
std::cout << "invalid region type, key not available m_iRegionType: " << m_iRegionType << std::endl;
}
}
else
{
std::cout << "[ReadFileContents]Read Write Json object is empty" << std::endl;
}
}
I have also tried using the small json structure where I am not able to access the value using the runtime key.
json j =
{
{"integer", 1},
{"floating", 42.23},
{"string", "hello world"},
{"boolean", true},
{"object", {{"key1", 1}, {"key2", 2}}},
{"array", {1, 2, 3}}
};
int avail4 = j.value("/integer"_json_pointer, 444);
std::cout << "avail4 : " << avail4 << std::endl; //OUTPUT- avial4 : 1
int avail5 = j.value("/object/key2"_json_pointer, 555);
std::cout << "avail5 : " << avail5 << std::endl; //OUTPUT- avial5 : 2
auto strKey3 = "/object/key2";
int avail6 = j.value(strKey3, 666);
std::cout << "avail6 : " << avail6 << std::endl; //OUTPUT- avial6 : 666
Could any one help me.
You can't use ["Map"]["1"] to find the inner array objects. You need iterator through the array
A code example may like this:
#include <nlohmann/json.hpp>
#include <iostream>
// for convenience
using json = nlohmann::json;
int main() {
json j = R"(
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{
"0": "india"
}, {
"1": "usa"
}, {
"2": "china"
}, {
"2": "japan"
}],
"name": "xxx"
}
)"_json;
for (const auto& ele : j["Map"]) {
if (ele.contains("1")) {
std::cout << ele["1"] << std::endl;
}
}
}
Output:
usa
Demo
I am currently working on a project that should help me create an implied volatility surface for a given stock. For this purpose, I am writing a script that will download all the available options for this specific stock - from what I've gathered, this is possible by sending a request through the Bloomberg API using bulks fields/overrides. Here is my current code:
d_host = "localhost";
d_port = 8194;
SessionOptions sessionOptions;
sessionOptions.setServerHost(d_host.c_str());
sessionOptions.setServerPort(d_port);
Session session(sessionOptions);
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("ReferenceDataRequest");
request.append("securities", "MSFT US EQUITY");
request.append("fields", "CHAIN_TICKERS");
// add overrides
Element overrides = request.getElement("overrides");
Element override1 = overrides.appendElement();
override1.setElement("fieldId", "CHAIN_PUT_CALL_TYPE_OVRD");
override1.setElement("value", "C");
Element override2 = overrides.appendElement();
override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 100);
Element override3 = overrides.appendElement();
override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
override3.setElement("value", "20250203");
std::cout << "Sending Request: " << request << std::endl;
CorrelationId cid(this);
session.sendRequest(request, cid);
(followed by event handling)
Now I have several issues/questions:
The code compiles without problems, but when running it on the Bloomberg terminal,the following error is printed:
How would I go about fixing this problem? I assume I made a mistake somewhere in the override fields..
How would I need to adjust my code to download all options available given a specific maturity, i.e. I want to get a list of all the options until today + 15 years.
How would I then download the implied volatility for each option? Would I need to store the tickers in an array and then send a request for the field "IVOL_MID" for each option or is there some kind of way to obtain all the volatilities at once?
Edit: Here is the code of my event handler, since that seems to be the problem.
session.sendRequest(request, cid);
while (true)
{
Event event = session.nextEvent();
MessageIterator msgIter(event);
while (msgIter.next()) {
Message msg = msgIter.message();
if (msg.correlationId() == cid) {
processMessage(msg);
}
}
if (event.eventType() == Event::RESPONSE) {
break;
}
}
void processMessage(Message &msg)
{
Element securityDataArray = msg.getElement(SECURITY_DATA);
int numSecurities = securityDataArray.numValues();
for (int i = 0; i < numSecurities; ++i) {
Element securityData = securityDataArray.getValueAsElement(i);
std::cout << securityData.getElementAsString(SECURITY)
<< std::endl;
const Element fieldData = securityData.getElement(FIELD_DATA);
for (size_t j = 0; j < fieldData.numElements(); ++j) {
Element field = fieldData.getElement(j);
if (!field.isValid()) {
std::cout << field.name() << " is NULL." << std::endl;
}
else {
std::cout << field.name() << " = "
<< field.getValueAsString() << std::endl;
}
}
Element fieldExceptionArray =
securityData.getElement(FIELD_EXCEPTIONS);
for (size_t k = 0; k < fieldExceptionArray.numValues(); ++k) {
Element fieldException =
fieldExceptionArray.getValueAsElement(k);
std::cout <<
fieldException.getElement(ERROR_INFO).getElementAsString(
"category")
<< ": " << fieldException.getElementAsString(FIELD_ID);
}
std::cout << std::endl;
}
The problem is in the event handling code that you are not showing. You are probably parsing it incorrectly.
Running your query I get the following result:
MSFT US 01/20/17 C23
MSFT US 01/20/17 C25
MSFT US 01/20/17 C30
MSFT US 01/20/17 C33
MSFT US 01/20/17 C35
MSFT US 01/20/17 C38
MSFT US 01/20/17 C40
MSFT US 01/20/17 C43
MSFT US 01/20/17 C45
MSFT US 01/20/17 C47
MSFT US 01/20/17 C50
MSFT US 01/20/17 C52.5
MSFT US 01/20/17 C55
MSFT US 01/20/17 C57.5
MSFT US 01/20/17 C60
MSFT US 01/20/17 C65
MSFT US 01/20/17 C70
Note: I'm using the Java API but it is essentially the same.
UPDATE:
your code does not parse the field data array element properly: the returned data contains an array of sequences so you need to parse it in two steps. Instead of field.getValueAsString(), you should have a code that looks like this (it's in Java and not tested):
//...
for (int i = 0; i < field.numValues(); i++) {
Element sequence = field.getValueAsElement(i);
ElementIterator it = sequence.elementIterator();
while (it.hasNext()) {
Element e = it.next();
System.out.println(e.getValueAsString());
}
If that does not work I suggest you debug your code step by step and inspect the type of data you receive and handle it accordingly.
For more details you should read the Developer's guide, in particular A.2.3.
As seen in the other answer, the problem lies in the event handling so I've rewritten that part using some examples from the Bloomberg API emulator.
session.sendRequest(request, cid);
bool continueToLoop = true;
while (continueToLoop)
{
Event evt = session.nextEvent();
switch (evt.eventType())
{
case Event::RESPONSE:
continueToLoop = false; //fall through
case Event::PARTIAL_RESPONSE:
ProcessReferenceDataEvent(evt);
break;
}
}
void ProcessReferenceDataEvent(Event evt)
{
const string level1 = "";
const string level2 = "\t";
const string level3 = "\t\t";
const string level4 = "\t\t\t";
std::cout << endl << endl;
std::cout << level1 << "EventType = " << evt.eventType();
MessageIterator iter(evt);
while (iter.next())
{
Message msg = iter.message();
std::cout << endl << endl;
std::cout << level1 << "correlationID = " << msg.correlationId().asInteger() << endl;
std::cout << level1 << "messageType = " << msg.messageType().string() << endl;
std::cout << endl << endl;
Element SecurityDataArray = msg.getElement(SECURITY_DATA);
int numSecurities = SecurityDataArray.numValues();
for (int valueIndex = 0; valueIndex < numSecurities; valueIndex++)
{
Element SecurityData = SecurityDataArray.getValueAsElement(valueIndex);
string Security = SecurityData.getElementAsString(SECURITY);
std::cout << level2 << Security << endl;
bool hasFieldErrors = SecurityData.hasElement("fieldExceptions", true);
if (hasFieldErrors)
{
Element FieldErrors = SecurityData.getElement(FIELD_EXCEPTIONS);
for (size_t errorIndex = 0; errorIndex < FieldErrors.numValues(); errorIndex++)
{
Element fieldError = FieldErrors.getValueAsElement(errorIndex);
string fieldId = fieldError.getElementAsString(FIELD_ID);
Element errorInfo = fieldError.getElement(ERROR_INFO);
string source = errorInfo.getElementAsString("source");
int code = errorInfo.getElementAsInt32("code");
string category = errorInfo.getElementAsString("category");
string strMessage = errorInfo.getElementAsString("message");
string subCategory = errorInfo.getElementAsString("subcategory");
cerr << level3 << "field error:" << endl;
cerr << level4 << "fieldId = " << fieldId << endl;
cerr << level4 << "source = " << source << endl;
cerr << level4 << "code = " << code << endl;
cerr << level4 << "category = " << category << endl;
cerr << level4 << "errorMessage = " << strMessage << endl;
cerr << level4 << "subCategory = " << subCategory << endl;
}
}
bool isSecurityError = SecurityData.hasElement("securityError", true);
if (isSecurityError)
{
Element secError = SecurityData.getElement("securityError");
string source = secError.getElementAsString("source");
int code = secError.getElementAsInt32("code");
string category = secError.getElementAsString("category");
string errorMessage = secError.getElementAsString("message");
string subCategory = secError.getElementAsString("subcategory");
cerr << level3 << "security error:" << endl;
cerr << level4 << "source = " << source << endl;
cerr << level4 << "code = " << code << endl;
cerr << level4 << "category = " << category << endl;
cerr << level4 << "errorMessage = " << errorMessage << endl;
cerr << level4 << "subCategory = " << subCategory << endl;
}
else
{
Element FieldData = SecurityData.getElement(FIELD_DATA);
double pxLast = FieldData.getElementAsFloat64("PX_LAST");
double bid = FieldData.getElementAsFloat64("BID");
double ask = FieldData.getElementAsFloat64("ASK");
string ticker = FieldData.getElementAsString("TICKER");
std::cout << level3 << "fields: " << endl;
std::cout << level4 << "PX_LAST = " << pxLast << endl;
std::cout << level4 << "BID = " << bid << endl;
std::cout << level4 << "ASK = " << ask << endl;
std::cout << level4 << "TICKER = " << ticker << endl;
bool excludeNullElements = true;
if (FieldData.hasElement("CHAIN_TICKERS", excludeNullElements))
{
Element chainTickers = FieldData.getElement("CHAIN_TICKERS");
for (size_t chainTickerValueIndex = 0; chainTickerValueIndex < chainTickers.numValues(); chainTickerValueIndex++)
{
Element chainTicker = chainTickers.getValueAsElement(chainTickerValueIndex);
string strChainTicker = chainTicker.getElementAsString("Ticker");
std::cout << level4 << "CHAIN_TICKER = " << strChainTicker << endl;
}
}
else
{
std::cout << level4 << "NO CHAIN_TICKER information" << endl;
}
}
}
}
}
Regarding the second question, the Bloomberg support staff recommended me to just pick an arbitarily high number so that all options would be downloaded, i.e.
override2.setElement("fieldId", "CHAIN_POINTS_OVRD");
override2.setElement("value", 50000);
For the third question, it is possible to download the chain tickers for all maturities by setting the "CHAIN_EXP_DT_OVRD" override to 'ALL' (this part is currently untested):
Element override3 = overrides.appendElement();
override3.setElement("fieldId", "CHAIN_EXP_DT_OVRD");
override3.setElement("value", 'ALL');
I am using a linked list to store information on binary bits. Degree tells which power to raise an integer, 2, to.
The problem occurs in my set_bit method. It is supposed to delete the node pointer "currentSet" once the "target" node pointer is found. However instead of setting "currentSet" to null/releasing the memory, currentSet is being given a different, lower memory address. Why is this? What am I doing wrong? The program works when I explicitly sell currentSet to nullptr but shouldn't delete currentSet do this as well?
Here is the implementation of header
//file is "binary.cpp"
#include <iostream>
#include "binary.h"
//using std::cout;
Binary::Binary(int x) {
firstTerm = nullptr;
while (x > 0) {
unsigned int degree = (unsigned int) (log(float(x)) / log(float(2)));
set_bit(1, degree);
x -= (int) pow(float(2), float(degree));
}
}
Binary::~Binary() {
BinaryNode *temp;
while (firstTerm != nullptr) {
temp = firstTerm->next;
delete firstTerm;
firstTerm = temp;
}
}
void Binary::set_bit(int bit, int degree) {
BinaryNode *currentSet = firstTerm;
BinaryNode *target;
std::cout << "get_bit returns " << get_bit(degree) << std::endl;
if (bit == 0 && get_bit(degree)) {
std::cout << "bit = 0 " << std::endl;
std::cout << "currentSet->degree " << currentSet->degree << std::endl;
if (currentSet->degree == degree) {
std::cout << "in if" << std::endl;
firstTerm = currentSet->next;
delete currentSet;
std::cout << "end if" << std::endl;
}
else {
target = currentSet;
std::cout << "in else" << std::endl;
while (currentSet != nullptr) {
if (currentSet->degree == degree) {
std::cout << "in nested if" << std::endl;
//std::cout << "currentSet->degree = " << currentSet->degree << std::endl;
target->next = currentSet->next;
std::cout << "currentSet before delete " << currentSet << std::endl;
delete currentSet;
std::cout << "currentSet " << currentSet << "\nend nested if" << std::endl;
}
else {
std::cout << "in nested else" << std::endl;
std::cout << "firstTerm->next = " << firstTerm->next << std::endl;
std::cout << "currentSet->next = " << currentSet->next << std::endl;
target = currentSet;
currentSet = currentSet->next;
std::cout << "currentSet->next = " << currentSet->next << std::endl;
std::cout << "end nested else\n";
}
}
}
}
else if (bit == 1 && get_bit(degree) == 0) {
std::cout << "bit = 1" << std::endl;
firstTerm = new BinaryNode(degree, firstTerm);
/*if (firstTerm->next nullptr) {
currentSet = firstTerm;
}*/
std::cout << "firstTerm = " << firstTerm << std::endl;
std::cout << "firstTerm->degree = " << firstTerm->degree << std::endl;
std::cout << "firstTerm->next = " << firstTerm->next << std::endl;
}
}
int Binary::get_bit(int degree) const {
BinaryNode *currentGet = firstTerm;
while (currentGet != nullptr) {
//std::cout << "currentGet != nullptr";
if (currentGet->degree == degree) {
return 1;
}
currentGet = currentGet->next;
}
return 0;
}
Here is the header
//file is "binary.h"
#ifndef _BINARY_H_
#define _BINARY_H_
#include <iostream>
class Binary {
private:
struct BinaryNode {
int degree;
BinaryNode* next;
BinaryNode(int d, BinaryNode* n): degree(d),next(n) {}
};
BinaryNode *firstTerm;
public:
// default constructor
Binary() {
firstTerm = nullptr;
}
void set_bit(int b, int d);
int get_bit(int d) const;
#endif
Here is the tester file
//file is "binary_main.cpp
#include <iostream>
#include "binary.h"
using namespace std;
int main (void)
{
cout << "\nTESTING GET AND SET METHODS" << endl;
b1.set_bit(1, 2);
b1.set_bit(1, 5);
b1.set_bit(1, 0);
b1.set_bit(0, 2);
}
edited
Explicitly set currentSet to nullptr,
answer was found using information from n.m.
I have below simple XML template in my C++ source code. Within below code block I need to get values for <scannerID> and <subscannerID>. both elements are children of pugixml document root.
xml_document doc;
xml_parse_result r;
std::string sXml = "<inArgs><scannerID>1</scannerID><subScannerID>2</subScannerID></inArgs>";
r = doc.load_buffer(sXml.c_str(), sXml.length());
if (!r) {
return false;
}
xml_node root = doc.child("inArgs");
if (!root) {
return false;
}
std::cout << "root = " << root.name() << std::endl;
xml_node scanner_node = root.child("scannerID");
if (scanner_node) {
std::cout << "scannerID = " << scanner_node.name() << std::endl;
std::cout << "scannerID = " << scanner_node.value() << std::endl;
}
xml_node sub_scanner_node = root.child("subscannerID");
if (scanner_node) {
std::cout << "sub_scanner_node = " << sub_scanner_node.name() << std::endl;
std::cout << "sub_scanner_node = " << sub_scanner_node.value() << std::endl;
}
this code portion giving an output like below. I can get the node's names correctly but failed to retrieve the values.
Out put: values are empty strings.
root = inArgs
scannerID = scannerID
scannerID =
subscannerID = subscannerID
subscannerID =
Edited to add modification for the approach in the answer
node = root.child("scannerID");
if (!node) {
return false;
}
std::cout << "nodeName = %s" << node.name() << std::endl;
std::cout << "text value: " << node.child_value() << std::endl;
but still the output is the same. I saw something different while reading the documents in
The data is in the pcdata child of your element_nodes.
Try scanner_node.child_value()
see the Getting node data section for further examples and explanation.
see node_element
see node_pcdata