-2

Recently, I created a small XOR checksum which allegedly worked (or at least in my head it did). I do not know what I have done wrong as I am following the exact same logic I used, when I have did it in C#/Java.

At the moment, it outputs rubbish values such as -87, -88 when the ints are sign and 2287800, 3485000 when unsigned. Is there a particular reason for that to happen?

Input data:

QByteArray str;

    str[0] =0xAA;
    str[1] =0xBB;
    str[2] =0xCC;
    str[3] =0xDD;
    str[4] =0xFF;
    str[5] =0x00;
    char ch = checkSum(str).data()[0];
    str[6] = ch; 
    serial.write(str, 7);

checkSum described bellow:

QByteArray MainWindow::checkSum(QByteArray &b)
{
    qint16 b_len = b.length();
    printf("b_length = %d\n", b_len);

    char val = 0x00;

    for (
       int i = 0 ; i < b_len ; i ++ ){
       val ^=  b[i];
       printf("Current: %d %d\n", val, b[i]);
    }

    return b;
}

Some output:

b_length = 6
Current: -88 1939120
Current: -81 1939120
Current: -80 1939120
Current: -69 1939120
Current: -70 1939120
Current: -70 1939120
Joe Carr
  • 445
  • 1
  • 10
  • 23
  • 2
    It seems that on your compiler `char` is *signed*, so any value above `127` will be printed as a negative value. Use `unsigned char` to specify that it should be unsigned. Or better yet use the standard `uint8_t` type to specify that it's an unsigned 8-bit integer. – Some programmer dude Dec 02 '16 at 09:42
  • I used it and it returned numbers like 224000 etc. This is mostly the reason I posted question here. – Joe Carr Dec 02 '16 at 09:44
  • These are the values which are printed : b_length = 6 Current: -88 1939120 Current: -81 1939120 Current: -80 1939120 Current: -69 1939120 Current: -70 1939120 Current: -70 1939120 – Joe Carr Dec 02 '16 at 10:45
  • Actually it would be better if I add them to the question. – Joe Carr Dec 02 '16 at 10:46
  • Can you provide the Input data you use to get this output data ? That'll allow us to test your code and analyze the results. When I set the input as "Jean", for example, the output is fine, so I'd like to know which values you use as input – Elcan Dec 02 '16 at 10:52
  • I am inputting an array with hexes. Just added it! – Joe Carr Dec 02 '16 at 10:55
  • Just tried it again and it does process the input values, but only if I do the XOR calculation by hand(ie hard code it inside the str[6] ). – Joe Carr Dec 02 '16 at 11:17
  • What happens if you make val a quint8 and cast b[i] to quint8? – Silicomancer Dec 02 '16 at 13:20

2 Answers2

1

There are plenty of errors in your code:

char ch = checkSum(str).data()[0];
                // checkSum doesn't actually return any checksum.

QByteArray checkSum(QByteArray &b)
   // You should be returning a char, not a QByteArray.
   // You also should be taking a const reference to QByteArray.
{
    qint16 b_len = b.length();        // You're truncating the length here.
    printf("b_length = %d\n", b_len); // Perhaps you should use qDebug() instead, but it's OK as quint16 is passed to printf as an int.

    char val = 0x00;                  // OK

    for (int i = 0 ; i < b_len ; i ++ ) {
       val ^=  b[i];                  // OK
       printf("Current: %d %d\n", val, b[i]);
                                      // You're passing a `QCharRef` where an int is expected.
                                      // That's the pitfall of using non-typesafe
                                      // printf. It'd have worked with qDebug()!
    }                  

    return b;                         // You're returning the wrong thing.
}

Here's how I'd write it:

#include <initializer_list>

char checkSum(const QByteArray &data)
{
   char sum = 0x00;
   for (char c : data) {
      sum ^= c;
      qDebug() << "Current:" << (int)sum << (int)c;
   }
   return sum;
}

// This hopefully won't be necessary in a future Qt version.
QByteArray makeByteArray(std::initializer_list<uint8_t> in) {
   return QByteArray(reinterpret_cast<const char*>(in.begin()), in.size());
}

int main() {
   auto str = makeByteArray({0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0x00});
   str.append(checkSum(str));
   qDebug() << str.toHex();
}

Since checkSum has nothing to do with the MainWindow, it should be a free function, not a method - not even a static method.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
0

I solved it sometime ago by using for each and changing the output to be a char.

char MainWindow::checkSum(QByteArray &b)
{
    qint16 b_len = b.length();
    printf("b_length = %d\n", b_len);

    char val = 0x00;
    char i;
    foreach (i, b)
    {
       val ^= i;
      // printf("Current: %x %x\n", val, b);
    }

    return val;
}
Joe Carr
  • 445
  • 1
  • 10
  • 23