簡體   English   中英

為什么sscanf會忽略指定的寬度?

[英]Why does sscanf ignore the specified width?

我正在使用此代碼將固定大小為32的十六進制字符串轉換為16字節的uint8數組。

const uint8_t* c = "0123456789abcdef0123456789abcdef";
uint8_t Bytes[16];
for (int i = 0; i < 16; i++) {
    sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
}

盡管hh指定了1字節的目標寬度,但每步寫入4個字節。 因此,代碼在緩沖區末尾寫入3個字節。 這是為什么?

(現在,我使用臨時int修復它,並在每一步中復制到數組。)

重現:

#include <stdint.h>
#include <string>

void main (int argc, char* argv[])
{
    const char* c = "0123456789abcdef0123456789abcdef";
    uint8_t b[20];
    for (int i = 0; i < 20; i++) {
        b[i] = i;
    }
    for (int i = 0; i < 16; i++) {
        sscanf (&c[2*i], "%2hhx", &(b[i]));
    }
    for (int i = 0; i < 20; i++) {
        fprintf(stdout,  "%02x\n", (int)(b[i]));
    }
}

預期輸出為01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef 10 11 12 13

但是,使用Visual Studio 2010的實際輸出是:

01 23 ... cd ef 00 00 00 13

您的代碼在開始時存在一個小問題。

const uint8_t* c = "0123456789abcdef0123456789abcdef";

在C ++中,未指定char是有signed還是unsigned 更確切地說, charsigned charunsigned char是不同的,事實上,在重載函數和專門化模板時,必須考慮到這一點。

現在的代碼是:

const char* c = "0123456789abcdef0123456789abcdef";
uint8_t Bytes[16];
for (int i = 0; i < 16; i++) {
    sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
}

讓我們分析你的格式字符串:

2  : maximum field witdh to be read
hh : expecting a pointer to signed or unsigned char
x  : means unsigned hex-input

(http://linux.die.net/man/3/scanf)

有了這些信息,到目前為止看起來是正確的。

據我所知, C99符合庫 *沒有問題。


* :在這方面,MSVC庫不支持hh說明符。

我在Mac OS X上使用gcc 4.2.1構建並運行以下代碼:

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    const char *c = "0123456789abcdef0123456789abcdef";
    uint8_t b[20] = { 0 };
    int i;

    for (i = 0; i < 20; i++) {
        b[i] = i;
    }

    for (i = 0; i < 16; i++) {
        sscanf (&c[2*i], "%2hhx", &b[i]);
    }

    for (i = 0; i < 20; i++) {
        printf("%02x", b[i]);
    }
    printf("\n");

    return 0;
}

它看起來像預期的那樣:

$ gcc -v
...
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
$ gcc -Wall scanf_hex.c
$ ./a.out 
0123456789abcdef0123456789abcdef10111213
$ 

請嘗試使用編譯器等構建並運行上面的代碼,以便我們可以看到它是否是可能的編譯器/庫錯誤,或者是否是代碼中的其他問題。 (您可能希望嘗試調試和發布版本。)

對我來說非常適合:

#include <stdio.h>
#include <stdint.h>
int main()
{
    const char* c = "0123456789abcdef0123456789abcdef";
    unsigned char Bytes[16];
    int i;
    for (i = 0; i < 16; i++)
    {   
            sscanf (&c[2*i], "%2hhx", &(Bytes[i]));
    }   
    for (i=0; i < 16; ++i)
    {   
        fprintf(stdout,  "%02x\n", (int)(Bytes[i]));
    }   
}

期運用:

> gcc gh.c 
> ./a.out
01
23
45
67
89
ab
cd
ef
01
23
45
67
89
ab
cd
ef

使用iostream的c ++解決方案可能如下:

  #include<iostream>
  #include<sstream>
  #include<iomanip>      
  using namespace std;

  //...

  const char* c = "0123456789abcdef0123456789abcdef";
  unsigned char Bytes[16];
  stringstream s_in(c);
  for (int i = 0; i < 16; i++) 
  {
      string s;
      s_in >> setw(2) >> s;
      unsigned int t;
      stringstream(s) >> hex >> t;
      Bytes[i] = t;
  }

請注意,如果變量類型不是字符串,則s_in不希望服從setw(2)。 另外,寬度為1 通過各種手段如果變量是char類型的,因此從int轉換。

測試它:

  for (int i = 0; i < 16; i++) 
  {
    cout << setfill('0') << setw(2) << hex << (int) Bytes[i] << " ";
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM