Im getting a slight math error in my program, which is causing problems in the rest of it, and i dont get why it is happening. in this part of the class, i did not overload the operators for built in types (i hope). if i did, please show me where
this function is meant to calculate the least number of bits needed to store a the number, which is stored in a deque <uint8_t> value as one value, so 0x123456 will be stored as {0x12, 0x34, 0x56}, and the output to integer.bits() should be 21
// all types here are standard, so i dont know whats going on
unsigned int bits(){
unsigned int out = value.size() << 3;
std::cout << out << " " << value.size() << " " << (value.size() << 3) << std::endl;
uint8_t top = 128;
while (!(value.front() & top)){
out--;
top >>= 1;
}
return out;
}
yet, this part is couting
8 1 8
16 2 16
...
and finally,
18 3 18
http://ideone.com/zLfz2
3*8 is 24, and in hex that's 0x18. You have std::hex scattered about your code...
Someone has changed your stream to hex and it's printing 24 decimal as 18 hex.
Related
I'm currently writing some tests for an MD5 hash generating function. The functions returns an unsigned char*. I have a reference sample to compare to hard coded into the test. From my research it appears that memcmp is the correct way to go, however I am having issues with the results.
When printed to the terminal they match, however memcmp is returning a negative match.
CODE sample:
unsigned char ref_digest[] = "d41d8cd98f00b204e9800998ecf8427e";
unsigned char *calculated_digest = md5_gen_ctx.get_digest();
std::cout << std::setfill('0') << std::setw(2) << std::hex << ref_digest << endl;
for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
std::cout << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(calculated_digest[i]);
}
cout << endl;
int compare = std::memcmp(calculated_digest, ref_digest , MD5_DIGEST_LENGTH);
cout << "Comparison result: " << compare << endl;
OUTPUT
2: Test timeout computed to be: 10000000
2: d41d8cd98f00b204e9800998ecf8427e
2: d41d8cd98f00b204e9800998ecf8427e
2: Comparison result: 70
Can anyone guide me as to what I am doing incorrectly here? I am wondering if there are issues with the definition of my reference hash. Is there a better way of managing this comparison for the test?
Cheers.
This is wrong:
unsigned char ref_digest[] = "d41d8cd98f00b204e9800998ecf8427e";
That is a string of 32 characters, when what you want is an array of 16 bytes. Note that two hexadecimal characters (4+4 bits) corresponds to one byte.
To fix it, you can use a pair of 64-bit integers:
uint64_t ref_digest[] = {htobe64(0xd41d8cd98f00b204), htobe64(0xe9800998ecf8427e)};
I used htobe64() to put the bytes in the correct order, e.g. 0xd4 needs to be the first byte.
I'm coding in C++ on Linux (Ubuntu) and trying to print a string that contains some Latin characters.
Trying to debug, I have something like the following:
std::wstring foo = L"ÆØÅ";
std::wcout << foo;
for(int i = 0; i < foo.length(); ++i) {
std::wcout << std::hex << (int)foo[i] << " ";
std::wcout << (char)foo[i];
}
Characteristics of output I get:
The first print shows: ???
The loop prints the hex for the three characters as c6 d8 c5
When foo[i] is cast to char (or wchar_t), nothing is printed
Environmental variable $LANG is set to default en_US.UTF-8
In the conclusion of the answer I linked (which I still recommend reading) we can find:
When I should use std::wstring over std::string?
On Linux? Almost never, unless you use a toolkit/framework.
Short explanation why:
First of all, Linux is natively encoded in UTF-8 and is consequent in it (in contrast to e.g. Windows where files has one encoding and cmd.exe another).
Now let's have a look at such simple program:
#include <iostream>
int main()
{
std::string foo = "ψA"; // character 'A' is just control sample
std::wstring bar = L"ψA"; // --
for (int i = 0; i < foo.length(); ++i) {
std::cout << static_cast<int>(foo[i]) << " ";
}
std::cout << std::endl;
for (int i = 0; i < bar.length(); ++i) {
std::wcout << static_cast<int>(bar[i]) << " ";
}
std::cout << std::endl;
return 0;
}
The output is:
-49 -120 65
968 65
What does it tell us? 65 is ASCII code of character 'A', it means that that -49 -120 and 968 corresponds to 'ψ'.
In case of char character 'ψ' takes actually two chars. In case of wchar_t it's just one wchar_t.
Let's also check sizes of those types:
std::cout << "sizeof(char) : " << sizeof(char) << std::endl;
std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl;
Output:
sizeof(char) : 1
sizeof(wchar_t) : 4
1 byte on my machine has standard 8 bits. char has 1 byte (8 bits), while wchar_t has 4 bytes (32 bits).
UTF-8 operates on, nomen omen, code units having 8 bits. There is is a fixed-length UTF-32 encoding used to encode Unicode code points that uses exactly 32 bits (4 bytes) per code point, but it's UTF-8 which Linux uses.
Ergo, terminal expects to get those two negatively signed values to print character 'ψ', not one value which is way above ASCII table (codes are defined up to number 127 - half of char possible values).
That's why std::cout << char(-49) << char(-120); will also print ψ.
But it shows the const char[] as printing correctly. But when I typecast to (char), nothing is printed.
The character was already encoded different, there are different values in there, simple casting won't be enough to convert them.
And as I've shown, size char is 1 byte and of wchar_t is 4 bytes. You can safely cast upward, not downward.
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.
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..
In C++, an octal number is defined by preceeding it with a 0, example:
01 = 1
010 = 8
014 = 12
So I was experimenting how working with Base 8 in c++ works, and tried adding to it with a loop, like so:
int base8Number = 00;
for (int i = 01; i < 011; i+=01)
{
base8Number += i;
cout << base8Number << '\n';
}
And apparently, C++ doesn't like working with octal numbers, the output I got is as follows:
1
3
6
10
15
21
28
36
The most obvious reason I know it's not working in Base 8, is the 28 output as a result, since the 8 number isn't used in Base 8.
So, my question: Can you work with Base 8 in c++, or is it just meant to be used as a constant, and if you can work with Base 8 in c++, how do you do it?
So first, let's remember that when we print numbers the way you're doing, they will be shown in decimal.
Now, let's rewrite your code without octal:
int base10Number = 0;
for (int i = 1; i < 9; i+=1)
{
base10Number += i;
cout << base10Number << '\n';
}
So let's now look at what your code is actually doing:
cout << 1 << "\n"; // 1
cout << 1 + 2 << "\n"; // 3
cout << 1 + 2 + 3 << "\n"; // 6
cout << 1 + 2 + 3 + 4 << "\n"; // 10
....
Which is what you're seeing. So no, there is no problem with how octal works in c++.
If you'd like you can use std::oct to tell std::cout to use octal printing. For example:
int main() {
std::cout << std::oct << 25 << "\n"; // Outputs: 31
}
Remember that "base" is a property of number representation, not the number itself. If you've got enough pegs to put one on each finger, then that is the same number of pegs regardless of whether you write 10, 012 0xA, or anything else.
Your code computes the numbers which would be shown in base 10 as 1, 3, 6, 10, 15, etc. You output them in base 10. To output them in base 8 use:
std::cout << std::oct << base8Number << std::endl;
There are a couple of things going on here.
Intrinsically, your computer operates in binary (base 2). When you do something like int foo = 10;, you are expressing the number 10 in decimal form because it's convenient for you to read it that way, but in the end the computer will still store it using binary, e.g. 1010.
If you were to use an octal literal (e.g. 012), then as far as the computer's concerned that's still just a 1010 binary constant - the only thing that's changed is its representation in the source code.
Finally, the last thing to realise is that the computer will by default output integers in base 10, because that's what's easy for people to read. It's still outputting the number 1010, just using the decimal representation of it.
Given all of the above, your code is entirely equivalent to doing the following, which you can verify for yourself produces the same output without using any octal:
int num = 0;
for (int i = 1; i < 9; i += 1) // Constants the same, just changed from octal representation to decimal.
{
num += i;
cout << num << '\n'; // Outputs in decimal, as with original program.
}
To get what you expect, try using the oct modifier:
int base8Number = 00;
for (int i = 01; i < 011; i+=01)
{
base8Number += i;
cout << oct << base8Number << '\n';
// ^--Here. Explicitly requests octal output.
}
This then explicitly requests that the computer output the values using octal.