Field values for nested structs not getting set in protobuf - c++

I am using google protobuffer for data deserialization, but my issue is that the field values for the nested structures are not getting set. I checked the bin file in a hex editor and the values look fine. However, since the first field in my nested struct is a float and if I try to get the corresponding number of bytes and decode it into a float, the value seems fine.
Can someone advice what else I can do to check this or what perhaps is happening? I have tried using ParseFromIstream as well.
the proto file is :
syntax = "proto3";
package generatedata;
message DataSample {
DataSample_Safe DataSafe = 1;
uint32 PassReSts = 2;
uint32 Dir = 3;
}
message DataSample_Safe {
float ALast = 1;
uint32 ALastQf = 2;
}
message DataSampleMultiple
{
repeated DataSample finaldata = 1;
}
The C++ code is
fstream in("test.bin", ios::in | ios::binary);
generatedata::DataSample test_data;
while(in.read((char *) &test_data,sizeof(test_data)))
{
const generatedata::DataSample_Safe& veh = test_data.datasafe();
cout << "safe" << veh.alast() << endl;
cout << "First " << test_data.passrests() << endl;
cout << "Second " << test_data.dir() << endl;
}
Using ParseFromIstream, the code is
generatedata::DataSampleMultiple test_data;
test_data.ParseFromIstream(&in);
for(int i = 0 ; i < test_data.finaldata_size(); i ++)
{
const generatedata::DataSample& veh = test_data.finaldata(i);
const generatedata::DataSample_Safe& check = veh.datasafe();
cout << "safe" << check.alast() << endl;
cout << "First " << veh.passrests() << endl;
cout << "Second " << veh.dir() << endl;
}
in the above case using ParseFromIstream, the final data size is 0
The first cout gives segmentation fault as the value of safe has not been set. However, the second and third couts are output correctly when using istream::read

Related

C++ Writing a vector of objects to file

I have a vector of objects with quite a few variables (name, type, length etc) which I am trying to write to file.
vector <Boat> berths;
void Boat::write_boats()
{
ofstream file("records_file.txt");
for (Boat b : berths)
{
file << owner_name << "; " << boat_name << "; " << type << "; " << length << "; " << draft << '\n';
}
file.close();
}
void save_records()
{
for (unsigned int i = 1; i < berths.size(); i++)
{
berths[i].write_boats();
}
}
I call the save_records() function with a menu option that ends the application.
The output i get is:
1) If i register a boat object, close the app and go in the text file, I can see the object written twice.
2) If i register 2 objects and I go in the text file, only the last (second) object has been written to file, and it shows 3 times.
Now my questions are:
What causes the double output?
Why is only the last object written to file? I thought the loop would fix that but it didn't
One problem I can spot: "i = 1" in the loop should be "i = 0", because array indexes start from 0. The second: you iterate 'berths' array, so you will get N * N boats saved, if you have N boats in 'berths'.
The simple solution would be
void save_all()
{
ofstream file("records_file.txt");
for (Boat b : berths)
{
file << b.owner_name << "; " << b.boat_name << "; " << b.type << "; " << b.length << "; " << b.draft << '\n';
}
}
If you have to make 'owner_name', 'type' and the rest of the fields as private, then you would have to declare
void Boat::save(std::ofstream& f) const
{
file << owner_name << "; " << boat_name << "; " << type << "; " << length << "; " << draft << '\n';
}
and modify 'save_all' to
void save_all()
{
ofstream file("records_file.txt");
for (const Boat& b: berths)
b.save(f);
}
Every time ofstream file("records_file.txt"); is called, it created a new file and overwrite it, if you want to append in the file you have to open it by this way:
ofstream file("records_file.txt", ios::app);
See: http://www.cplusplus.com/doc/tutorial/files/
I guess you are using something like while(!bla.eof()), if so then it reaches the end of the buffer but it needs to go past it to raise the flag, so you have the same output twice at the end.

Why does my program infinitely loop?

The program that I'm working on reads an input file's contents (.csv), creates an output file (.txt), and outputs the input file's content in the output file in a formatted fashion. Here's how it looks:
#include "stdafx.h"
#include <iostream> // standard input/output library
#include <string> // string data type and its associated functions
#include <fstream> // file input/output
using namespace std; // use standard namespaces
const int iRows = 1119; // input file contains 1,119 rows
const int iColumns = 11; // input file contains 11 columns
string strData[iRows][iColumns]; // 2-dimensional array that holds input file contents
// pads strings to make them the same wide, for fixed width output
string Align(string strIn, int iWidth)
{
string strOut; // padding
// add padding
for (int i = 0; i < iWidth - strIn.length(); i++)
strOut += " ";
return strOut; // return padding
}
// main program entry point
int main()
{
ifstream inFile; // handle for input file
string strSourcePath = // input file path
"C:\\Users\\Logan\\Documents\\CIS022_S2017_Lab8b.csv";
ofstream outFile; // handle for output file
string strDestPath = // output file path
"C:\\Users\\Logan\\Documents\\out.txt";
inFile.open(strSourcePath); // open input file for read (ifstream)
for (int i = 0; i < iRows; i++) // loop for rows
for (int j = 0; j < iColumns; j++) // embedded loop for column
{
if (j == iColumns - 1) // the last element in the row is newline delimited
getline(inFile, strData[i][j], '\n');
else // all other elements are comma delimited
getline(inFile, strData[i][j], ',');
/*cout << "i = " << i << " j = " << j << " " << strData[i][j] << endl;*/ // console dump for error checking
}
inFile.close(); // done with input file, close it
outFile.open(strDestPath); // open output file for write (ofstream)
for (int i = 0; i < iRows; i++) // loop through each input row
{
outFile <<
strData[i][0] << Align(strData[i][0], 7) << // CRN
strData[i][1] << Align(strData[i][1], 6) << // Subject
strData[i][2] << Align(strData[i][2], 6) << // Number
strData[i][3] << Align(strData[i][3], 20) << // Title
strData[i][4] << Align(strData[i][4], 7) << // Days
strData[i][5] << Align(strData[i][5], 13) << // Meetdates
strData[i][6] << Align(strData[i][6], 17) << // Times
strData[i][7] << Align(strData[i][7], 6) << // Credits
strData[i][8] << Align(strData[i][8], 13) << // Instructor
strData[i][9] << Align(strData[i][9], 6) << // Room
strData[i][10] << endl; // Max Enroll
}
outFile.close(); // close output file
system("Pause"); // wait for user input
return 0; // exit program
}
However, whenever I run it, it loops infinitely here:
for (int i = 0; i < iRows; i++) // loop through each input row
{
outFile <<
strData[i][0] << Align(strData[i][0], 7) << // CRN
strData[i][1] << Align(strData[i][1], 6) << // Subject
strData[i][2] << Align(strData[i][2], 6) << // Number
strData[i][3] << Align(strData[i][3], 20) << // Title
strData[i][4] << Align(strData[i][4], 7) << // Days
strData[i][5] << Align(strData[i][5], 13) << // Meetdates
strData[i][6] << Align(strData[i][6], 17) << // Times
strData[i][7] << Align(strData[i][7], 6) << // Credits
strData[i][8] << Align(strData[i][8], 13) << // Instructor
strData[i][9] << Align(strData[i][9], 6) << // Room
strData[i][10] << endl; // Max Enroll
}
The input file contains 1119 rows of information, so I'll give you the first row:
CRN,Subj,Num,Title,Days,Meetdates,Times,Credits,Instructor,Room,Max Enroll
I let my program sit for a minute and nothing happened. Even adding this code at the beginning of the for loop only outputs the first row of information:
cout <<
strData[i][0] << " " <<
strData[i][1] << " " <<
strData[i][2] << " " <<
strData[i][3] << " " <<
strData[i][4] << " " <<
strData[i][5] << " " <<
strData[i][6] << " " <<
strData[i][7] << " " <<
strData[i][8] << " " <<
strData[i][9] << " " <<
strData[i][10] << endl;
Why does my program infinitely loop?
What happens if, in this code,
string Align(string strIn, int iWidth)
{
string strOut; // padding
// add padding
for (int i = 0; i < iWidth - strIn.length(); i++)
strOut += " ";
return strOut; // return padding
}
strIn is longer than iWidth ?
You will attempt to increment i until it reaches a negative number.
Here is probably your issue.

VTK: Extracting Cell Data from vtu unstructured grids in c++

I need to extract all the cell data from a .vtu (XML unstructured grid) for further manipulations in a c++ program. I am quite new to VTK...
//read all the data from the file
vtkSmartPointer<vtkXMLUnstructuredGridReader> reader =
vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
unsigned int cellNumber = reader->GetOutput()->GetNumberOfCells();
cout << "There are " << cellNumber << " input cells." << endl;
This is correct - the cell number is displayed correctly. How do access now the names of the different CellArrays properties stored in the .vtu file and then their actual numeric values? Any help is appreciated!
Cheers,
Domanov
//read all the data from the file
vtkSmartPointer<vtkXMLUnstructuredGridReader> reader =
vtkSmartPointer<vtkXMLUnstructuredGridReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
unsigned int cellNumber = reader->GetOutput()->GetNumberOfCells();
cout << "There are " << cellNumber << " input cells." << endl;
To access the cell data of unstructured grid, you can do as following:
vtkUnstructuredGrid* ugrid = reader->GetOutput();
vtkCellData *cellData = ugrid->GetCellData();
for (int i = 0; i < cellData->GetNumberOfArrays(); i++)
{
vtkDataArray* data = cellData->GetArray(j);
cout << "name " << data->GetName() << endl;
for (int j = 0; j < data->GetNumberOfTuples(); j++)
{
double value = data->GetTuple1(j);
cout << " value " << j << "th is " << value << endl;
}
}

Where am I wrong? SetDataBuffer for DATE

I want to do array fetch for DATE in oracle with following code. It compiles alright and export all other data types correctly, except for the DATE type. The program says "ora-32146 cannot peform operation on a null date".
Any one can see where I am wrong?
Statement *stmt = conn->createStatement("SELECT AGE,CASH2, BIRTHDATE from myTable2"); /*, CASH1, CASH2, BIRTHDATE*/
//stmt->setMaxParamSize(1,sizeof(Number));
ResultSet *rs=stmt->executeQuery();
string myName[400];
int myAge[400];
double myCash1[400];
double myCash2[400];
oracle::occi::Date myBirthDate[400];
//rs->setDataBuffer(1,myName,OCCI_SQLT_STR,sizeof(string));
rs->setDataBuffer(1,myAge,OCCIINT,sizeof(int));
rs->setDataBuffer(2, myCash2, OCCIBDOUBLE, sizeof(double),NULL);
rs->setDataBuffer(3, myBirthDate,OCCI_SQLT_DATE, sizeof(oracle::occi::Date),NULL);
while (rs->next(200)==ResultSet::DATA_AVAILABLE)
{
//cout << "Exporting batch..." << endl;
for(size_t i=0;i<rs->getNumArrayRows();i++)
{
//cout << myName[i] << endl;
cout << myAge[i] << endl;
//cout << myCash1[i] << endl;
cout << myCash2[i] << endl;
int y;
unsigned int m,d,h,mm,s;
myBirthDate[i].getDate(y,m,d,h,mm,s);
cout << y <<"-"<<m<<"-"<<s << endl;
}
}
Figured it out.
using rs->setDataBuffer(3, myBirthDate,OCCI_SQLT_DAT, 7,NULL);
works out all right.
No good document on OCCI...

Trying to write a M3U file in Qt with ID3_Tag info

I try to make a M3U file(playlist) but when I try to write a file my program crash without an error.
bool Playlist::savePlaylist(QString path)
{
this->filename = path;
QFile file(path);
if((file.open(QIODevice::WriteOnly | QIODevice::Truncate)) == false)
{
return false;
}
QTextStream out(&file);
if(out.status() != QTextStream::Ok)
{
return false;
}
out << "#EXTM3U" << endl;
for(int i = 0 ; i < this->getSize() ; i++)
{
SongInfo si = this->songs.at(i);
int durata = this->getLengthInSeconds(si.getAddress().toString(QUrl::None));
out << "#EXTINF:" << durata << "," << ID3_GetArtist(&si.getTag()) << " - "
<< ID3_GetTitle(&si.getTag()) << endl;
out << si.getAddress().toString(QUrl::None) << endl;
}
file.close();
return true;
}
If I try with 188 files, 1.07 Gb size on disc, after about 100 songs the program crash. When I try to get the SongInfo at that position I get the crash. If I try with let's say 30-40 songs everything works perfect. I don't know what could be the problem. I've tried to write chunks, and delete those chunks from memory, I've used flush. I don't know what to do, where the problem could be. If I write to console those information(a for loop just for printing) everything is perfect, but when I try to write...crash.
What could be the problem?
To me it looks weird how you iterate over the song list with this->getSize() and then get the SongInfo with this->songs.at(i);.
this is not the same object as this->songs, and just by looking at your code it's not possible to know what getSize() does.
Would you care to try this?
int size = songs.size();
for(int i = 0 ; i < size ; i++)
{
SongInfo si = this->songs.at(i);
int durata = this->getLengthInSeconds(si.getAddress().toString(QUrl::None));
out << "#EXTINF:" << durata << "," << ID3_GetArtist(&si.getTag()) << " - "
<< ID3_GetTitle(&si.getTag()) << endl;
out << si.getAddress().toString(QUrl::None) << endl;
}
or even better, if songs is a QList:
foreach(SongInfo si, songs){
int durata = this->getLengthInSeconds(si.getAddress().toString(QUrl::None));
...
}