【问题标题】:scanf is getting skipped, showing segmentation fault [duplicate]scanf 被跳过,显示分段错误 [重复]
【发布时间】:2021-04-20 03:44:34
【问题描述】:

此代码表示分段错误导致程序的 scanf 不起作用。我使用调试器来找出这一点。 scanf(num) 被跳过。因此分段错误。有人能说出为什么 scanf 被跳过了吗?我使用 [^\n] 以便 scanf 可以读取带空格的字符串。帮助。

#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(void)
{
    int a, b;

    scanf("%d %d", &a, &b);
    int sumr, maxr;
    int sumc, maxc;

    int white[b + 1];
    white[0] = -1;
    int ele[b][a];
    for (int opl = 0; opl < a; opl++)
    {
        for (int pl = 0; pl < b; pl++)
        {
            ele[pl][opl] = 0;
        }
    }
    char num[100000];
    int c = -1;
c:
    c++;
    scanf("%[^\n]%*c", num);
    int hu = 0;
    int len = strlen(num);
    white[b] = len;
    for (int ji = 0; ji < len; ji++)
    {
        if (isspace(num[ji]))
        {
            white[hu] = ji;
            hu++;
        }
    }
    for (int ft = 0; ft < b; ft++)

    {
        int lopl = 1;
        for (int koi = white[ft + 1] - 1; koi > white[ft]; koi--)
        {
            ele[ft][c] += lopl * (num[koi] - '0');
            lopl = lopl * 10;
        }
    }

    if (a > c)
        goto c;
}

【问题讨论】:

  • 您的一个问题是scanf("%d %d", …) 在缓冲区中留下了换行符。您的下一个输入是scanf("%[^\n]%*c", …),由于留下换行符而立即失败。正如在下面的一些答案中所指出的,您没有检查您的输入是否成功,因此您的代码在使用未初始化的变量时会出错,这通常会导致不愉快。

标签: c segmentation-fault scanf


【解决方案1】:
scanf("%[^\n]%*c", num);

作为第一步。您应该始终检查可能对您的程序产生不利影响的函数的返回值。换句话说,类似于:

if (scanf("%d %d", &a, &b) != 2) { handleOneProblem(); }
if (scanf("%[^\n]%*c", num) < 1) { handleAnother(); }

如果第二个失败,那么num 将保留它在调用之前包含的任意数据,并且您可能不想然后使用它,就好像它包含一个有效的字符串。

最重要的是,您应该知道一些,但不是全部,scanf 格式说明符会在尝试读取数据之前吞噬空白。例如,%d 将首先跳过空格,然后尝试读取一个整数。但是,[c 等格式说明符不会。

并且 none 在为格式说明符读取字段后,它们中的任何一个都会吞噬空白。这意味着,如果你想这样做,你需要自己做,使用一组函数,比如:

#include <stdio.h>

int gobbleLineFile(FILE *inFile) {
    int ch;
    while ((ch = fgetc(inFile)) != '\n' && ch != EOF) {}
    return ch;
}

int gobbleLineStdIn(void) { return gobbleLineFile(stdin); }

顺便说一句,scanf 的许多问题是由那些跳过空格的格式说明符与不跳过空格的格式说明符混合引起的。您可以按照上面的建议围绕它进行编码,但是,如果您希望用户提供基于行的输入,通常最好将所有事情都作为基于行的输入,然后使用sscanf 来中断分开线。

可以找到一个相当不错的基于行的输入例程here

【讨论】:

    【解决方案2】:

    你必须抓住第一次scanf留下的'\n'

    要么改成:scanf("%d %d\n", &amp;a, &amp;b);

    或者在它后面加上getchar();

    因为下一个读数:scanf("%[^\n]%*c", num); 将一直读取到下一个 '\n',这是缓冲区中剩下的第一件事。

    【讨论】:

    • 我不会使用getchar(),那只会得到一个空格,如果用户输入1&lt;space&gt;2&lt;space&gt;&lt;newline&gt;就会有问题。
    • 使用“gobble”函数——可能是内联函数——例如:static inline void gobble(void) { int c; while ((c = getchar()) != EOF &amp;&amp; c != '\n') ; }。这会吃掉所有剩余的字符,直到下一个换行符。
    • @JonathanLeffler:这可能是有史以来最好的函数名称!使用类似的扩展我的答案,希望你不介意:-)
    猜你喜欢
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多