Unexpected big endian conversion output - c++

I am using libflac and I need to convert my data from little endian to big endian. However in one of my test code i am not getting what I expect. I am using g++
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
int main() {
unsigned char transform[4];
unsigned char output[4];
unsigned char temp;
int normal = 24000;
memcpy(output, &normal, 4);
std::cout << (int)output[0] << " " << (int)output[1] << " " << (int)output[2] << " " << (int)output[3] << "\n";
//FLAC__int32 big_endian;
int big_endian;
short allo = 24000;
memcpy(transform, &allo, 2); // transform[0], transform[1]
std::cout << (int)transform[0] << " " << (int)transform[1] << "\n";
//big_endian = (FLAC__int32)(((FLAC__int16)(FLAC__int8)transform[1] << 8) | (FLAC__int16)transform[0]); // whaaat, doesn't work...
big_endian = transform[1] << 8 | transform[0]; // this also give 192 93 0 0 uh?
memcpy(output, &big_endian, 4);
std::cout << (int)output[0] << " " << (int)output[1] << " " << (int)output[2] << " " << (int)output[3] << "\n";
// 192 93 0 0 uh?
// this one works
transform[3] = transform[0];
transform[2] = transform[1];
transform[0] = 0;
transform[1] = 0;
memcpy(&big_endian, transform, 4);
memcpy(output, &big_endian, 4);
std::cout << (int)output[0] << " " << (int)output[1] << " " << (int)output[2] << " " << (int)output[3] << "\n";
// 0 0 93 192 (binary)93 << 8 | (binary)192 = 24000
return 0;
}
output:
192 93 0 0
192 93
192 93 0 0
0 0 93 192
When I do
big_endian = transform[1] << 8 | transform[0];
I'd expect to see 93 192 0 0 or 0 0 93 192, what's going on?

The problem is in this line
big_endian = transform[1] << 8 | transform[0];
transform[0] is keeping the LSB in little endian. When you do transform[1] << 8 | transform[0] you store it in the LSB position, therefore it doesn't move anywhere and is still the lowest byte. The same to transform[1] which is the second byte and it's still the second byte after shifting.
Use this
big_endian = transform[0] << 8 | transform[1];
or
big_endian = transform[0] << 24 | transform[1] << 16 | transform[2] << 8 | transform[3];
But why don't just write a function for endian conversion?
unsigned int convert_endian(unsigned int n)
{
return (n << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | (n >> 24);
}
or use the ntohl/ntohs function that is already available on every operating systems

Related

Convert 16 bits to 4 char ( in Hexadecimal)

I want to convert 16 bit to 4 characters which are in Hexadecimal character.
For example, a 16 bit, 1101 1010 1101 0001 in hexadecimal is DAD1 and in decimal is 56017. Now I want to convert this 16 bit into DAD1 as characters so that I can use the character to write into a text file.
My coding part, my variable "CRC" is my result from CRC checksum. Now I want to convert 16 bit "CRC" into 4 characters which are DAD1 (capital letters).
cout << hex << CRC<<endl;
char lo = CRC & 0xFF;
char hi = CRC >> 8;
cout << hi << endl;
cout << lo;
*******Result********
dad1
┌
₸
Try this:
#include <iostream>
#include <bitset>
#include <string>
int main()
{
int i = 56017;
std::cout <<hex <<i << std::endl;
std::bitset<16> bin = i;
std::string str = bin.to_string();
std::bitset<8> hi(str.substr(0, 8));
std::bitset<8> lo(str.substr(8, 8));
std::cout << bin << std::endl;
std::cout << hi << " " << hi.to_ullong() << std::endl;
std::cout << lo << " " << lo.to_ullong() << std::endl;
}
OR you can also do
std::cout <<hex << (CRC & 0xFF)<< std::endl;
std::cout << hex << (CRC >> 8) << std::endl;
Output:
Try This :
#include <iostream>
#include <bitset>
#include <limits>
int main()
{
int i = 56017;
std::bitset<std::numeric_limits<unsigned long long>::digits> b(i);
std::cout<< std::hex << b.to_ullong();
}

C++: Unable to set type int to non-scalar after bitwise functions

I have two bitfields: (1) one to handle the frame (header), (2) the other to handle a subframe within a frame (identityFieldO2M).
union header
{
unsigned char arr[16]; // 128 bytes allocated
BitFieldMember<0, 1> SOF;
BitFieldMember<1, 11> BID;
BitFieldMember<12, 1> SRR;
BitFieldMember<13, 1> IDE;
BitFieldMember<14, 18> IDEX;
BitFieldMember<32, 1> RTR;
BitFieldMember<33, 1> r1;
BitFieldMember<34, 1> r0;
BitFieldMember<35, 4> DLC;
BitFieldMember<39, 8> DataField1;
BitFieldMember<47, 15> CRC;
BitFieldMember<62, 1> CRCDelim;
BitFieldMember<63, 1> ACKSlot;
BitFieldMember<64, 1> ACKdelim;
BitFieldMember<65, 7> eof;
};
union identityFieldO2M
{
unsigned char arr[5]; // 3 bytes allocated though only need 29 bits
BitFieldMember<0, 2> RCI;
BitFieldMember<2, 14> DOC;
BitFieldMember<16, 1> PVT;
BitFieldMember<17, 1> LCL;
BitFieldMember<18, 1> FSB;
BitFieldMember<19, 7> SourceFID;
BitFieldMember<26, 3> LCC;
};
I need to process first the first bitfield and from there I am combining two members of this bitfield and then running their combined output into another bitfield to determine subframes. The issue I have it, however, is when I do the bitwise function to combine the two bitfields, I am not able to pass this data back into the bitfield.
I think I am doing something "duh" wrong but I am not able to figure this out. Below is my implementation:
int main()
{
header a;
memset(a.arr, 0, sizeof(a.arr));
a = {0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0}; // 1010 0000
cout << hex << a.SOF << endl; // 1 -> 1
cout << hex << a.BID << endl; // 010 0000 1010 -> 20a
cout << hex << a.SRR << endl; // 0 -> 0
cout << hex << a.IDE << endl; // 0 -> 0
cout << hex << a.IDEX << endl; // 00 1010 0000 1010 0000 -> a0a0
cout << hex << a.RTR << endl; // 1 -> 1
cout << hex << a.r1 << endl; // 0 -> 0
cout << hex << a.r0 << endl; // 1 -> 1
cout << hex << a.DLC << endl; // 0 000 -> 0
cout << hex << a.DataField1 << endl; // 0 1010 000 -> 50
cout << hex << a.CRC << endl; // 0 1010 0000 1010 00 -> 2828
cout << hex << a.CRCDelim << endl; // 0 -> 0
cout << hex << a.ACKSlot << endl; // 0 -> 0
cout << hex << a.ACKdelim << endl; // 1 -> 1
cout << hex << a.eof << endl; // 010 0000 -> 20
int BID = a.BID;
int IDEX = a.IDEX;
int result = (BID<<18) | IDEX; // concatenate BID and IDEX together to get 29 bit header
cout << "test" << endl;
cout << "BID: " << hex << BID << endl; //-> 20a -> 010 0000 1010
cout << "IDEX: " << hex << IDEX << endl; //-> a0a0-> 00 1010 0000 1010 0000
cout << "Identifier Field: " << hex << result << endl; //-> 828a0a0 -> 01 0000 0101 0001 01 0 0 0 0010100 000
cout << "Size of Bitfield header: " << sizeof(a) << endl;
identityFieldO2M b;
b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
memset(b.arr,0,sizeof(b.arr));
cout << hex << b.RCI << endl; // 01 -> 0x01
cout << hex << b.DOC << endl; // 0000 0101 0001 01 -> 0x145
cout << hex << b.PVT << endl; // 0 -> 0x00
cout << hex << b.LCL << endl; // 0 -> 0x00
cout << hex << b.FSB << endl; // 0 -> 0x00
cout << hex << b.SourceFID << endl; // 0010100 -> 0x14
cout << hex << b.LCC << endl; // 000 -> 0 -> 0x00
sleep(100);
return 0;
}
where the error happens when I am setting the result of concatenate BID and IDEX to struct b:
identityFieldO2M b;
b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
memset(b.arr,0,sizeof(b.arr));
For the BitFieldMember template I am using this very helpful template here:
https://codereview.stackexchange.com/questions/54342/template-for-endianness-free-code-data-always-packed-as-big-endian
Looking through the definition of the BitFieldMember template, here is the operand = to assign values into the field, where I suspect this issue may lay?
/* used to assign a value into the field */
inline self_t& operator=(unsigned m)
{
uchar *arr = selfArray();
m &= mask;
unsigned wmask = ~(mask << (7 - (lastBit & 7)));
m <<= (7 - (lastBit & 7));
uchar *p = arr + lastBit / 8;
int i = (lastBit & 7) + 1;
(*p &= wmask) |= m;
while (i < bitSize)
{
m >>= 8;
wmask >>= 8;
(*(--p) &= wmask) |= m;
i += 8;
}
return *this;
}
According to your bitfield definition, you need to use an unsigned char[5] and it's expecting big endian values (from following the link to where you got this code). You cannot assign it to an int as you have seen from your compiler error. One option is to copy your int value into your big endian b.arr through bit shifting. Something like this should do it.
int result = 0x0828a0a0;
identityFieldO2M b;
b.arr[0] = (result >> 24) & 0xFF; // 0x08
b.arr[1] = (result >> 16) & 0xFF; // 0x28
b.arr[2] = (result >> 8) & 0xFF; // 0xa0
b.arr[3] = result & 0xFF; // 0xa0

(C++) Need help resolving Output file error

Priority:
I am quite new at this obviously. I have tried reading other peoples errors for what I have and can't find a fix. When I take out the ofstream bit and switch fOut for cout then program works fine but I cant seem to get it to output to a file. I did make the file in advance.
Secondary:
I am suppose to also somehow use 1 loop for the range of x should be 0 to 10 in steps of 1, 10 to 50 in steps of 5( In the SquareMachine function). Same rule of 1 loop for the bit in main with 0 to 15 in 1 degree increments and 15 to 45 in 5 degree increments. I am sure there is a technique I am simply not seeing to combine my loops or perhaps a loop... hole.. hah get it? Anyway, primarily need assistance with the output file.
Thank you for any advice/assistance
Error(s):
week4.cpp: In function ‘void ShowProgramHeader()’:
week4.cpp:34: error: ‘fOut’ was not declared in this scope
week4.cpp: In function ‘int main()’:
week4.cpp:44: error: ‘struct std::ofstream’ has no member named ‘is’
week4.cpp: In function ‘int SquareMachine()’:
week4.cpp:92: error: ‘fOut’ was not declared in this scope
Code:
#include <cmath>
#include<stdlib.h>
#include <iostream>
#include t<ime.h>
#include<cstdlib>
#include<unistd.h>
#include<iomanip>
#include<fstream>
using namespace std;
//Global Variable(s)
long fact(long n);
// Prototype(s)
int SquareMachine();
// Program Header
void ShowProgramHeader()
{
fOut << "Name" << endl;
fOut << "Class and Date \n\n\n" << endl;
}
//Command Center
int main()
{
ofstream fOut( "sTable.out", ios::out| ios::trunc);
if( fOut.is.open())
{
ShowProgramHeader();
SquareMachine();
fOut << "Value---Output\n"<<endl;
for( long t =0; t <=15; t++)
{
fOut << setw(10) << t;
fOut << setw(20) << fact(t) << endl;
}
for( long t =20; t <=45; t=t+5)
{
fOut << setw(10) << t;
fOut << setw(20) << fact(t) << endl;
fOut.close();
}
}
else
cout<<"Unable to Open the file: sTable.out";
exit(-1);
}
long fact(long n)
{
if( n ==0 || n==1 )
return 1;
else if( n==2 || n <= 15)
return n * fact( n-1);
else if( n <=15 || n <=45)
return n * fact (n-5);
}
int SquareMachine()
{
double x = 10;
int n = 2;
double z;
fOut << "\nNumber Sqrt Exp Pow\n";
for ( z=0; z<=x; ++z)
{
fOut << setw(10) << left << z << setprecision(2);
fOut << setw(10) << left << sqrt(z) << setprecision(3);
fOut << setw(10) << left << exp(z) << setprecision(10);
fOut << setw(10) << left << pow(z,n) << setprecision(4);
fOut << "\n" ;
}
for ( z=15; z<=50; z= z+5)
{
fOut << setw(10) << left << z << setprecision(2);
fOut << setw(10) << left << sqrt(z) << setprecision(3);
fOut << setw(10) << left << exp(z) << setprecision(10);
fOut << setw(10) << left << pow(z,n) << setprecision(4);
fOut << "\n" ;
}
fOut << " \n End of Part 1\n"<< endl;
}
You have numerous errors in your code. Mostly optimization errors, also some typos. But always, you should listen to your compiler first, because it helps you find the problem. It is designed to do so!
Sometimes it literally says what you should do (or what not) in a case of error.
For example your compiler says:
week4.cpp: In function ‘void ShowProgramHeader()’:
week4.cpp:34: error: ‘fOut’ was not declared in this scope
It means that in that function's scope fOut cannot be seen. It is because it was declared in the main() function, so it is a local variable (only avaiable in a scope) and not global (avaiable from everywhere). If you want to use this variable in other functions too, it is a good practice to use references or pointers. (I would recommend you using global variables only if you really need to do so, in special cases)
Included headers: (don't include unnecessary headers)
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath> // for Mathematical functions
Function prototypes:
void ShowProgramHeader(std::ofstream&);
long fact(long);
int SquareMachine(std::ofstream&);
Client code:
int main() {
std::ofstream f_out("sTable.txt", std::ios::out | std::ios::trunc);
if(f_out.is_open()) {
ShowProgramHeader(f_out);
SquareMachine(f_out);
f_out << std::endl << std::left << std::setw(10) << "Number";
f_out << std::left << std::setw(10) << "Output" << std::endl;
long i = 0; // for fact(long)
while(i <= 45) {
if(i <= 15 || i >= 20) {
f_out << std::left << std::setw(10) << i;
f_out << std::left << std::setw(10) << fact(i) << std::endl;
if(i <= 15) i++;
else i += 5;
} else i++;
}
f_out.close();
}
else {
std::cerr << "Unable to Open the file: sTable.out";
return -1;
}
return 0;
}
Function implementations from here!
Header (I'm not really sure what you are planning to do with this function):
void ShowProgramHeader(std::ofstream& f_out) { f_out << "Name\nClass and Date\n"; }
Square machine:
int SquareMachine(std::ofstream& f_out) {
f_out << std::endl << std::left << std::setw(10) << "Number";
f_out << std::left << std::setw(10) << "Square";
f_out << std::left << std::setw(20) << "Exp";
f_out << std::left << std::setw(10) << "Power" << std::endl;
float i = 0;
while (i <= 50) {
if(i <= 10 || i >= 15) {
f_out << std::left << std::setw(10) << std::setprecision(2) << i;
f_out << std::left << std::setw(10) << std::setprecision(3) << std::sqrt(i);
f_out << std::left << std::setw(20) << std::setprecision(10) << std::exp(i);
f_out << std::left << std::setw(10) << std::setprecision(4) << std::pow(i, 2) << std::endl;
if(i <= 10) i++;
else i += 5;
} else i++;
}
f_out << std::endl << "End of Part 1" << std::endl;
}
And finally the recursive factorial function! (You overcomplicated your solution, if you meant to use the factorial method). Also note that when your factorial's value becomes so big, you have to handle it. You should find a type that can store larger numbers than long!
long fact(long n) {
if(n <= 1) return 1;
return n * fact(n - 1);
}
Output (I used sTable.txt instead of sTable.out)
Name
Class and Date
Number Square Exp Power
0 0 1 0
1 1 2.718281746 1
2 1.41 7.389056206 4
3 1.73 20.08553696 9
4 2 54.59814835 16
5 2.24 148.4131622 25
6 2.45 403.4288025 36
7 2.65 1096.633179 49
8 2.83 2980.958008 64
9 3 8103.083984 81
10 3.16 22026.46484 100
15 3.87 3269017.25 225
20 4.47 485165184 400
25 5 7.200490291e+010 625
30 5.48 1.068647422e+013 900
35 5.92 1.586013445e+015 1225
40 6.32 2.353852703e+017 1600
45 6.71 3.493427058e+019 2025
50 7.07 5.184705458e+021 2500
End of Part 1
Number Output
0 1
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
11 39916800
12 479001600
13 1932053504 // long storage problem starts from here
14 1278945280 // wrong!
15 2004310016 // wrong!
20 -2102132736 // wrong!
25 2076180480 // wrong!
30 1409286144 // wrong!
35 0 // wrong!
40 0 // wrong!
45 0 // wrong!
Since long can contain a value up to ~2,1*10^9, however 13! ~ 6*10^9!

char, hex, because it shows ffffff

I have a char [], with the buffer name, the data is saved using an ifstream in binary mode,
void File::mostrarBuffer(){
for (int a = 0; a < std::strlen(buffer); a++){
std::cout << std::hex << ((int)buffer[a]) << std::endl;
}
// para ver char test, only for test
std::cout << "===" << std::endl;
for (int a = 0; a < std::strlen(buffer); a++){
std::cout << buffer[a] << std::endl;
}
char charTest = '\211';
std::cout << "===" << std::endl;
std::cout << std::hex << (int)charTest << std::endl;
std::cout << std::hex << (int)buffer[0] << std::endl;
}
the shell out:
ffffff89
50
4e
47
===
\211
P
N
G
===
ffffff89
ffffff89
the file in hexdump ("little-endian"):
0000000 5089 474e 0a0d 0a1a 0000 0d00 4849 5244
my question is why, appears ffffff89 and not 89, and only on the first element of char [] I've been around with this and can not find the solution. thanks for reading.
this solution works for me:
std::cout << std::hex << ((unsigned int)(unsigned char)buffer[a])
<< std::endl;
Because your chars are signed (highest bit is set).
I'm sorry, I'm not familiar with using std::hex but you somehow need to treat it like an unsigned char value. Try casting the char to and unsigned type.

Read bytes and its decimal value from any kind of file in C++

This may have been answered before but I've tried several ways with no success.
What I need is to read all the bytes of any file type in C++ and access the decimal value of each byte.
Eg
some_file.txt
   ab¶
Expected outcome of each byte would be (in binary):
   01100001 01100010 11110100
Final result as a decimal (NEED THIS):
   97 98 244
some_file.bin
   01000001 01000010 11110100
Would have to read the 8 bits of each byte and return each value in decimal (NEED THIS)
65 66 244
-
For the curious, I need the decimal to access the position of a heap that was assembled following the ASCII table to count the occurrence of each character.
EDIT -
I have the following code to read any kind of file:
readFile.cpp
char* mem;
void readFile(char* file_name)
{
ifstream::pos_type size;
ifstream file;
file.open(file_name, ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
mem = new char[size];
file.seekg(0, ios::beg);
file.read(mem, size);
file.close();
delete[] mem;
}else{
cout << "Not able to open the file";
}
}
main.cpp
if(argc != 2) {
exit(1);
}
char* fileName = argv[1];
readFile(fileName);
cout << mem[0] << " | dec: " << (int) (unsigned char) mem[0] << endl;
cout << mem[1] << " | dec: " << (int) (unsigned char) mem[1] << endl;
cout << mem[2] << " | dec: " << (int) (unsigned char) mem[2] << endl;
cout << mem[3] << " | dec: " << (int) (unsigned char) mem[3] << endl;
When the input file is something like "abc", the output is correct:
a | dec: 97
b | dec: 98
c | dec: 99
But when the input contains some extended ASCII char, the output gets crazy:
input = a¶aa
output =
a | dec: 97
\ | dec: 92
2 | dec: 50
6 | dec: 54
Just cast through unsigned char (This works in C# too, using char or byte) to int to get the character code. To the computer, it is just a number, no distinction between binary or decimal.
cout << mem[0] << " | dec: " << (int)(unsigned char)mem[0] << endl;
But you have to do this before you delete[] mem. Consider using vector<char> or std::string instead.
Your file doesn't have the bytes you expect. Your C++ code shows the content is
61 C2 B6 61
With the help of http://www.percederberg.net/tools/text_converter.html:
C++ is not wrong, those really are the bytes in the file.