Outputting large structures to HD - visual-c++

I have an array of a large structure that I am trying to output to hard drive. I seem to be able to write to hard drive just fine (though it's difficult to verify by looking at the binary data), however when I try to read it back, I always end up with a garbled mess. Any ideas what I'm doing wrong?
here's the structure configuration:
class xyz
{
public:
double x, y, z;
};
class trianglePackage
{
public:
int score;
int position;
xyz contactCoordinates;
xyz normalVector;
xyz locatorOffset;
};
class quadanglesOutput
{
public:
int locator1position, locator2position, locator3position, locator4position;
xyz centroid;
int surfaceAreaScore;
int centroidDifferance1Score;
int centroidDifferance2Score;
int minDistance1Score;
int minDistance2Score;
int totalLocatorScore;
int totalHullScore;
int totalScore;
double surfaceArea;
double centroidDifferance1;
double centroidDifferance2;
double minDistance1;
double minDistance2;
int hull;
trianglePackage locator1, locator2, locator3, locator4;
};
and here are the read/write functions I'm using:
void outputQuadangleOutput(quadanglesOutput* output, string description, param parameters)
{
string outputName = parameters.fileName + " " + description + ".bin";
cout << "Output " << outputName.c_str() << "...";
ofstream output2;
output2.open(outputName.c_str());
output2.write(reinterpret_cast<char*>(output), streamsize(parameters.topXlist * sizeof(quadanglesOutput)));
output2.close();
cout << "done" << endl;
}
void readIn(quadanglesOutput* pointer, param parameters, string description)
{
string fileName = parameters.fileName + " " + description + ".bin";
cout << "openining " << fileName << "...";
ifstream readFile;
readFile.open(fileName.c_str());
readFile.read(reinterpret_cast<char*>(pointer), (parameters.topXlist * sizeof(quadanglesOutput)));
readFile.close();
cout << "done" << endl;
}
Typically the arrays of structures are about 100 in length, but usually only about the first 25 read back correctly, everything else is default uninitialized data.
I'm 99% sure that it's something wrong with my code, however is there a possibility it has something to do with four byte alignment?
Thanks.

It may be an issue with byte alignment, use pragma.
try wrap classes around with
#PRAGMA PACK PUSH(1)
....
#PRAGMA PACK POP
or
#PRAGMA PACK(1)
struct{
..
}
Try those as well:
Force binary flag for the stream.
ios_base::binary
readFile.open(fileName.c_str(), ios_base::binary);
Try to flush the the stream.
stream.write(...)
stream.flush()
//i know that close() should flush it.
UPDATE:
Everything works for me:
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
#pragma pack(1)
class xyz
{
public:
double x, y, z;
};
#pragma pack(1)
class trianglePackage
{
public:
int score;
int position;
xyz contactCoordinates;
xyz normalVector;
xyz locatorOffset;
};
#pragma pack(1)
class quadanglesOutput
{
public:
int locator1position, locator2position, locator3position, locator4position;
xyz centroid;
int surfaceAreaScore;
int centroidDifferance1Score;
int centroidDifferance2Score;
int minDistance1Score;
int minDistance2Score;
int totalLocatorScore;
int totalHullScore;
int totalScore;
double surfaceArea;
double centroidDifferance1;
double centroidDifferance2;
double minDistance1;
double minDistance2;
int hull;
trianglePackage locator1, locator2, locator3, locator4;
};
class param
{
public:
string fileName;
int topXlist;
};
void outputQuadangleOutput(quadanglesOutput* output, string description, param parameters)
{
string outputName = parameters.fileName + " " + description + ".bin";
cout << "Output " << outputName.c_str() << "...";
ofstream output2;
output2.open(outputName.c_str());
output2.write(reinterpret_cast<char*>(output), streamsize(parameters.topXlist * sizeof(quadanglesOutput)));
output2.close();
cout << "done" << endl;
}
void readIn(quadanglesOutput* pointer, param parameters, string description)
{
string fileName = parameters.fileName + " " + description + ".bin";
cout << "openining " << fileName << "...";
ifstream readFile;
readFile.open(fileName.c_str());
readFile.read(reinterpret_cast<char*>(pointer), (parameters.topXlist * sizeof(quadanglesOutput)));
readFile.close();
cout << "done" << endl;
}
int main(int argc, char *argv[])
{
quadanglesOutput a = {0};
cout<<"total score:"<<a.totalScore<<endl;
cout<<"locator position:"<<a.totalScore<<endl;
cout<<"locator position:"<<a.locator1.position<<endl;
cout<<"locator position:"<<a.locator2.normalVector.y <<endl;
cout<<"sizeof quadangsomething:"<<sizeof(quadanglesOutput)<<endl;
a.totalScore=1;
a.locator1.position=333445;
a.locator2.normalVector.y = 999.3224;
cout<<"total score:"<<a.totalScore<<endl;
cout<<"locator position:"<<a.locator1.position<<endl;
cout<<"locator position:"<<a.locator2.normalVector.y <<endl;
param p = {"C:/", 1};
outputQuadangleOutput(&a, "file1", p);
quadanglesOutput *b = new quadanglesOutput();
readIn(b, p, "file1");
cout<<"new total score:"<<b->totalScore<<endl;
cout<<"new locator position:"<<b->locator1.position<<endl;
cout<<"new locator position:"<<b->locator2.normalVector.y <<endl;
delete b;
string asdf;
cin>>asdf;
};
OUTPUT:
total score:0
locator position:0
locator2.normalVector.y :0
sizeof quadangsomething:436
total score:1
locator position:333445
locator2.normalVector.y :999.322
Output C:/ file1.bin...done
openining C:/ file1.bin...done
new total score:1
new locator position:333445
new locator2.normalVector.y :999.322
without pragma it's still correct but you can see the difference in size:
sizeof quadangsomething:440
But packing it is good when sending structures over network.
Because here system alligns it always in the same fashion.

Related

how to sort a string in C++ using sort function

Why I'm getting error in this code
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string s1= "deepak";
cout << s1 << endl;
string s2= sort(s1.begin(), s1.end());
cout << s2 << endl;
return 0;
}
ERROR :
enter image description here
main.cpp:10:20: error: conversion from 'void' to non-scalar type 'std::string'
{aka 'std""__cxx11::basic_string,char>'} requested
The sort function sorts elements in a range, but it does not return the sorted string. You can sort s1 in-place:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string s1= "deepak";
cout << s1 << endl;
sort(s1.begin(), s1.end());
cout << s1 << endl;
return 0;
}
if you want to return a sorted string:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string sortString(string s) {
string sortedString = s;
sort(sortedString.begin(), sortedString.end());
return sortedString;
}
int main()
{
string s1= "deepak";
cout << s1 << endl;
string sortedS1 = sortString(s1);
cout << sortedS1 << endl;
return 0;
}

How to fix C++ argument of type"const char*" is incompatible with parameter of type"char*"

I'm using vs2019 and I have a problem the compiler give me an error however I cant solving that
please help me.
the error is : argument of type"const char*" is incompatible with parameter of type"char*"
Blockquote
*** #include <iostream>
#include<cstring>
using namespace std;
class part
{
public:
char partname[30];
int partnumber;
double cost;
void setpart(char pname[], int pn, double c)
{
strcpy_s(partname, pname);
partnumber = pn;
cost = c;
}
void showpart()const
{
cout << "\npartname : " << partname;
cout << "\npartnumber : " << partnumber;
cout << "\ncost($) : " << cost;
}
};
int main()
{
part part1, part2;
part1.setpart("handle bolt", 467, 4500);
part2.setpart("start lever", 549, 2300);
cout << "\nFirst part : "; part1.showpart();
cout << "\nSecond part : "; part2.showpart();
}***
The strings you are giving to setpart are const strings ( const char *) . But set part take a char * as parameter. Since pname will not be modified in your example you can replace void setpart(char pname[], int pn, double c) by void setpart(const char pname[], int pn, double c)

Building 32bit Float from 4 Bytes [Binary File I/O] in C++

I'm sure this must be a common problem but can't seem to find an equivalent question* or example.
I have a binary file that is a series of 4 byte floats. I am reading into a vector that is sized by the length of the file (divided by the size of my float). I have used the bytesToFloat method from another post. When printing out the data my code returns the same value for all data points. What's wrong?
*Sorry to the admins if I have missed it.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
typedef unsigned char uchar;
float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3);
int main()
{
int i,j;
char u[4];
// Open file
ifstream file;
file.open("file.dat");
// Find file size in bytes
file.seekg(0,ios::end);
double size = 0;
size = file.tellg();
file.seekg(0,ios::beg);
vector<float> data;
data.resize(size/4);
i=0;
while(i<size/4)
{
j=0;
while(j<4)
{
file.read(&u[j],1);
j++;
}
data[i] = bytesToFloat(u[0],u[1],u[2],u[3]);
cout << data[i]<< endl;
i++;
}
// End program
file.close();
return 0;
}
float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3)
{
float output;
*((uchar*)(&output) + 3) = b0;
*((uchar*)(&output) + 2) = b1;
*((uchar*)(&output) + 1) = b2;
*((uchar*)(&output) + 0) = b3;
return output;
}
So with a bit of effort and Igor's comment I was able to solve the problem. The following function reads everything into a buffer vector.
vector<char> buffer;
void fill() {
string filename = "";
cout << "Please enter a filename:\n>";
getline(cin, filename);
ifstream file(filename.c_str());
if (file) {
file.seekg(0,std::ios::end);
streampos length = file.tellg();
cout<< length << endl;
file.seekg(0,std::ios::beg);
file.seekg(540,'\0');
length-=540;
buffer.resize(length);
file.read(&buffer[0],length);
}
}
Then later on I call bytesToFloat in a loop. The endian-ness of bytesToFloat was incorrect so has now been reversed and it outputs the same values as my original file (I made my random file generator output a plain text version for comparison).

C++/cli: How to convert String containing Bytes as characters to double

I have problem converting String^ containing 8 bytes as characters (as ascii) to double.
I want to take those 8 characters and convert them binary to double.
What would you recommend to do this conversion in C++/cli?
I was trying to use Marshal::Copy, Double::TryParse, etc.
Maybe I use wrong specifications of parameters, but I really lost my last hopes.
There must be something easy to do this conversion.
Thanks.
Well, the bad news is that the System.String class uses only Unicode encoding internally.
So if you give it bytes it will map them to its internal encoding hiding the original value.
The good news is that you can play with the System.Text.Encoding class to retrieve 8bits values corresponding to the unicode characters.
Here is a sample :
#include <iostream>
using namespace System;
using namespace System::Text;
int main()
{
int n = 123456;
double d = 123.456;
std::cout << n << std::endl;
std::cout << d << std::endl;
char* n_as_bytes = (char*)&n;
char* d_as_bytes = (char*)&d;
String^ n_as_string = gcnew String(n_as_bytes, 0, sizeof(n));
String^ d_as_string = gcnew String(d_as_bytes, 0, sizeof(d));
Encoding^ ascii = Encoding::GetEncoding("iso-8859-1");
array<Byte>^ n_as_array = ascii->GetBytes(n_as_string);
array<Byte>^ d_as_array = ascii->GetBytes(d_as_string);
cli::pin_ptr<unsigned char> pin_ptr_n = &n_as_array[0];
cli::pin_ptr<unsigned char> pin_ptr_d = &d_as_array[0];
unsigned char* ptr_n = pin_ptr_n;
unsigned char* ptr_d = pin_ptr_d;
int n_out = *(int*)ptr_n;
double d_out = *(double*)ptr_d;
std::cout << n_out << std::endl;
std::cout << d_out << std::endl;
return 0;
}
This should give you :
123456
123.456
123456
123.456
Not sure it is completely safe, but trying it in your context should be a good start to ensure it is viable. :)

Why doesn't unsigned char* work with ifstream::read?

I am a beginner with C++. I have a new project at work where I have to learn it, so I'm trying some things just to test my understanding. For this problem, I'm trying to read a file and then print it on screen. Super simple, just trying to get good at it and understand the functions that I'm using. I copied some text from a MS Word document into a notepad (*.txt) file, and I'm trying to read this *.txt file. All of the text in the word document is bolded, but other than that there are no 'unusual' characters. Everything prints out on the screen as it appears in the document except the bolded " - " symbol. This character is printed as the "u" with a hat character ("so called extended ASCII" code 150). I try to print out the integer value of this character in my array (which should be 150) but I get -106. I realize this signed integer has the same bits as the unsigned integer 150. My question is how to get the output to say 150? Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
unsigned char* input1;
int input1size = 57;
ifstream file("hello_world2.txt",ios::binary | ios::ate);
if (file.is_open()){
int size;
size = (int) file.tellg();
cout <<"This file is " << size << " bytes." << endl;
file.seekg(0,ios::beg);
input1 = new unsigned char[input1size];
file.read(input1, input1size);
cout << "The first " << input1size <<" characters of this file are:" << endl<<endl;
for (int i=0; i<input1size; i++) {
cout << input1[i];
}
cout<<endl;
}
else {
cout <<"Unable to open file" << endl;
int paus;
cin>>paus;
return 0;
}
file.close();
int charcheck = 25;
int a=0;
int a1=0;
int a2=0;
unsigned int a3=0;
unsigned short int a4=0;
short int a5=0;
a = input1[charcheck];
a1 = input1[charcheck-1];
a2 = input1[charcheck+1];
a3 = input1[charcheck];
a4 = input1[charcheck];
a5 = input1[charcheck];
cout <<endl<<"ASCII code for char in input1[" << charcheck-1 <<"] is: " << a1 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] is: " << a << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck+1 <<"] is: " << a2 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as unsigned int: " << a3 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as unsigned short int: " << a4 << endl;
cout <<endl<<"ASCII code for char in input1[" << charcheck <<"] as short int: " << a5 << endl;
int paus;
cin>>paus;
return 0;
}
Output for all this looks like:
This file is 80 bytes.
The first 57 characters of this file are:
STATUS REPORT
PERIOD 01 u 31 JUL 09
TASK 310: APPLIC
ASCII code for char in input1[24] is: 32
ASCII code for char in input1[25] is: -106
ASCII code for char in input1[26] is: 32
ASCII code for char in input1[25] as unsigned int: 4294967190
ASCII code for char in input1[25] as unsigned short int: 65430
ASCII code for char in input1[25] as short int: -106
So it appears "int a" is always read as signed. When I try to make "a" unsigned, it turns all the bits left of the eight bits for the char to 1's. Why is this? Sorry for the length of the question, just trying to be detailed. Thanks!
What you're dealing with is the sign-extension that takes place when the char is promoted to int when you assign it to one of your a? variables.
All the higher order bits must be set to 1 to keep it the same negative value as was in the smaller storage of the char.

Resources