-6

Simple function to create a declaration node at the beginning and an elementNode named "List", containing 26 elementNodes each named "IP" with a random IPv4 address in string data type as value of the node. The Random ip come from a storage vector with all the 26 IPs. There is no problem with the IPs and vector as it output correctly on the console.

To ensure that the nodes still exist after the method is called, I store them in a vector from outside the function, even though I'm pretty sure it does not change anything to do that.

I've tried to declare ip string inside the loop and assign the value to the variable inside the loop too as it might have revealed information. It does not change anything.

Also, I tried to name each IP node differently with a number as string too. It is worst as it output pure garbage.

I have gotten some hints to make my question a better one, so I edited the code. Everything is in main now and that's all there is.

#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>

#include <Dependencies/Rapidxml/rapidxml.hpp>
#include <Dependencies/Rapidxml/rapidxml_utils.hpp>
#include <Dependencies/Rapidxml/rapidxml_print.hpp>

#include "IPV4.h"

int8_t ComputerQty = 25;
std::vector<rapidxml::xml_node<>*> IPVec;
std::vector<IPV4> IPVector;
std::string FilePath = "C:/Users/Bob/Documents/Visual Studio 2017/Projects/UtryonWithIrrLicht/Files/IPList.xml";

int main(int argc, char** argv)
    {for (size_t A = 0; A < ComputerQty + 1; A++)
        {IPV4 NewIP = IPV4();
        NewIP.SetRandomIP();
        IPVector.push_back(NewIP);
        bool IpCollision = true;
        while (IpCollision)
            {IpCollision = false;
            size_t Size = IPVector.size();
            for(size_t B = 0; B < Size; B++)
                {if (A != B)
                        {if (IPVector[A].GetIP() == IPVector[B].GetIP())
                                {IpCollision = true;
                                if  (A < B)
                                        {IPVector[B].SetRandomIP();}
                                }
                        }
                }
            }
        }

    rapidxml::xml_document<> Doc;
    rapidxml::xml_node<>* Decl = Doc.allocate_node(rapidxml::node_declaration);
    Decl->append_attribute(Doc.allocate_attribute("version", "1.0"));
    Decl->append_attribute(Doc.allocate_attribute("encoding", "utf-8"));
    Doc.append_node(Decl);
    rapidxml::xml_node<>* List = Doc.allocate_node(rapidxml::node_element, "List");
    Doc.append_node(List);
    for (size_t A = 0; A < ComputerQty + 1; A++)
        {std::cout << "IPVector[A].GetIP() = " << IPVector[A].GetIP() << std::endl;
        IPVec.push_back(Doc.allocate_node(rapidxml::node_element, "IP", IPVector[A].GetIP().c_str()));
        List->append_node(IPVec[A]);
        }
    std::ofstream theFile(FilePath);
    theFile << Doc;
    theFile.close();
    Doc.clear();
    }

Here is the resulting file on Notepad++. A list of IPs except most start and end with NUL, a few have b's at the end, and a few have digits missing from the end.

First thing first, what are theses strange characters and where they come from? Never seen anything like that. Then, why is there some missing pieces of the IP? Finally why is it always the same IP?

1 Answers1

0

I found the answer by myself. It turns out that the Node constructor do not accept a std::string although you can do it and it will raise no error anywhere. It's only going to produce an ugly output. You have to wrap the std::string in the allocate_string(my_string) function when you pass it to the constructor as an argument. Seems that rapidxml somehow process the string and modify it to it's desired format. I did that an the output was perfect.

I just changed that line:

IPVec.push_back(Doc.allocate_node(rapidxml::node_element, 
                "IP", 
                IPVector[A].GetIP().c_str()));

For that line:

IPVec.push_back(Doc.allocate_node(rapidxml::node_element,  
                "IP", 
                Doc.allocate_string(IPVector[A].GetIP().c_str()));
rene
  • 37,946
  • 78
  • 99
  • 132
  • This is a duplicate of almost every RapidXML question on stackoverflow, but well done for finding the answer. Just to be clear, you're not passing a `std::string` in either case - you're passing a `const char *` in both, which is why there's no error. – Roddy Feb 25 '19 at 17:21