I am using sscanf to put a MAC address from a string into a uint8 array. For some reason, the uint8 array is all blank.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
std::string mac = "00:00:00:00:00:00";
uint8_t smac[7];
memset(smac, 0, 7);
sscanf(
mac.c_str(),
"%hhu:%hhu:%hhu:%hhu:%hhu:%hhu",
&smac[0],
&smac[1],
&smac[2],
&smac[3],
&smac[4],
&smac[5]
);
std::cout << "string: " << mac << std::endl;
std::cout << "uint8_t: "<< smac;
return 0;
}
uint8_t is on most platforms a typedef for unsigned char. Therefore, cout is trying to print it as a string, but it encounters a null byte (or string terminator) as the first character, so it stops printing.
A solution here would be to print all the MAC address members individually:
for(int c = 0; c < sizeof(smac); c++)
{
std::cout << +smac[c];
if(c != sizeof(smac) - 1)
std::cout << "::";
}
std::cout << '\n';
The + here performs integer promotion so smac[c] will be printed as a number and not a character.
The types uint8_t and unsigned char are generally equivalent to the compiler. The convention for outputting an array of char (unsigned or not) is to stop when you reach a value of zero, because that indicates the end of the string.
Related
I have this code:
#include <iostream>
#include <cstdlib>
#include <stdio.h>
int main()
{
std::string napis = "Inhibitor";
int length = napis.length();
char hex[256];
std::cout << "Original: " << napis << '\n';
for (int i = 0; i < length; i++)
{
char buffer[2];
itoa(napis[i], buffer, 16);
hex[2*i] = buffer[0];
hex[2*i+1] = buffer[1];
}
for (int i = 0; i < length * 2 + 1; i++)
{
std::cout << hex[i];
}
}
After all those operations I get that hex[0] == 0. Don't really know why. I am not setting this value anywhere I guess. Program is supposed to code string into hexadecimal.
The itoa function will write a terminating nul character into the buffer. In your code, this it will write 2 or 3 characters (depending in the ASCII value of the character in the string), which can exceed the array bounds.
The solution is to increase the size of buffer by at least 1:
char buffer[4];
Even better is to use the non-deprecated name (_itoa), which, in C++ with a character array, will call the safe version of the function (_itoa_s) which will detect buffer overruns.
Just avoid the temporary buffer and write directly in the result buffer.
char str[] {"abcdefg"};
char hex[256];
for (uint i {0}; i < sizeof(str) - 1; ++i) {
::sprintf (&hex[i*2], "%02X", str[i]);
}
std::cout << "Hex: " << hex << std::endl;
I have a weird problem about working with integers in C++.
I wrote a simple program that sets a value to a variable and then prints it, but it is not working as expected.
My program has only two lines of code:
uint8_t aa = 5;
cout << "value is " << aa << endl;
The output of this program is value is
I.e., it prints blank for aa.
When I change uint8_t to uint16_t the above code works like a charm.
I use Ubuntu 12.04 (Precise Pangolin), 64-bit, and my compiler version is:
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
It doesn't really print a blank, but most probably the ASCII character with value 5, which is non-printable (or invisible). There's a number of invisible ASCII character codes, most of them below value 32, which is the blank actually.
You have to convert aa to unsigned int to output the numeric value, since ostream& operator<<(ostream&, unsigned char) tries to output the visible character value.
uint8_t aa=5;
cout << "value is " << unsigned(aa) << endl;
Adding a unary + operator before the variable of any primitive data type will give printable numerical value instead of ASCII character(in case of char type).
uint8_t aa = 5;
cout<<"value is "<< +aa <<endl; // value is 5
uint8_t will most likely be a typedef for unsigned char. The ostream class has a special overload for unsigned char, i.e. it prints the character with the number 5, which is non-printable, hence the empty space.
Making use of ADL (Argument-dependent name lookup):
#include <cstdint>
#include <iostream>
#include <typeinfo>
namespace numerical_chars {
inline std::ostream &operator<<(std::ostream &os, char c) {
return std::is_signed<char>::value ? os << static_cast<int>(c)
: os << static_cast<unsigned int>(c);
}
inline std::ostream &operator<<(std::ostream &os, signed char c) {
return os << static_cast<int>(c);
}
inline std::ostream &operator<<(std::ostream &os, unsigned char c) {
return os << static_cast<unsigned int>(c);
}
}
int main() {
using namespace std;
uint8_t i = 42;
{
cout << i << endl;
}
{
using namespace numerical_chars;
cout << i << endl;
}
}
output:
*
42
A custom stream manipulator would also be possible.
The unary plus operator is a neat idiom too (cout << +i << endl).
It's because the output operator treats the uint8_t like a char (uint8_t is usually just an alias for unsigned char), so it prints the character with the ASCII code (which is the most common character encoding system) 5.
See e.g. this reference.
cout is treating aa as char of ASCII value 5 which is an unprintable character, try typecasting to int before printing.
The operator<<() overload between std::ostream and char is a non-member function. You can explicitly use the member function to treat a char (or a uint8_t) as an int.
#include <iostream>
#include <cstddef>
int main()
{
uint8_t aa=5;
std::cout << "value is ";
std::cout.operator<<(aa);
std::cout << std::endl;
return 0;
}
Output:
value is 5
As others said before the problem occurs because standard stream treats signed char and unsigned char as single characters and not as numbers.
Here is my solution with minimal code changes:
uint8_t aa = 5;
cout << "value is " << aa + 0 << endl;
Adding "+0" is safe with any number including floating point.
For integer types it will change type of result to int if sizeof(aa) < sizeof(int). And it will not change type if sizeof(aa) >= sizeof(int).
This solution is also good for preparing int8_t to be printed to stream while some other solutions are not so good:
int8_t aa = -120;
cout << "value is " << aa + 0 << endl;
cout << "bad value is " << unsigned(aa) << endl;
Output:
value is -120
bad value is 4294967176
P.S. Solution with ADL given by pepper_chico and πάντα ῥεῖ is really beautiful.
I was experimenting with C++ and I decided to try the is_big_endian code, in much the same way I would do it in C. However I am getting no output when I try to print out the value of the pointer. I tried both the C and C++ style casts. What am I doing wrong?
#include <iostream>
using namespace std;
int main (void){
int num = 1;
char *ptr = (char *)#
//char *ptr = reinterpret_cast<char *>(&num);
cout << "Value is: " << *ptr << endl;
}
operator<< sees that you are outputting a char, so it prints it as a character, not as a number (it's as if in C you wrote %c instead of %d in a printf); and since *ptr will either be 0 or 1, you'll end up in both cases with a non-printable character.
To fix this, cast explicitly *ptr to int:
cout << "Value is: " << int(*ptr) << endl;
Sorry if this is hard to understand :P I'm trying to convert a decimal int value to a char value so I can write it in binary mode with fstream in c++. I did this: char hexChar = 0x01; file.write(hexChar, size);. That worked fine until I needed to write a decimal int from user. My question is, how do I convert decimal int to char hex value like this: int decInt = 10; char hexChar = 0x00; hexChar = decInt; file.write(hexChar, size); PS: I've been googling this for about an hour, and haven't found an answer. Every other solved problem with this has been decimal to ASCII hex value like "0A" using cout, not 0x0A using fstream.
It doesn't matter which kind of literal you are using to initialize an int variable
int x = 0x0A;
int y = 10;
The above statements assign the exactly same value to the variables.
To output numeric values with hexadecimal base representation you can use the std::hex I/O stream manipulator:
#include <iostream>
#include <iomanip>
int main() {
int x = 10; // equivalents to 0x0A
int y = 0x0A; // equivalents to 10
std::cout << std::setw(2) << std::setfill('0')
<< "x = " << std::hex << "0x" << x << std::endl;
std::cout << "y = " << std::dec << y << std::endl;
return 0;
}
Output:
x = 0xa
y = 10
See the live sample here.
I have this array : BYTE set[6] = { 0xA8,0x12,0x84,0x03,0x00,0x00, } and i need to insert this value : "" int Value = 1200; "" ....on last 4 bytes. Practically to convert from int to hex and then to write inside the array...
Is this possible ?
I already have BitConverter::GetBytes function, but that's not enough.
Thank you,
To answer original quesion: sure you can.
As soon as your sizeof(int) == 4 and sizeof(BYTE) == 1.
But I'm not sure what you mean by "converting int to hex". If you want a hex string representation, you'll be much better off just using one of standard methods of doing it.
For example, on last line I use std::hex to print numbers as hex.
Here is solution to what you've been asking for and a little more (live example: http://codepad.org/rsmzngUL):
#include <iostream>
using namespace std;
int main() {
const int value = 1200;
unsigned char set[] = { 0xA8,0x12,0x84,0x03,0x00,0x00 };
for (const unsigned char* c = set; c != set + sizeof(set); ++c) {
cout << static_cast<int>(*c) << endl;
}
cout << endl << "Putting value into array:" << endl;
*reinterpret_cast<int*>(&set[2]) = value;
for (const unsigned char* c = set; c != set + sizeof(set); ++c) {
cout << static_cast<int>(*c) << endl;
}
cout << endl << "Printing int's bytes one by one: " << endl;
for (int byteNumber = 0; byteNumber != sizeof(int); ++byteNumber) {
const unsigned char oneByte = reinterpret_cast<const unsigned char*>(&value)[byteNumber];
cout << static_cast<int>(oneByte) << endl;
}
cout << endl << "Printing value as hex: " << hex << value << std::endl;
}
UPD: From comments to your question:
1. If you need just getting separate digits out of the number in separate bytes, it's a different story.
2. Little vs Big endianness matters as well, I did not account for that in my answer.
did you mean this ?
#include <stdio.h>
#include <stdlib.h>
#define BYTE unsigned char
int main ( void )
{
BYTE set[6] = { 0xA8,0x12,0x84,0x03,0x00,0x00, } ;
sprintf ( &set[2] , "%d" , 1200 ) ;
printf ( "\n%c%c%c%c", set[2],set[3],set[4],set[5] ) ;
return 0 ;
}
output :
1200