C++ How to display Unicode wstring as Number in Unicode format - c++

I have a std::wstring like that:
std::wstring mystr = L"abc\U0000FFFF\U0000000A\U00000061\U00000010de";
I want to print it out to the console where it should look like that:
abc\U0000FFFF\U0000000A\U00000061\U00000010de
When I try this :
for (int i = 0; i < 9; i++)
{
char16_t* ctest = &c[i];
std::cout << *ctest<< " ";
}
the result is
61 62 63 ffff a 61 10 64 65
How can I get the my desired output?

Just inspect each character as you output it. If it's in the printable ASCII range, output it as a char; otherwise output it as a hex sequence.
std::wstring mystr = L"abc\U0000FFFF\U0000000A\U00000061\U00000010de";
for (int i = 0; i < mystr.size(); ++i)
{
if (mystr[i] >= 0x20 && mystr[i] < 0xff)
cout << (char)mystr[i];
else
cout << "\\U" << std::setfill('0') << std::right << std::setw(8) << std::hex << mystr[i];
}
https://ideone.com/ucepKy
The output differs from your desired output because you have the character "a" in there twice, once as a single character and once as a hex escape sequence. Once the string is compiled, there's no way to tell the difference between the two.

Related

How to convert int to binary and concatenate as char in C++

I have two values, 0 and 30, I need to store it's binary representation on one byte for each. Like:
byte 0 = 00000000
byte 1 = 00011110
and then concatenate them on a string that will print the ASCII for 0 (NULL) and for 30 (Record Separator). So, not print "030", but something I can't really right here and neither the command can print properly. I know those are not nice things to print.
I was doing like this:
string final_message = static_cast<unsigned char>(bitset<8>(0).to_ulong());
final_message += static_cast<unsigned char>((bitset<8>(answer.size())).to_ulong()); // where answer.size() = 30
cout << final_message << endl;
Not sure if it's right, I never worked with bitset since now. I think it's right but the server that receives my messages keep telling me that the numbers are wrong. I'm pretty sure that the numbers I need are 0 and 30 on that order, so, as the only part I'm not sure how it works are those three lines, I'm putting this question here.
Those three lines are right? There's a better way to do that?
A byte (or a char) holds a single 8-bit value, and the value is the same whether you "view" it in a binary format, in a decimal format, or as a character to be printed on the console. It's just the way you look at it.
See the following example. The first two examples byte1 and byte2 are those referred in your question. Unfortunately, you won't see much on the console.
Therefore I added another example, which illustrates three ways of viewing the same value 65 in different ways. Hope it helps.
int main(){
char byte1 = 0b00000000;
char byte2 = 0b00011110;
std::cout << "byte1 as 'int value': " << (int)byte1 << "; and as character: " << byte1 << endl;
std::cout << "byte2 as 'int value': " << (int)byte2 << "; and as character: " << byte2 << endl;
char a1 = 65;
char a2 = 'A';
char a3 = 0b001000001;
std::cout << "a1 as 'int value': " << (int)a1 << "; and as character: " << a1 << endl;
std::cout << "a2 as 'int value': " << (int)a2 << "; and as character: " << a2 << endl;
std::cout << "a3 as 'int value': " << (int)a3 << "; and as character: " << a3 << endl;
return 0;
}
Output:
byte1 as 'int value': 0; and as character:
byte2 as 'int value': 30; and as character:
a1 as 'int value': 65; and as character: A
a2 as 'int value': 65; and as character: A
a3 as 'int value': 65; and as character: A
The line
string final_message = static_cast<unsigned char>(bitset<8>(0).to_ulong());
does not compile. And obviously, there is no need for bitset here as you are essentially juts add extra conversions in the path.
If I split the line above in 2 and use +=, the resulting string as a size of 2 and contain characters with values of 0 and 30 (I have inspected in using the debugger).
So I don't know what is your problem as it appears to do what you want...

stringstream >> uint8_t in hex? c++

i am confused by the output of the following code:
uint8_t x = 0, y = 0x4a;
std::stringstream ss;
std::string a = "4a";
ss << std::hex << a;
ss >> x;
std::cout << (int)x << " "<< (int)y << std::endl;
std::cout << x << " "<< y <<std::endl;
std::cout << std::hex << (int)x << " " << (int)y << std::endl;
uint8_t z(x);
std::cout << z;
the output for the above is:
52 74
4 J
34 4a
4
and when we change replace the first line with:
uint16_t x = 0, y = 0x4a;
the output turns into:
74 74
74 74
4a 4a
J
I think i understand what happens but i don't understand why it happens or how i can prevent it/work around it. From my understanding std::hex modifier is somehow undermined because of the type of x, maybe not exactly true at a technical level but it simply just writes the first character it reads.
Background: The input is supposed to be a string of hexadecimal digits, each pair representing a byte( just like a bitmap except in string). I want to be able to read each byte and store it in a uint8_t so i was experimenting with that when i came across this problem. I still can't determine what's the best method of this so if you think what i'm doing is inefficient or unnecessary i would appreciate to know why. Thank you for reading,
ss >> x
is treating uint8_t x as an unsigned char. The ascii value of '4' is (decimal) 52. It's reading the first char of the string "4a" into x as if x were a character. When you switch it to uint16_t, it's treating it as an unsigned short integer type. Same with y.

Printing out the hex vale of an unsigned char array in C++

I want to print out the hex value of an unsigned char array using the cout function.
The most obvious approach would be something like the following.
unsigned char str[] = "foo bar baz\n";
for(unsigned short int i = 0; i < sizeof(str); i++){
std::cout << std::hex << str[i] << std::dec << ' ';
}
std::cout << std::endl;
Suprisingly, this outputs the following string:
foo bar baz
For some reason this does not print out the proper hexadecimal value of str
How can I cout the proper hex value of str?
To cout the proper hex value of an unsigned char, it will need to be converted to an integer first.
unsigned char str[] = "foo bar baz\n";
for(unsigned short int i = 0; i < sizeof(str); i++){
std::cout << std::hex << (int) str[i] << std::dec << ' ';
}
std::cout << std::endl;
Gives the following output.
66 6f 6f 20 62 61 72 20 62 61 7a 00
Which corresponds with the hex value of each unsigned char in str.
An explaination for this can be found in the following std::hex documentation.
std::hex
Sets the basefield format flag for the str stream to hex.
When basefield is set to hex, integer values inserted into the stream are expressed in hexadecimal base (i.e., radix 16). For input streams, extracted values are also expected to be expressed in hexadecimal base when this flag is set.
http://www.cplusplus.com/reference/ios/hex/

Function behave differently with similar input (C++)

I am trying to work with the modbus protocol and right now i am calculating the LRC of the messages. I made a function which worked with no issue whatever i was putting into and then i noticed that id did not worked with one input and i can't find a logical explanation on why this don't work.
The function is :
void LRCstring(std::string example)
{
std::stringstream ss;
std::string hex =example.substr(1, example.length()-5);
std::vector<unsigned char> hexCh;
unsigned int buffer;
int offset = 0;
while (offset < hex.length()) {
ss.clear();
ss << std::hex << hex.substr(offset, 2);
ss >> buffer;
hexCh.push_back(static_cast<unsigned char>(buffer));
offset += 2;
}
unsigned char LRC=0x00;
int i;
for (i=0;i<hexCh.size();i++)
{
LRC=LRC+hexCh[i];
}
LRC = 0xFF-LRC; // 1 complement
LRC = LRC+1; // 2 complement
//std::string s = std::to_string(LRC);
//int deci = atoi(s.c_str());
int deci = LRC;
int reste=deci % 16;
std::string temp;
int partiehexa=(deci-reste)/16;
std::string temp2;
std::cout << "deci : " << deci << std::endl;
std::cout << "reste : " << reste << std::endl;
std::cout << "partiehexa : " << partiehexa << std::endl;
std::stringstream ss2;
ss2 << reste;
ss2 >> temp;
ss2 << partiehexa;
ss2 >> temp2;
if (partiehexa<10) {LRCascii+=temp2;}
if (partiehexa==10) {LRCascii+='A';}
if (partiehexa==11) {LRCascii+='B';}
if (partiehexa==12) {LRCascii+='C';}
if (partiehexa==13) {LRCascii+='D';}
if (partiehexa==14) {LRCascii+='E';}
if (partiehexa==15) {LRCascii+='F';}
if (reste<10) {LRCascii+=temp;}
if (reste==10) {LRCascii+='A';}
if (reste==11) {LRCascii+='B';}
if (reste==12) {LRCascii+='C';}
if (reste==13) {LRCascii+='D';}
if (reste==14) {LRCascii+='E';}
if (reste==15) {LRCascii+='F';}
std::cout << "LRC : " << LRCascii << std::endl;
return;
}
Examples on what is the input and the result when it is working :
input > ":040100130013??\r\n"
The cout display "LRC : D5"
input > ":0401CD6B05??\r\n"
The cout display "LRC : BE"
D5 and BE are the right results.
I tried with other inputs and had no problem until this :
input > ":0403006B0003??\r\n"
The cout display "LRC : B"
input > ":040306022B00000064??\r\n"
The cout display "LRC : 2"
It should be 8B and not simply B and it should be 62 and not simply 2.
We can see that the last part of the LRC is good but the other part is ignored. What is even stranger is that in this case the cout of "partiehexa" is showing "8" and "6", it is not like this int was empty. I fail to understand why this is happening in this case.
To me it seems to a C code. But I did quickly analyze your code. I Think the problem lies where your are calculating the
(partiehexa < 10)
The LRCascii only gets assigned while looping through the "reste" part of the code. In the "partiehexa" part of the code it do not get assigned to anything.
Suggestion: Change the code to the following and your code will work
if (partiehexa<10)
{
std::stringstream ss3;
ss3 << partiehexa;
ss3 >> temp2;
LRCascii += temp2;
}
Best solution would be to rewrite the code in proper optimized way.
To calculate the LRC
Add up all the data bytes in the message (before converting to ASCII and without the initial colon and final CR/LF).
Throw away any bits that carry over 8 bits.
Make the result negative (by twos compliment) to get the LRC byte.
In your example, checksum can be calculated mathematically as below:
String: 040306022B00000064
Checksum: 62
Byte# 1 Hex Value 04 Decimal Value 4
Byte# 2 Hex Value 03 Decimal Value 3
Byte# 3 Hex Value 06 Decimal Value 6
Byte# 4 Hex Value 02 Decimal Value 2
Byte# 5 Hex Value 2B Decimal Value 43
Byte# 6 Hex Value 00 Decimal Value 0
Byte# 7 Hex Value 00 Decimal Value 0
Byte# 8 Hex Value 00 Decimal Value 0
Byte# 9 Hex Value 64 Decimal Value 100
Total Hex Value 9E Decimal Value 158
LRC: Hex Value FFFFFFFF62 Decimal Value -158
So the single Hex LRC Byte in this example is 62.
Prashant..

character to binary conversion in C++ two characters at a time to get 16 bit binary form

Hello i want to convert two characters at a time in a string to binary? how can i do that by applying simple arithmetic (that is by making my own function?)
For example: our string is = hello world:
Desired output (two characters at a time):
he // need binaryform of 0's and 1's (16 bits for 2 characters 'h' and 'e'
ll // similarly
o(space) // single space also counts as a character with 8 zero bit in binary.
wo
rl
d(space) // space equals a character again with 8 zero bits
how to go about with it. i dont want any ascii in between. directly from character to binary...is that possible?
If you're looking for a way to textually represent the binary representation of characters, then here's a small example of how you can do it:
A small function that prints out the binary representation of c to std::cout (will only work for standard ASCII letters):
void printBinary(char c) {
for (int i = 7; i >= 0; --i) {
std::cout << ((c & (1 << i))? '1' : '0');
}
}
Use it like this (will only print out pairs of characters):
std::string s = "hello "; // Some string.
for (int i = 0; i < s.size(); i += 2) {
printBinary(s[i]);
std::cout << " - ";
printBinary(s[i + 1]);
std::cout << " - ";
}
Outputs:
01101000 - 01100101 - 01101100 - 01101100 - 01101111 - 00100000 -
Edit:
Actually, using std::bitset this is all that is needed:
std::string s = "hello "; // Some string.
for (int i = 0; i < s.size(); i += 2) {
std::cout << std::bitset<8>(s[i]) << " ";
std::cout << std::bitset<8>(s[i + 1]) << " ";
}
Outputs:
01101000 01100101 01101100 01101100 01101111 00100000
If you want to store the binary numbers of the character pairs in a std::vector, as mentioned in a comment, then this will do it:
std::vector<std::string> bitvec;
std::string bits;
for (int i = 0; i < s.size(); i += 2) {
bits = std::bitset<8>(s[i]).to_string() + std::bitset<8>(s[i + 1]).to_string();
bitvec.push_back(bits);
}
This can be accomplished quickly and easily using the bitset class in the C++ STL.
Below is a function that you can use:
#include <string>
#include <bitset>
string two_char_to_binary(string s) // s is a string of 2 characters of the input string
{
bitset<8> a (s[0]); // bitset constructors only take integers or string that consists of 1s and 0s e.g. "00110011"
bitset<8> b (s[1]); // The number 8 represents the bit depth
bitset<16> ans (a.to_string() + b.to_string()); // We take advantage of the bitset constructor that takes a string of 1s and 0s and the concatenation operator of the C++ string class
return ans.to_string();
}
Sample Usage:
using namespace std;
int main(int argc, char** argv)
{
string s = "hello world";
if(s.length() % 2 != 0) // Ensure string is even in length
s += " ";
for(int i=0; i<s.length(); i += 2)
{
cout << two_char_to_binary(s.substr(i, 2)) << endl;
}
return 0;
}
I guess the thing you're looking for is casting. Try like this:
char *string = "hello world ";
short *tab = (short*)string;
for(int i = 0; i < 6; i++)
std::cout << tab[i] << std::endl;