【问题标题】:scanning a string to hex char array将字符串扫描到十六进制字符数组
【发布时间】:2014-12-19 12:25:55
【问题描述】:

这是我的示例代码:

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]);
}
        }

}

这里的问题是,例如,当我在终端中输入以下输入时: 0x1234567890abcdef+0x1234567890abcdef

这会导致一个错误,其中 char 数组的输出完全错误,并且大多数数字都被追踪到 a 中,这应该是加号,我做的事情根本上是错误的吗?

更新: 我将代码更改为以下内容:

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);
}

我将 str 的大小增加到 30 问题是程序的输出是:

 1 arguments read 

 abcdef+0xabcdef 

所以 b 的值而不是 abcdef 它是整个字符串!!

更新 2: 发现这个代码完美,但我想使用 scanf 而不是 cin 这里是代码

:`#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();
   } 
} `

【问题讨论】:

  • 你的代码真的是这样格式化的还是你“没有时间”为我们格式化?
  • 我只写了大约 10 分钟,因为我想弄清楚怎么做,我不会先格式化,但我会为你做 :)
  • 只是一个友好的建议 - 尝试从一开始就编写格式化的代码,而不是稍后重新格式化。这样可以节省时间并更容易发现错误/错误。
  • 当然,我确实格式化了一点可读性,谢谢
  • 0x1234567890abcdef+0x1234567890abcdef 超过 20 个charss。所以这个argsread = scanf("%s", str); 溢出了str

标签: c string hex 64-bit scanf


【解决方案1】:

如果代码以 fgets() 开头,用户输入和错误处理会更容易。
然后使用sscanf()strtol()等进行解析。

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,只需使用允许十六进制输入"%x""%i" 的整数格式说明符

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

为什么char str [20]; scanf("%s", str);有麻烦:

"%s" 做了三件事:
1) 扫描但不保存所有前面的(0 个或更多)空白(' ''\t''\n ' 等)。
2) 扫描并保存所有非空白。
3)最后到达一个空白。它停止扫描并将该空白放回stdin

"%s" 说明符缺少宽度,如"%19s",因此很容易溢出str

sscanf(str, "0x%s%c0x%s", b, &amp;a, c);也有问题。

输入在第一个数字的结尾和'+' 之间没有空格,所以"%s" 继续扫描。代码不检查来自sscanf() 的返回值,然后使用abc。所以abc 可能无法正确扫描或初始化 - 导致潜在的未定义行为。

【讨论】:

    【解决方案2】:

    您正在使用 scanf 读取字符串并将其存储在整数中。我认为这就是导致您出现问题的原因。

    另外,来自MAN 页面

    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.
    

    【讨论】:

    • 我将其更改为添加到字符串,但我仍然无法根据 0x 和加号将字符串分成子字符串
    【解决方案3】:

    我认为你放错了分配,如果你想知道有多少参数匹配,然后改变这个

    argsread = scanf("%s", str);
    
    sscanf(str, "0x%x%c0x%x", b, &a, c);
    

    到这里

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

    根据你的cmets,你应该改变一些其他的东西,可能这个代码可以工作

    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;
    

    【讨论】:

    • 好的,但这不是问题,问题在于“0x%x%c0x%x”,正如您在我的更新中看到的那样,b 数组接受所有输入,并且不受 0x 限制, 因为我的输入字符串应该分成3个子字符串2个以0x开头,中间是符号操作
    • 我需要将它们存储在一个 char 数组中,所以我将其更改为“0x%s%c0x%s”,但它仍然不起作用,请参阅更新。谢谢
    • 字符串是一个以空结尾的char 数组,因此中间的char 将被视为字符串的一部分,scanf 将消耗整个输入,从而返回1
    • @Omarshaaban 检查我的新答案更新,这对你有用吗。
    • 次要:不需要"0x%x..." 中的"0x""%x" 将消耗前导的“0x”。
    猜你喜欢
    • 2012-05-30
    • 2010-10-04
    • 2014-03-07
    • 2013-08-09
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    相关资源
    最近更新 更多