1

Need some help with beginner C++ code:

#include "stdafx.h"
#include <iostream>
#include <stdio.h>

LONG __cdecl main(LONG     Argc, char* Argv[])
{

    if (Argc == 8 && stricmp(Argv[1], "sendir") == 0){

        int nDeviceID;
        unsigned short nUsage, nUsagePage;
        BYTE nIRBlink, nMsgCode, nHidReportID;

        sscanf_s(Argv[2], "%d", &nDeviceID);
        sscanf_s(Argv[3], "%4hhx", &nUsage);
        sscanf_s(Argv[4], "%4hhx", &nUsagePage);
        sscanf_s(Argv[5], "%2hhx", &nHidReportID);
        sscanf_s(Argv[6], "%2hhx", &nIRBlink);
        sscanf_s(Argv[7], "%2hhx", &nMsgCode);

        printf("param: %d, %d, %d, %d, %d, %d\n", nDeviceID, nUsage, nUsagePage, nHidReportID, nIRBlink, nMsgCode);

    }
    return 0;
}

So I type in cmd prompt: test.exe sendir 2 0001 ff00 06 01 01

I got: param: 2, 1, 65280, 0, 0, 1

Ideally I would want: param: 2, 1, 65280, 6, 1, 1

I think the problem is how I am using sscanf...

this
  • 5,229
  • 1
  • 22
  • 51
dching
  • 17
  • 1
  • 2
    What is the reason of not using c++ standard library? – VP. Jul 13 '15 at 16:13
  • 1
    https://msdn.microsoft.com/de-de/library/t6z7bya3.aspx doesn't help? I don't know WinAPI myself, only the standard library – WorldSEnder Jul 13 '15 at 16:16
  • 2
    It's very likely that the used `sscanf_s()` implementation doesn't support the `hh` length modifier. – cremno Jul 13 '15 at 16:19
  • sscanf() doesn't work either and if I use %x instead of %hhx, the result is the same. – dching Jul 13 '15 at 16:22
  • 1
    You're including `` anyway and aren't even leveraging the formatting capabilities of `scanf`, so why not just use `std::cin` and `std::cout`? – celticminstrel Jul 13 '15 at 16:47
  • Did you change the types of the variables to `unsigned int`? Also, use `strtol()` to convert strings to integers. [Using `scanf()` is bad.](https://www.securecoding.cert.org/confluence/display/c/INT05-C.+Do+not+use+input+functions+to+convert+character+data+if+they+cannot+handle+all+possible+inputs) – cremno Jul 13 '15 at 16:49
  • If I do use %d for the last 3 sscanf_s, then the result is a bit better param: 2, 1, 65280, 6, 0, 1 – dching Jul 13 '15 at 16:59
  • I'll try the strtol and post my results here – dching Jul 13 '15 at 17:02

2 Answers2

0

Code failure was using the wrong scanf specifier.

    int nDeviceID;
    unsigned short nUsage, nUsagePage;
    BYTE nIRBlink, nMsgCode, nHidReportID;

    sscanf_s(Argv[2], "%d", &nDeviceID);

    // Wrong, Use hx with unsigned short than hhx
    sscanf_s(Argv[3], "%4hx", &nUsage);
    sscanf_s(Argv[4], "%4hx", &nUsagePage);

    // Likely OK if BYTE is the same as unsigned char
    sscanf_s(Argv[5], "%2hhx", &nHidReportID);
    sscanf_s(Argv[6], "%2hhx", &nIRBlink);
    sscanf_s(Argv[7], "%2hhx", &nMsgCode);

In all cases the result of sscanf_s() was not checked, casting doubt on the success of the conversions.

Alternative: using own conversion functions Ref

    errno = 0;
    char *endptr; 
    nDeviceID = strtoi(Argv[2], &endptr, 10);
    if (errno || *endptr) Fail();
    nUsage = strtosuchar(Argv[3], &endptr, 16);
    if (errno || *endptr) Fail();
    ...
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
-1

Figured it out.

    sscanf_s(Argv[2], "%d", &nDeviceID);
    sscanf_s(Argv[3], "%4hhx", &nUsage);
    sscanf_s(Argv[4], "%4hhx", &nUsagePage);
    //sscanf_s(Argv[5], "%2hhx", &nHidReportID);
    nHidReportID = (byte)strtoul(Argv[5], NULL, 16);
    //sscanf_s(Argv[6], "%2hhx", &nIRBlink);
    nIRBlink = (byte)strtoul(Argv[6], NULL, 16);
    //sscanf_s(Argv[7], "%2hhx", &nMsgCode);
    nMsgCode = (byte)strtoul(Argv[7], NULL, 16);

All in all , don't use the sscanf.

dching
  • 17
  • 1