仅在scanf语句中使用“%1d”而不是“%d”有什么区别?

时间:2016-11-02 12:38:01

标签: c

https://www.codechef.com/problems/LCOLLIS

我在codechef上解决了上面的问题,我为它编写了下面的代码,但它给了我运行时错误(SIGSEVG)。

#include<stdio.h>

int main(void)
{
int t, n, m;
scanf("%d", &t);

while(t--)
{
    scanf("%d %d", &n, &m);

    int a[10][10], i, j, sum, ans;

    for(i = 0; i < n; i++)
    {
        for(j = 0; j < m; j++)
            scanf("%d", &a[i][j]);
    }

    ans = 0;
    for(i = 0; i < m; i++)
    {
        sum = 0;
        for(j = 0; j < n; j++)
        {
            if(a[j][i] == 1)
                sum++;
        }


        if(sum > 1)
            ans = ans + ( sum * (sum - 1) ) / 2;
    }

    printf("%d\n", ans);
}

return 0;
}

我看到其中一个与我完全相同的解决方案只是略有不同而且被接受了。代码如下:

#include<stdio.h>

int main(void)
{
int t, n, m;
scanf("%d", &t);

while(t--)
{
    scanf("%d %d", &n, &m);

    int a[10][10], i, j, sum, ans;

    for(i = 0; i < n; i++)
    {
        for(j = 0; j < m; j++)
            scanf("%1d", &a[i][j]); // SEE RIGHT HERE ITS JUST A 1 BEFORE d
    }

    ans = 0;
    for(i = 0; i < m; i++)
    {
        sum = 0;
        for(j = 0; j < n; j++)
        {
            if(a[j][i] == 1)
                sum++;
        }


        if(sum > 1)
            ans = ans + ( sum * (sum - 1) ) / 2;
    }

    printf("%d\n", ans);
}

return 0;
}

现在我无法理解这一点是如何产生重大影响的。 请有人帮助我。

3 个答案:

答案 0 :(得分:1)

如果没有宽度说明符,scanf()会读取所有数字,而不是在单个数字后停止。同一行的以下scanf()将失败,在矩阵中留下未定义/垃圾数据。

所以对于链接页面的第一行:

111

将被视为整数111,后面没有任何内容,而不是三个。当然,这在CodeChef方面是狡猾的。 :)

使用scanf()来阅读单个字符非常难以理解,你可以做一些更简单的事情。

此外,如果您使用scanf()总是检查其返回值:它的I / O和可能会失败

答案 1 :(得分:0)

"%1d"中的1是 width 限制。在扫描前导空白区域后,它是字符的最大数量(不仅仅是数字)。

"%d"不限制它将扫描的最大字符数。

int main() {
  int i;
  i = 42; sscanf("  123", "%1d", &i); printf("%d\n", i);
  i = 42; sscanf("123", "%1d", &i); printf("%d\n", i);
  i = 42; sscanf("-123", "%1d", &i); printf("%d\n", i);
  i = 42; sscanf("+123", "%1d", &i); printf("%d\n", i);
  i = 42; sscanf("  -123", "%1d", &i); printf("%d\n", i);
}

输出

1
1
42  // Nothing saved into `i`
42  //       "
42  //       "

答案 2 :(得分:0)

所以,假设我要扫描一个文本文件,该文件包含一个二进制数字矩阵,它们之间没有任何空格。转换规范%d没有定义额外的字段(字段宽度和精度字段)。扫描时,%d会查找空格以确定整数的结尾。

但在我们的例子中,我们已经定义了一个没有任何空间的二进制矩阵,因此程序会抛出一个垃圾值。我们可以做的是我们可以在%d中定义字段宽度1,例如%1d。这些不会在打印输出时添加任何额外的空间,但这样scanf现在知道每个整数都是一个带有额外空字段的数字(在我们的例子中是一个空格)。现在即使你没有在两个数字之间放置空格,它也会将它作为单独的数字扫描。

例如,1001010将作为不同的数字分别扫描为1和0,而不是将1001010扫描为整个数字。这是一个简单的代码示例。

int main()
    {
        FILE *ptr;

        int i,j,count_0=0,count_1=0;
        int a[row][col];

        ptr=fopen("bin.txt","r");

        for(i=0;i<3;i++)
        {
            for(j=0;j<3;j++)
            {
                fscanf(ptr,"%1d",&a[i][j]);

            }
        }

        for(i=0;i<3;i++)
        {
           for(j=0;j<3;j++)
           {
              printf("%1d",a[i][j]);
           }
           printf("\n");
        }

     return 0;
    }