char, hex, because it shows ffffff - c++

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.

Related

Why do I get garbage when I try to parse the binary file in C++?

I'm trying to parse .wav files in C++.
The 44 bytes in the header of the .wav file are some of the file's meta information, which I am trying to parse.
I parsed it in Python and got the following, which should be correct
Chunk_id : RIFF
Chunk_size : 468556
Format : WAVE
fmt_id : fmt
fmt_size : 16
audio_format : 1
channels_count : 1
sample_rate : 44100
byte_rate : 88200
block_align : 2
bits_per_sample : 16
data_id : data
data_size : 468520
But when I switch in to C++, I got this:
ChunkID: RIFFL&
ChunkSize: 468556
Format: WAVEfmt
FmtID: fmt
FmtChunkSize: 16
FmtAudioFormat: 1
FmtChannelNumber: 1
FmtSampleRate: 44100
FmtByteRate: 88200
FmtBlockAlign: 2
FmtBitPerSample: 16
DataChunkID: data(&
The problem is three fields consisting of a char array of four bytes.
ChunkID: RIFFL&, Format: WAVEfmt, DataChunkID: data(&
As parsed by Python, the contents of the three fields should be RIFF, WAVE, data.
And this is my C++ code.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct WaveChunk
{
char ChunkID[4];
int ChunkSize;
char Format[4];
// fmt
char FmtID[4];
int FmtChunkSize;
short FmtAudioFormat;
short FmtChannelNumber;
int FmtSampleRate;
int FmtByteRate;
short FmtBlockAlign;
short FmtBitPerSample;
// fmt
// data
char DataChunkID[4];
int DataChunkSize;
// data
};
string WaveChunkToString(WaveChunk* wavechunk){
stringstream ss;
ss << "ChunkID: " << wavechunk->ChunkID << "\n";
ss << "ChunkSize: " << wavechunk->ChunkSize << "\n";
ss << "Format: " << wavechunk->Format << "\n";
ss << "FmtID: " << wavechunk->FmtID << "\n";
ss << "FmtChunkSize: " << wavechunk->FmtChunkSize << "\n";
ss << "FmtAudioFormat: " << wavechunk->FmtAudioFormat << "\n";
ss << "FmtChannelNumber: " << wavechunk->FmtChannelNumber << "\n";
ss << "FmtSampleRate: " << wavechunk->FmtSampleRate << "\n";
ss << "FmtByteRate: " << wavechunk->FmtByteRate << "\n";
ss << "FmtBlockAlign: " << wavechunk->FmtBlockAlign << "\n";
ss << "FmtBitPerSample: " << wavechunk->FmtBitPerSample << "\n";
ss << "DataChunkID: " << wavechunk->DataChunkID << "\n";
ss << "DataChunkSize: " << wavechunk->DataChunkSize << endl;
return ss.str();
}
using namespace std;
int main(){
WaveChunk w;
ifstream inf("target.wav", ios::binary|ios::in);
inf.read((char* ) &w, sizeof(WaveChunk));
cout << WaveChunkToString(&w);
return 0;
}
That's it, why are these three fields parsed differently than expected, but the other fields made up of numbers are fine?
In this line and the other lines to print char something[4];:
ss << "ChunkID: " << wavechunk->ChunkID << "\n";
std::stringstream will read until null-character '\0' but the array doesn't contain that, so it will read beyond the allocated buffer.
You will have to specify the size to print for properly printing the array without adding extra byte.
It can be done like this:
ss << "ChunkID: "; ss.write(wavechunk->ChunkID, 4); ss << "\n";

'cout' displays integer as hex

I use memcpy to merge multiple bytes into an integer. The Code seems to work and value can be used for further calculations without any problems. But if I display the result with cout, the value is displayed as hex:
Code:
int readByNameInt(const char handleName[], std::ostream& out, long port, const AmsAddr& server)
{
uint32_t bytesRead;
out << __FUNCTION__ << "():\n";
const uint32_t handle = getHandleByName(out, port, server, handleName);
const uint32_t bufferSize = getSymbolSize(out, port, server, handleName);
const auto buffer = std::unique_ptr<uint8_t>(new uint8_t[bufferSize]);
int result;
const long status = AdsSyncReadReqEx2(port,
&server,
ADSIGRP_SYM_VALBYHND,
handle,
bufferSize,
buffer.get(),
&bytesRead);
if (status) {
out << "ADS read failed with: " << std::dec << status << '\n';
return 0;
}
out << "ADS read " << std::dec << bytesRead << " bytes:" << std::hex;
for (size_t i = 0; i < bytesRead; ++i) {
out << ' ' << (int)buffer.get()[i];
}
std::memcpy(&result, buffer.get(), sizeof(result));
out << " ---> " << result << '\n';
releaseHandle(out, port, server, handle);
return result;
}
Result:
Integer Function: readByNameInt():
ADS read 2 bytes: 85 ff ---> ff85
I use an almost identical function to create a float. Here the output works without problems.
How can the value be displayed as an integer?
Greeting
Tillman
That's because you changed the base of the output in the following line:
out << "ADS read " << std::dec << bytesRead << " bytes:" << std::hex;
The std::hex in the end of the line will apply to every subsequent input stream to out.
Change it back to decimal before printing the last line:
out << " ---> " << std::dec << result << '\n';

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();
}

creating a c++ program that displays hexadecimal-formatted data from a bmp file

I'm trying to create a program that displays output of a bmp file in the form of hexadecimal. So far I get the output, but I need it to be organized a certain way.
The way it needs to be organized is with the address of the bmp file to be on the left column and then 16 bytes of data in hex across each row in the order they appear in the file. While leaving an extra space between every 8 bytes. So far, I got the hexadecimal to show up, I just need help with organizing it.
What I have:
What I'm trying to make it look like:
Here is my code:
#include <iostream> // cout
#include <fstream> // ifstream
#include <iomanip> // setfill, setw
#include <stdlib.h>
using namespace std; // Use this to avoid repeated "std::cout", etc.
int main(int argc, char *argv[]) // argv[1] is the first command-line argument
[enter image description here][1]{
// Open the provided file for reading of binary data
ifstream is("C:\\Users\\Test\\Documents\\SmallTest.bmp", ifstream::binary);
if (is) // if file was opened correctly . . .
{
is.seekg(0, is.end); // Move to the end of the file
int length = is.tellg(); // Find the current position, which is file length
is.seekg(0, is.beg); // Move to the beginning of the file
char * buffer = new char[length]; // Explicit allocation of memory.
cout << "Reading " << length << " characters... ";
is.read(buffer, length); // read data as a block or group (not individually)
if (is)
cout << "all characters read successfully.\n";
else
cout << "error: only " << is.gcount() << " could be read.\n";
is.close();
// Now buffer contains the entire file. The buffer can be printed as if it
// is a _string_, but by definition that kind of print will stop at the first
// occurrence of a zero character, which is the string-ending mark.
cout << "buffer is:\n" << buffer << "\n"; // Print buffer
for (int i = 0; i < 100; i++) // upper range limit is typically length
{
cout << setfill('0') << setw(4) << hex << i << " ";
cout << setfill('0') << setw(2) << hex << (0xff & (int)buffer[i]) << " ";
}
delete[] buffer; // Explicit freeing or de-allocation of memory.
}
else // There was some error opening file. Show message.
{
cout << "\n\n\tUnable to open file " << argv[1] << "\n";
}
return 0;
}
You could do it something like this:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <cctype>
std::ostream& fullLine(std::ostream& out, const std::vector<uint8_t>& v, size_t offset)
{
//save stream state so we can restore it after all the hex/setw/setfill nonsense.
std::ios oldState(0);
oldState.copyfmt(out);
out << std::hex << std::setfill('0') << std::setw(8) << offset << " ";
for (size_t i = 0; i < 16; ++i)
{
if (i == 8) out << " ";
out << std::hex << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(v[i + offset]) << " ";
}
out << " ";
//restore stream state to print normal text
out.copyfmt(oldState);
for (size_t i = 0; i < 16; ++i)
{
out << (std::isprint(v[i + offset]) ? static_cast<char>(v[i + offset]) : '.');
}
out << "\n";
return out;
}
int main()
{
std::vector<uint8_t> data;
std::ifstream f("test.txt", std::ios::binary);
if (f)
{
f.seekg(0, f.end);
data.resize(static_cast<size_t>(f.tellg()));
f.seekg(0, f.beg);
f.read((char*)data.data(), data.size());
const size_t numFullLines = data.size() / 16;
const size_t lastLineLength = data.size() % 16;
for (size_t i = 0; i < numFullLines; ++i)
{
if (!fullLine(std::cout, data, i * 16))
{
std::cerr << "Error during output!\n";
return -1;
}
}
}
return 0;
}
There's probably a fancy way to do it, but I usually go for brute force when I'm looking for particular output using iostreams.
How to handle the partial last line is up to you. :)
Use the % operator to break the line after every 16th count:
cout << hex;
for(int i = 0; i < 100; i++)
{
if(i && (i % 16) == 0)
cout << "\n";
cout << setfill('0') << setw(2) << (buffer[i] & 0xFF) << " ";
}
I need it to be organized a certain way.
In another answer, I submitted this form of dumpByteHex()... perhaps it can help you achieve what you want. (see also https://stackoverflow.com/a/46083427/2785528)
// C++ support function
std::string dumpByteHex (char* startAddr, // reinterpret_cast explicitly
size_t len, // allows to char* from T*
std::string label = "",
int indent = 0)
{
std::stringstream ss;
if(len == 0) {
std::cerr << "\n dumpByteHex() err: data length is 0? " << std::endl << std::dec;
assert(len != 0);
}
// Output description
ss << label << std::flush;
unsigned char* kar = reinterpret_cast<unsigned char*>(startAddr); // signed to unsigned
std::string echo; // holds input chars until eoln
size_t indx;
size_t wSpaceAdded = false;
for (indx = 0; indx < len; indx++)
{
if((indx % 16) == 0)
{
if(indx != 0) // echo is empty the first time through for loop
{
ss << " " << echo << std::endl;
echo.erase();
}
// fields are typically < 8 bytes, so skip when small
if(len > 7) {
if (indent) { ss << std::setw(indent) << " "; }
ss << std::setfill('0') << std::setw(4) << std::hex
<< indx << " " << std::flush;
} // normally show index
}
// hex code
ss << " " << std::setfill('0') << std::setw(2) << std::hex
<< static_cast<int>(kar[indx]) << std::flush;
if((indx % 16) == 7) { ss << " "; wSpaceAdded = true; } // white space for readability
// defer the echo-of-input, capture to echo
if (std::isprint(kar[indx])) { echo += kar[indx]; }
else { echo += '.'; }
}
// finish last line when < 17 characters
if (((indx % 16) != 0) && wSpaceAdded) { ss << " "; indx++; } // when white space added
while ((indx % 16) != 0) { ss << " "; indx++; } // finish line
// the last echo
ss << " " << echo << '\n';
return ss.str();
} // void dumpByteHex()
Output format:
0000 11 22 33 44 55 66 00 00 00 00 77 88 99 aa ."3DUf....w...

Why do I have to cast a byte as unsigned twice to see hex output? [duplicate]

This question already has answers here:
Are int8_t and uint8_t intended to be char types?
(5 answers)
Closed 7 years ago.
I want to print a variable as hex:
#include <iostream>
#include <string>
#include <cstdint>
int main() {
auto c = 0xb7;
std::cout << std::hex << static_cast<unsigned char>(c) << std::endl;
std::cout << std::hex << static_cast<unsigned>(static_cast<unsigned char>(c)) << std::endl;
std::cout << std::hex << (uint8_t)(c) << std::endl;
std::cout << std::hex << (unsigned)(uint8_t)(c) << std::endl;
return 0;
}
The output seems to be:
\ufffd (tries to print it as a char)
b7
\ufffd (tries to print it as a char)
b7
I do understand that c has higher bits set (10110111), but I cast it to uint8_t and unsigned char once already.
Why do I have to cast uint8_t or unsigned char to unsigned again to get the expected output?
std::hex sets the basefield of the stream str to hex as if by calling str.setf(std::ios_base::hex, std::ios_base::basefield).
When this basefield hex bit is set, iostreams use hexadecimal base for integer I/O.
Code
#include <iostream>
int main()
{
int i = 0xb7;
unsigned u = 0xb7;
char c = static_cast<char>(0xb7);
unsigned char b = 0xb7;
std::cout << std::hex << i << std::endl;
std::cout << std::hex << u << std::endl;
std::cout << std::hex << c << std::endl;
std::cout << std::hex << b << std::endl;
return 0;
}
Output
b7
b7
�
�
I suspect this output to vary on a Windows (non UTF-8) system.