Building 32bit Float from 4 Bytes [Binary File I/O] in C++ - visual-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).

Related

How to return a int converted to char array back to main for displaying it

My doubts are as follows :
1 : how to send 'str' from function 'fun' , So that i can display it in main function.
2 : And is the return type correct in the code ?
2 : the current code is displaying some different output.
char * fun(int *arr)
{
char *str[5];
int i;
for(i=0;i<5;i++)
{
char c[sizeof(int)] ;
sprintf(c,"%d",arr[i]);
str[i] = malloc(sizeof(c));
strcpy(str[i],c);
}
return str;
}
int main()
{
int arr[] = {2,1,3,4,5},i;
char *str = fun(arr);
for(i=0;i<5;i++)
{
printf("%c",str[i]);
}
return 0;
}
how to send 'str' from function 'fun' , So that i can display it in main function.
This is the way:
char* str = malloc( size );
if( str == NULL ) {
fprintf( stderr,"Failed to malloc\n");
}
/* Do stuff with str, use str[index],
* remember to free it in main*/
free(str);
And is the return type correct in the code ?
No, Probably char** is the one you need to return.
the current code is displaying some different output.
Consider explaining what/why do you want to do ? The way you have written, seems completely messed up way to me. You're passing array of integer but not its length. How is the fun() supposed to know length of array? Another problem is array of pointers in fun().
You can't write a int to a char (See the both size). So I used char array instead.
However, I'm not sure if this is what you want to do (might be a quick and dirty way of doing it):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char**
fun(int *arr, int size)
{
char **str = malloc( sizeof(char*)*size );
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
int i;
for(i=0;i<5;i++) {
str[i] = malloc(sizeof(int));
if( str == NULL ) {
fprintf( stderr, "Failed malloc\n");
}
sprintf(str[i],"%d",arr[i]);
}
return str;
}
int
main()
{
int arr[] = {2,1,3,4,5},i;
char **str = fun(arr, 5);
for(i=0;i<5;i++) {
printf("%s\n",str[i]);
free(str[i]);
}
free(str);
return 0;
}
I made these changes to your code to get it working:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **fun(int *arr)
{
char **str = malloc(sizeof(char *) * 5);
int i;
for(i = 0; i < 5; i++) {
if ((arr[i] >= 0) && (arr[i] <= 9)) {
char c[2] ;
sprintf(c, "%d", arr[i]);
str[i] = (char *) malloc(strlen(c) + 1);
strcpy(str[i],c);
}
}
return str;
}
int main()
{
int arr[] = {2, 1, 3, 4, 5}, i;
char **str = fun(arr);
for(i = 0; i < 5; i++) {
printf("%s", str[i]);
free(str[i]);
}
printf("\n");
free(str);
return 0;
}
Output
21345
I added a check to make sure that arr[i] is a single digit number. Also, returning a pointer to a stack variable will result in undefined behavior, so I changed the code to allocate an array of strings. I don't check the return value of the malloc calls, which means this program could crash due to a NULL pointer reference.
This solution differs from the others in that it attempts to answer your question based on the intended use.
how to send 'str' from function 'fun' , So that i can display it in main function.
First, you need to define a function that returns a pointer to array.
char (*fun(int arr[]))[]
Allocating variable length strings doesn't buy you anything. The longest string you'll need for 64bit unsigned int is 20 digits. All you need is to allocate an array of 5 elements of 2 characters long each. You may adjust the length to suit your need. This sample assumes 1 digit and 1 null character. Note the allocation is done only once. You may choose to use the length of 21 (20 digits and 1 null).
For readability on which values here are related to the number of digits including the terminator, I'll define a macro that you can modify to suit your needs.
#define NUM_OF_DIGITS 3
You can then use this macro in the whole code.
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
Finally the receiving variable in main() can be declared and assigned the returned array.
char (*str)[NUM_OF_DIGITS] = fun(arr);
Your complete code should look like this:
Code
char (*fun(int arr[]))[]
{
char (*str)[NUM_OF_DIGITS] = malloc(5 * NUM_OF_DIGITS);
int i;
for(i=0;i<5;i++)
{
snprintf(str[i],NUM_OF_DIGITS,"%d",arr[i]); //control and limit to single digit + null
}
return str;
}
int main()
{
int arr[] = {24,1,33,4,5},i;
char (*str)[NUM_OF_DIGITS] = fun(arr);
for(i=0;i<5;i++)
{
printf("%s",str[i]);
}
free(str);
return 0;
}
Output
2413345
With this method you only need to free the allocated memory once.

C++ trouble with outputing sum/avg

am taking a class of C++ and been asked to write a program that reads integers from a file.
first request is to output all of the integers in one line
and the second request is to output the average of the integers
ive tried what has been written in the book, and when I try to cout the sum or the average, it output the addition number by number not just the total
how can I fix this? i want the simplest code possible, I dont want anything that we didnt take in class yet
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
ifstream infile;
ofstream outfile;
int main()
{
int num;
ifstream infile;
ofstream outfile;
outfile.open("Answer.txt");
infile.open("DataFile2.txt");
infile >> num;
while (infile)
{
outfile << num << " ";
infile >> num;
}
infile.close();
infile.open("DataFile2.txt");
int sum = 0;
while (infile)
{
double avg;
infile >> num;
sum = sum + num;
avg = sum / 14;
cout << endl << sum << avg;
}
}
There are a lot of mistakes in your code.You should declare the avg variable outside the while loop.Also, you should calculate the average and print it after the while loop has finished looping.Also you are dividing the sum by 14 (constant) which is not good, since you don't know how many integers are in the file.
The code should look something like this:
int sum = 0;
double avg;
while (infile) {
infile >> num;
sum = sum + num;
}
avg = sum / 14;
cout << endl << sum << avg;

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. :)

Converting a decimal array into a 2D 16bit character array in C++

i want to convert decimal values to 16 bit binary values. i used this code in another one.
#include <iostream>
#include <bitset>
int main() {
int x = 5;
std::bitset<8> bin_x(x);
std::cout << bin_x;
return 0;
}
this is a code posted by a member. i want to use it in a loop and store the value of bin_x in a 16 two dimensional character array. how can it be done?
here is what iam doing
#include<iostream>
using namespace std;
#include <bitset>
int main(){
int DecimalArray[] = {1,2,3,4,5,22,555,85,18,741}; //Create an array of decimal numbers.
const int ArrayLen = sizeof(DecimalArray)/sizeof(int); //Store the size of the Decimal Array in a constant
//strcpy(BinaryArray[i], "0000000000000000");
char BinaryArray[ArrayLen][16]; //Create an array of the same length for binary nos.
for(int i = 0; i<ArrayLen; i++)
{
int CurrentDec = DecimalArray[i]; //Store current Decimal number in CurrentDec variable
strcpy(BinaryArray[i], "0000000000000000");
std::bitset<16> bin_x(CurrentDec);
cout<< "bin"<<bin_x<< endl;
for (int j = 0; j<15; j++)
{
bin_x=BinaryArray[i][j];
cout<< "b1"<< BinaryArray[i] << endl;
}
cout<<"The Decimal numbers and their Binary Equivalents are:\n\n";
cout<<"Decimal Binary \n\n";
}
//Output both arrays
for( i = 0; i<ArrayLen; i++){
cout<<DecimalArray[i]<<"\t "<<BinaryArray[i]<<endl;
}
cin.get();
return 0;
}
but i do not get the value in BinaryArray. kindly help me with it, its very urgent. Thanks!
#include<iostream>
using namespace std;
#include <bitset>
int main(){
int DecimalArray[] = {1,2,3,4,5,22,555,85,18,741}; //Create an array of decimal numbers.
const int ArrayLen = sizeof(DecimalArray)/sizeof(int); //Store the size of the Decimal Array in a constant
//strcpy(BinaryArray[i], "0000000000000000");
char BinaryArray[ArrayLen][17]; //Create an array of the same length for binary nos.
int i;
for(i = 0; i<ArrayLen; i++)
{
int CurrentDec = DecimalArray[i]; //Store current Decimal number in CurrentDec variable
int index = 1, CurrentBin = 0;
strcpy(BinaryArray[i], "0000000000000000");
std::bitset<16> bin_x(CurrentDec);
cout<< "bin"<<bin_x<< endl;
for (int j = 0; j<16; j++)
{
if (bin_x[15-j])
{
BinaryArray[i][j] = '1';
}
cout<< "b1"<< BinaryArray[i][j]<<endl ;
}
}
cout<<"The Decimal numbers and their Binary Equivalents are:\n\n";
cout<<"Decimal Binary \n\n";
//Output both arrays
for( i = 0; i<ArrayLen; i++){
cout<<DecimalArray[i]<<"\t "<<BinaryArray[i]<<endl;
}
cin.get();
return 0;
}

Outputting large structures to HD

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.

Resources