scanning a string to hex char array

2019-03-07 06:10发布

问题:

Here is my sample code :

char a;
char str [20];
unsigned char b[8] ;
unsigned char c[8];

int argsread;
int i;

init_8051();

while(1)
{
    printf("\n enter a 64 bit operation \n");

    argsread = scanf("%s", str);

    sscanf(str, "0x%x%c0x%x", b, &a, c);

    printf("\n %d arguments read \n",argsread);

        for(i=0;i<8;i++)
{
             printf("\n %#x %c %#x\n",b[i],a,c[i]);
}
        }

}

The problem here is that when i enter for example in the terminal the following input : 0x1234567890abcdef+0x1234567890abcdef

this leads to an error where output for char array is totally wrong and most of the numbers are traced into a , which should have been the plus sign , am ai doing something fundamentally wrong ?

Update: I changed my code to the following :

while(1)
{
printf("\n enter a 64 bit operation \n");
argsread = scanf("%s", str);
sscanf(str, "0x%s%c0x%s", b, &a, c);
printf("\n %d arguments read \n",argsread);

printf("\n %s \n",b);
}

and i increased size of str to 30 the problem is the output of the program is :

 1 arguments read 

 abcdef+0xabcdef 

so the value of b instead of being just abcdef it the the whole string!!

Update2: Found this code which works perfect but i wanted to use scanf instead of cin here is the code

:`#include <iostream> 

using namespace std;

int main()
{

  float a, b, result;
    char oper, clear;
    cout << "Please enter an equation: i.e 5+5 " << endl;
    for (;;) {
          cin >> a;
          cin >> oper;
          cin >> b;
         if (oper == '+')
        result = a + b;
         else if (oper == '-')
            result = a - b;
       else if (oper == '*')
              result = a * b;
     else if (oper == '/')
              result = a / b;   
    cout << "= " << result << endl << endl;
    cin.clear();
    cin.ignore();
   } 
} `

回答1:

User input and error handling much easier if code starts with fgets().
Then use sscanf(), strtol(), etc. to parse.

printf("\n enter a 64 bit operation \n");
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_IOErrororEOF();

char a;
char b[17];  // use right size arrays
char c[17];
// use width of 16 and %[]
if (sscanf(buf, " 0x%16[0-9abcdef] %c 0x%16[0-9abcdef]", b, &a, c) != 3) {
  Handle_Bad_Input();
}

OTOH, just use an integer format specifier that allows hex input "%x" or "%i"

unsigned long long b,c;
if (sscanf(buf, "%lli %c%lli", &b, &a, &c) != 3) {
  Handle_Bad_Input();
}

Why char str [20]; scanf("%s", str); has trouble:

"%s" does 3 things:
1) scans, but does not save, all preceding (0 or more) white-space (' ', '\t', '\n ', etc.).
2) scans and saves all non-white-space.
3) Finally reaching a white-space. it stops scanning and puts that white-space back into stdin.

The "%s" specifier lacks a width, like "%19s", so it can easily overfill str

sscanf(str, "0x%s%c0x%s", b, &a, c); has trouble too.

Input has no white-space between the end of the first number and the '+', so "%s" continues scanning. Code does not check the return value from sscanf() and then uses a, b, c. So a, b, c may not be properly scanned nor initialized - leading to potential undefined behavior .



回答2:

You are reading a string using scanf and storing it in an integer. I think that is what is causing you the problem.

Also, from the MAN Page

AME
       scanf,  fscanf, sscanf, vscanf, vsscanf, vfscanf 

       ...

RETURN VALUE

   These functions return the number of input items  successfully  matched
   and assigned, which can be fewer than provided for, or even zero in the
   event of an early matching failure.

   The value EOF is returned if the end of input is reached before  either
   the  first  successful conversion or a matching failure occurs.  EOF is
   also returned if a read error occurs, in which case the error indicator
   for  the  stream  (see ferror(3)) is set, and errno is set indicate the
   error.


回答3:

I think you missplaced the assignment, if you want to know how many arguments matched, then change this

argsread = scanf("%s", str);

sscanf(str, "0x%x%c0x%x", b, &a, c);

to this

scanf("%s", str);

argsread = sscanf(str, "%x%c%x", b, &a, c);

According to your comments, you should change some other things, may be this code will work

char a;
char str [64];
unsigned int b;
unsigned int c;
char B[11];
char C[11];
int argsread;

while(1)
{
    printf("\n enter a 64 bit operation \n");

    scanf("%s", str);

    argsread = sscanf(str, "0x%x%c0x%x", &b, &a, &c);
    if (argsread == 3) 
    {
        printf("\n %d arguments read\n", argsread);

        snprintf(B, sizeof(B), "0x%08X", b);
        snprintf(C, sizeof(B), "0x%08X", c);

        printf("\n %s%c%s\n", B, a, C);
    }
}
return 0;