scanf() 可以将非零输入转换为零吗

Can scanf() turn non-zero input into zero

提问人:Michael May 提问时间:8/27/2016 更新时间:8/27/2016 访问量:235

问:

在下面的代码中,main() 中的 scanf() 将其中一个输入数字从非零数字转换为零,如 while 循环中的调试 printf() 所示。我已经在几个编译器上测试了它,但只是为了继续得到相同的结果。请告诉我为什么会这样,请帮助我。谢谢。

 #include <stdio.h>

unsigned srl (unsigned x, int k)
{
    /* perform shift arithmetically */
    printf("x = %u, (int) x= %d\n", x, (int) x);
    unsigned xsra = (int) x >> k;
    printf("\nxsra before was: %u\n", xsra);
    unsigned test = 0xffffffff;
    test <<= ((sizeof (int) << 3) - k); // get e.g., 0xfff00...
    printf("test after shift is: %x, xsra & test = %x\n", test, xsra & test);
    if (xsra & test == 0) // if xsrl is positve
        return xsra;
    else
        xsra ^= test;    // turn 1s into 0s

    return xsra;
}

int sra (int x, int k) 
{
    /* perform shift logically */
    int xsrl = (unsigned) x >> k;
    unsigned test = 0xffffffff;
    test << ((sizeof (int) << 3) - k + 1); // get e.g., 0xffff00...
    if (xsrl & test == 0) // if xsrl is positve
        return xsrl;
    else 
                            xsrl |= test;

        return xsrl;
}

int main(void)
{
    int a;
    unsigned b;
    unsigned short n;

    puts("Enter an integer and a positive integer (q or negative second number to quit): ");
    while(scanf("%d%u", &a, &b) == 2 && b > 0)
    {
        printf("Enter the number of shifts (between 0 and %d): ", (sizeof (int) << 3) - 1);
        scanf("%d", &n);
        if (n < 0 || n >= ((sizeof (int)) << 3))
        {
            printf("The number of shifts should be between 0 and %d.\n", ((sizeof (int)) << 3) - 1);
            break;
        }
        printf("\nBefore shifting, int a = %d, unsigned b = %u\n", a, b);
        a = sra(a, n);
        b = srl(b, n);
        printf("\nAfter shifting, int a = %d, unsigned b = %u\n", a, b);
        puts("\nEnter an integer and a positive integer (q or negative second number to quit): ");
    }
    puts("Done!");

    return 0;
}
c 扫描

评论

2赞 ameyCU 8/27/2016
的说明符 should be 和 not 。unsgined short%hu%u
0赞 RastaJedi 8/27/2016
如果你让我知道哪一个变为 0,那会更容易,这样我就不必自己编译整个东西......(好吧,实际上,我可以想象这可能是在重新加载并看到 amey 的评论之后。此外,OP 永远不能是负数,因为它是 .nnunsigned
1赞 RastaJedi 8/27/2016
他实际上使用的是 ,而不是 , for,尽管仍然不正确。%d%un
0赞 Michael May 8/28/2016
谢谢你,ameyCU和RastaJedi。您的评论非常切中要害,非常有帮助。这确实是典型的溢出。

答:

4赞 lnyng 8/27/2016 #1

问题是,它的大小小于正常的 。调用 时,它会将值读入,如果内存位置紧跟在 后面,则可能会覆盖现有值。nunsigned shortintscanf("%d", &n);nbbn

您所要做的就是将有问题的行更改为:

scanf("%hu", &n);

是从这里开始的 的修饰符。hunsigned short int

评论

2赞 RastaJedi 8/27/2016
这是另一个示例,说明为什么您应该始终使用 和 进行编译。-Wall-Wextra
0赞 Michael May 8/28/2016
谢谢你,梁。你的回答很有帮助。没错,由于输入格式说明符不正确,因此会出现溢出。
0赞 Michael May 8/28/2016
再次感谢你,RastaJedi。我假设 -Wall 和 -Wextra 选项是默认值,但实际上并不是每个编译器的默认值