cereal compiles and runs, but does not write to file - c++

The following code does not write to file.
#include <cereal/types/vector.hpp>
#include <cereal/archives/xml.hpp>
{
vector<int> v = { 1,2,3 };
stringstream s;
s << "cereal_test.xml";
cereal::XMLOutputArchive oarchive(s);
oarchive(v);
}
It compiles and runs apparently correctly.
If we cout << s << endl; out of scope we see in the console:
cereal_test.xml
<?xml version="1.0" encoding="utf-8"?>
<cereal>
<value0 size="dynamic">
<value0>1</value0>
<value1>2</value1>
<value2>3</value2>
</value0>
</cereal>
What's missing?

A mistaken copy-paste from cereal's tuturial:
It should be ofstream instead of stringstream
{
vector<int> v = { 1,2,3 };
std::ofstream outFile("cereal_test.xml");
{
cereal::XMLOutputArchive oarchive(outFile);
oarchive(v);
}
}

Related

how exactly input and output file streams work in c++

I came across the following observation while working with input and output file streams and I am confused. Can anyone tell me why this happens:
I saved a txt file on my desktop by the name hello which contains the following text:
Hello my name is xyz
Next, I ran the following code:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
//std::string p;
//strm >> p;
//std::cout << p;
strm << "random text";
}
The content of the hello.txt file after running this code was:
random textme is xyz
Now i ran the following code on the original hello.txt file
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
std::string p;
strm >> p;
std::cout << p;
strm << "random text";
}
The console printed hello but the contents of the hello.txt file remained unaltered.
Can anybody explain, what difference did reading stream into the string make?
If you want to know how streams work in C++ then you need a reference work (and maybe a tutorial as well), obviously its much more complicated than can be explained here.
The reason for what you found is the rule that if you switch from reading to writing (or vice versa) you must execute a positioning or flushing operation before you make the switch. Try the following code instead
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
std::string p;
strm >> p;
std::cout << p;
strm.seekp(0); // position the stream at the beginning
strm << "random text";
}

getline has a strange behaviour in reading a text file

I have a strange behaviour with a piece of code I have wrote. There is the code :
#include "pugixml.hpp"
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <optional>
namespace xml = pugi;
void read_ascii_file(const std::string& filename)
{
std::ifstream file(filename, std::ios::in);
if(!file) {
std::cerr << "[ERREUR - read_ascii_file] Impossible d'ouvrir le fichier " << filename << "! VĂ©rifier son existence." << std::endl;
abort();
}
std::string tmp;
while(std::getline(file, tmp))
{
//Do nothing here
}
file.close();
}
class Foo{
public:
Foo(const xml::xml_document& doc)
{
_base_node = doc.child("test");
std::string id = _base_node.child("data1").child_value("id");
std::cout << "id from constructor " << id <<std::endl;
}
void bar()
{
std::string id = _base_node.child("data2").child_value("id");
std::cout << "id from bar " << id <<std::endl;
}
private:
xml::xml_node _base_node;
};
std::optional<Foo> make(const std::string& filename)
{
xml::xml_document doc;
xml::xml_parse_result result = doc.load_file(filename.c_str());
if(result.status != xml::xml_parse_status::status_ok)
return {};
else
return Foo(doc);
}
int main()
{
std::string filename = "xml_test.dat";
std::optional<Foo> f = make(filename);
if(!f)
std::abort();
else
{
std::string filename = "lbl-maj_for_test.dat";
//read_ascii_file(filename);
f->bar();
}
return 0;
}
The file xml_test.dat is :
<test>
<data1>
<id>1</id>
</data1>
<data2>
<id>2</id>
</data2>
</test>
This code giving an output :
id from constructor 1
id from bar 2
But when I uncomment the line //read_ascii_file(filename);, the output become :
id from constructor 1
Erreur de segmentation
gdb give me the error :
#0 0x00007ffff7f84b20 in pugi::xml_node::child(char const*) const () from /lib/x86_64-linux-gnu/libpugixml.so.1
#1 0x00005555555578ba in Foo::bar (this=0x7fffffffdf40) at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:42
#2 0x00005555555575ec in main () at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:73
The file lbl-maj_for_test.dat is a txt file of 132 lines and none seems to have a length more than 50 characters. I think to a an encoding problem, but I have no clue how I can resolve this problem ...
This has nothing to do with getline. Uncommenting/commenting things when your program has undefined behaviour can lead to red herrings such as this.
The problem is that your nodes are all dangling, since you do not persist doc. By the time you call bar(), _base_node is dead/invalid/orphaned.
From the documentation:
xml_document is the owner of the entire document structure; destroying the document destroys the whole tree.
Assuming the library supports it, I'd move doc into Foo and store it as a member by value.

program to delete certain text which is predefined in another file from a file in c++

Given two files input.txt and delete.txt. Our Task is to perform file extraction(Input-Delete) and save the output in the file say output.txt
Example image
Show some research effort when you post a question here.
#include <iostream>
#include <unordered_set>
#include <fstream>
int main()
{
std::unordered_set<std::string> mySet;
std::string word;
std::ifstream file1("myFile1.txt");
if(file1.is_open())
{
while(file1 >> word)
mySet.emplace(word);
file1.close();
}
std::ifstream file2("myFile2.txt");
if(file2.is_open())
{
while(file2 >> word)
{
auto look = mySet.find(word);
if(look != mySet.cend())
mySet.erase(look);
}
file2.close();
}
std::ofstream outputFile("Out.txt");
if(outputFile.is_open())
{
for(const auto &it: mySet)
outputFile << it << '\n';
outputFile.close();
}
return 0;
}
EDIT:
I don't know what do you mean by not working. just debug your code, before you write the final set of strings to the output file, that's what I can say.
Just use the following and see what do you get:
for(const auto &it: mySet)
std::cout << it << '\n';
For instance I am getting the requeried output what do you mentioned in the picture.
Here is my console output:

How Do I Print a Vector of Tuples?

So I'm trying to make a vector that contains tuples containing two ints, and I'm acquiring the ints from a text file source. To make sure I have the vector I want, I'm trying the print out my contents, but the output is not showing me anything. I'm not sure if it's because of my code, and where I put my text file. I'm just stuck at this point. If anything could help me with this, I'd appreciate it very much. Thanks
using namespace std;
int main()
{
ifstream file("source.txt");
typedef vector<tuple<int, int>> streets;
streets t;
int a, b;
if (file.is_open())
{
while (((file >> a).ignore() >> b).ignore())
{
t.push_back(tuple<int, int>(a, b));
for (streets::const_iterator i = t.begin();i != t.end();++i)
{
cout << get<0>(*i) << endl;
cout << get<1>(*i) << endl;
}
cout << get<0>(t[0]) << endl;
cout << get<1>(t[1]) << endl;
}
}
file.close();
system("pause");
return 0;
Here's my text file and where I placed it
enter image description here
Here's my output from debugging, if that's important
You should use a loop, that will print one tuple at a time.
Complete minimal example:
#include <iostream>
#include <tuple>
#include <vector>
#include <fstream>
using namespace std;
int main(void) {
std::ifstream infile("source.txt");
vector<tuple<int, int>> streets;
int a, b;
while (infile >> a >> b)
{
streets.push_back(tuple<int, int>(a, b));
}
infile.close();
for(auto& tuple: streets) {
cout << get<0>(tuple) << " " << get<1>(tuple) << endl;
}
return 0;
}
Output:
1 2
3 4
5 6
7 8

Boost .ini file parser - multiple section name(s)

I am using boost::property_tree to parse ini files.
I want to be able to do something like the following:
data.ini:
[electron]
position=0,0,0
velocity=0,0,0
[proton]
position=1,0,0
velocity=0,0,0
[proton]
position=-1,0,0
velocity=0,0,0
Currently the program runs, and gives this error: duplicate section name Obviously because there are two [proton] sections.
Is there an alternative way to parse a file like this? Should I perhaps be using an xml file?
Here is a simple reader, in case you need it:
XML-file:
<?xml version="1.0" encoding="utf-8"?>
<data>
<electron>
<position>0,0,0</position>
<velocity>0,0,0</velocity>
</electron>
<proton>
<position>1,0,0</position>
<velocity>0,0,0</velocity>
</proton>
<proton>
<position>-1,0,0</position>
<velocity>0,0,0</velocity>
</proton>
</data>
JSON-file:
{
"electron": {
"position": "0,0,0",
"velocity": "0,0,0"
},
"proton": {
"position": "1,0,0",
"velocity": "0,0,0"
},
"proton": {
"position": "-1,0,0",
"velocity": "0,0,0"
}
}
Read XML & JSON proton nodes:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <algorithm>
#include <iostream>
int main()
{
// XML
{
boost::property_tree::ptree pt;
boost::property_tree::read_xml("prop_data.xml", pt);
for(auto& el : pt.get_child("data.proton"))
{
std::cout << el.second.data() << std::endl;
}
}
// JSON
{
boost::property_tree::ptree pt;
boost::property_tree::read_json("prop_data.json", pt);
for(auto& el : pt.get_child("proton"))
{
std::cout << el.second.data() << std::endl;
}
}
return 0;
}
EDIT:
It is possible to use arrays for JSON, e.g:
...
"position": [-1, 0, 0],
...
And the code to read values of this array:
for(auto& el : pt.get_child("proton"))
{
std::cout << el.first << std::endl;
for(auto& a : el.second) {
std::cout << a.second.data() << std::endl;
}
std::cout << std::endl;
}
Here el.second is just a ptree, and you can iterate through it using a for loop.