I'm trying to use the RapidXML to parse my XML file. And I did it following the example here. Instead of doing the parsing in the main function, I wrote a wrapper class called XMLParser to do the parsing job. And this really gives me a headache.
The XMLParser.hpp:
#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include "rapidxml/rapidxml.hpp"
using namespace std;
using namespace rapidxml;
class XMLParser {
public:
XMLParser() {};
XMLParser(const std::string &xmlString): xmlCharVector(xmlString.begin(), xmlString.end())
{
//xmlCharVector.push_back('\0');
parseXML();
}
XMLParser(const std::vector<char> &_xmlVector):xmlCharVector(_xmlVector)
{
/* xmlCharVector.push_back('\0'); */ // already done in main.cpp
if (xmlCharVector != _xmlVector) //And it turns out they're the same....
std::cout << "The two vectors are not equal" << std::endl;
else
std::cout << "They are the same" << std::endl;
parseXML();
}
private:
std::vector<char> xmlCharVector;
rapidxml::xml_document<> doc;
void parseXML();
};
The XMLParser.cpp:
#include "XMLParser.hpp"
using namespace std;
using namespace rapidxml;
void XMLParser::parseXML()
{
doc.parse<0>(&xmlCharVector[0]);
}
And here is the main.cpp:
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include "XMLParser.hpp"
using namespace std;
using namespace rapidxml;
int main(int argc, char **argv)
{
xml_document<> doc;
xml_node<> *root_node;
ifstream theFile("beer.xml");
vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
root_node = doc.first_node("MyBeerJournal");
xml_node<> *engine = root_node->first_node("Brewery");
//The above code works pretty well, and I can get the element I want in XML file.
//The problem occurs when I tried to use the XMLParser
XMLParser xmlParser(buffer);
return 0;
}
The parsing process in the main function works pretty well. But when I tried to use the function in my wrapper class parseXML(), then error occured:
terminate called after throwing an instance of 'rapidxml::parse_error'
what(): expected >
Abort (core dumped)
Originally I have other code in this function, but I commented them all, and find that even with the single line doc.parse<0>(&xmlCharVector[0]);. Why it works well in main.cpp while not in the wrapper class? I really can't figure it out. Could anybody help me?
I've found out the reason... This stupid problem really takes me a long time to debug. I'm writing it here so that anyone ran into it (hope not) could save his time. The problem lies exactly in the code doc.parse<0>(&buffer[0]) in the main function. Before executing this line of code, the buffer(type of vector<char>) is like this: (by printing the vector to console)
<MyBeerJournal>
<Brewery name="Founders Brewing Company" location="Grand Rapids, MI">
<Beer name="Centennial" description="IPA" rating="A+" dateSampled="01/02/2011">
"What an excellent IPA. This is the most delicious beer I have ever tasted!"
</Beer>
</Brewery>
.....
.....
</MyBeerJournal>
It's the same with original xml file. After executing the above code, the buffer(type of vector<char>) becomes something like this:
<MyBeerJournal
<Breweryname"Founders Brewing Company location"Grand Rapids, MI>
<Beername"Centennial description"IPA rating"A+ dateSampled"01/02/2011>
"What an excellent IPA. This is the most delicious beer I have ever tasted!"
/Beer>
</Brewery>
As you can see, some angel brackets disappeared. and some other things like double quote has also been changed. So the wrapper class constructor copied the modified "xml buffer", and this not well formatted xml vector will certainly cause the second doc.parse<0>(&xmlCharVector[0]); in the wrapper class to fail. I don't know why the library writer needs to modify the char vector passed in, because the subsequent xml analysis is not relevant to the original char vector once the DOC has been created.
Related
I want to open a file named 1.board by calling a function and use getline function to print it's characters to new line.But this is showing a lot of errors.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using std::ifstream;
using std::cout;
using std::string;
using std::vector;
void ReadBoardFile(ifstream& search)
{
string line;
search.open("1.board");
while(getline("1.board",line))
{
cout<<line<<"\n";
}
}
int main() {
ifstream fin;
ReadBoardFile(fin);
}
I don't know what i'm doing wrong.I just can't find a perfect and exact answer.
Help,if you can.Thanku!!!!!
So here's your code rewritten so it works.
Two changes, first the first parameter to getline should be the stream you are reading from not the name of a file. I'm guessing that you just weren't concentrating when you wrote that.
Second change, I've moved the stream variable search so that it is local to your ReadBoardFile function. There's no reason in the code you've posted to pass that in as a parameter. You might want to pass the name of the file as a parameter, but I'll leave you to make that change.
void ReadBoardFile()
{
ifstream search("1.board");
string line;
while(getline(search,line))
{
cout<<line<<"\n";
}
}
int main() {
ReadBoardFile();
}
In my code below errors occur and the program will not run, I am required to make a Constructor that must open the file with the given filename. If the filename does not exist then it Prints an error message and terminates the program.
Below is the code that I have done so far in C++:
#include "ReadWords.h"
#include <iostream>
#include <cstdlib>
using namespace std;
ReadWords::ReadWords(const char filename[])
{
wordfile.open(filename);
if (!wordfile)
{
cout << "cannot make " << filename << endl;
exit(1);
}
}
void ReadWords::close()
{
wordfile.close();
}
Why dont you try including fstream to the top of your file and see if that works
I suppose wordfile is of type std::fstream. If your ReadWords.h #includes <fstream>, it should work (compiles and works as expected).
By the way, it's a bad practice to use using namespace std;.
Also, since you use C++, take a look at std::string. It's safer than using plain char* or char[].
I was attempting to follow the example of Finite State Filters in the Boost::iostreams documentation. However when I went to use the filter I got an error stating the ::imbue was not accessible because 'boost::iostreams::detail::finite_state_filter_impl' uses 'protected' to inherit from 'my_fsm'.
Frustrated I copied my code into the tests used to in the boost examples. The tests compile and pass. My conculsion is that I am probably mis-using the dual use filter defined by:
typedef io::finite_state_filter my_fsm_filter;
I feel that just pushing it onto a filtered_stream may not be proper, but I could not find a missing step. I am sure there must be a need to wrap the filter but I can find no example (though I am sure if I dug deep enough into the code used to test the boost code it has to be there somewhere).
here is a bit of example code:
#include <boost/mpl/vector.hpp>
#include <libs/iostreams/example/finite_state_filter.hpp>
namespace io = boost::iostreams;
struct my_fsm : io::finite_state_machine<my_fsm> {
BOOST_IOSTREAMS_FSM(my_fsm) // define skip and push.
typedef my_fsm self;
static const int beginline = 0;
static const int skipline = 1;
static const int dataline = 2;
typedef boost::mpl::vector <
row<beginline, is<'C'>, skipline, &self::skip>,
row<beginline, is_any, dataline, &self::push>,
row<skipline, is<'\n'>, beginline, &self::skip>,
row<skipline, is_any, skipline, &self::skip>,
row<dataline, is<'\n'>, beginline, &self::push>,
row<dataline, is_any, dataline, &self::push>
> transition_table;
};
typedef io::finite_state_filter<my_fsm> my_fsm_filter;
#include <iostream>
#include <string>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
int main() {
io::stream<io::file_sink> out(io::file_sink("outputfile.txt"));
io::filtering_istream in;
my_fsm_filter infsm;
in.push(my_fsm_filter());
in.push(io::file_source("inputdata.txt"));
while (in) {
std::string line;
if(std::getline(in, line)) {
//std::cout << line << std::endl;
out << line << std::endl;
}
}
return 0;
}
I personally feel that there is a bug in the sample header with respect to this imbue call.
However, you can work around it by changing the typedef to
struct my_fsm_filter : io::finite_state_filter<my_fsm> {
using io::finite_state_filter<my_fsm>::imbue;
};
This explicitly exposes the imbue method as public on the derived type. I haven't looked at the sample program that you reported to be working (because you didn't link to it). But it's possible they used a similar hack.
In my tests, a similar edit to finite_state_filte.hpp L278 to add
using base_type::imbue;
to class finite_state_filter has the same effect.
#include <iostream>
#include <string.h>
using namespace std;
int main ()
{
string st = "Hello world";
return 0;
}
and
#include <string>
int main ()
{
std::string st = "Hello world";
return 0;
}
I tried compiling this code using minGW compiler on netbeans. It brings up the following error after the successful build.
RUN FAILED (exit value -1,073,741,511, total time: 93ms)
But it works clean when strings are not used. I would like to know what I am doing wrong here. Thanks in advance.
Use c++ strings and don't use using namespace std:
#include <string> //c++ string header
int main ()
{
std::string st = "Hello world";
return 0;
}
#include <string.h> is the old C-style string header and most likely isn't what you want to use here. See this question for more details: Difference between <string> and <string.h>?
Note: If you really wanted the old C-style strings then you really should be using #include <cstring> because this will put those functions into the std namespace and won't cause any namespace pollution that can lead to other undesirable outcomes.
Likely what happened was that you used the old style string header and didn't properly initialize those strings. The old C-style strings don't have a constructor and operator= defined like the std::string class.
Edit: After looking at the Netbeans forum this is a problem with Netbeans and not a c++ issue. Try changing the output to an external terminal in Netbeans. Or run the program directly from the command line. If these approaches don't fix the problem or are undesirable then make a post over on the Netbeans forum. Also have a look at this question: Program won't run in NetBeans, but runs on the command line!
Uss #include <string> instead of string.h
I need to read the information contained in a json file like this:
{"first":10, "second":"0", "P1":"1.e-20","P2":"1000","P3":"1000","P4":"1000","P5":"1"}
Since I do not have experience with this issue, I started by playing with the short code you can see below these lines. It does compile with no problem but it gives a segmentation fault back upon execution. The file general.json is in the same folder. The information contained in the json file is correctly printed in the screen if I comment the last line. Could anyone tell me what am I doing wrong?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fstream> // fstream.h in old versions of g++
#include <iostream> //para cout
#include <sstream>
#include <json/json.h>
using namespace std;
int main() {
struct json_object *new_json, *json_arr, *json_reg, *json_field;
string line;
stringstream jsonfile;
ifstream json("file.json", ios::in);
{getline(json, line); do {jsonfile << line;} while (getline(json, line));}
json.close();
cout << jsonfile.str().c_str();
new_json=json_tokener_parse(jsonfile.str().c_str());
json_field=json_object_object_get(json_reg, "first");
}
You are using the json_reg pointer without initializing it and the function dereferences it. You are (most likely) using json-c where:
json_object_object_get calls json_object_object_get_ex on the object
json_object_object_get_ex does switch(jso->o_type) dereferencing an invalid pointer