scanf第三次没有正常工作

时间:2015-10-18 19:31:49

标签: c scanf

我正在尝试编写一个简单的C程序。输入格式如下:

Enter a: <a>

我想输入a,b,c和d但是scanf对c和d不起作用,程序在该点崩溃。

#include <stdio.h>
#include <math.h>
int main(){
    int a, b, c, d;
    char ch;
    printf("Enter a:");
    scanf("%c%d%c", &ch, &a, &ch);
    printf("Enter b:");
    scanf("%c%d%c", &ch, &b, &ch);
    printf("Enter c:");
    scanf("%c%d%c", &ch, &c, &ch);
    printf("Enter d:");
    scanf("%c%d%c", &ch, &d, &ch);
    double ans;
    ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
    ans=fabs(ans);
    printf("Formula 1 result = <%lf>", ans);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);

C语言在确定其类型时不会考虑对结果所做的操作。因此,将此操作的结果分配给double这一事实对计算结果的方式没有任何影响,它只是将整数结果转换为double。当你用整数除整数时,你得到整数除法。

你可以这样做:

ans=(a*1.0*b/c + c*1.0*d/a)/(b*1.0*a/c + d*1.0*b/a);

乘以非整数强制使用非整数乘法,加法和除法。

答案 1 :(得分:1)

有3种格式转换说明符,不会跳过前导空格。它们是%c(您正在使用),%[…]次扫描集和%n

键入时:

Enter a:<1>
Enter b:<2>

第一个<满足第一个%c; 1%d匹配,>与第二%c匹配,所以到目前为止一切正常。

然而,第二批输入从第一行读取换行符到第一行%c,然后无法将<转换为整数并停止,留下<用于下一个要处理的输入。

提供了Enter c:提示,但处理了<2>因为格式正确,因此提供了Enter d:提示。

有多种方法可以解决此问题,包括:

  1. 在格式字符串中的第一个%c之前插入空格。这将跳过空格,包括换行符,并为您提供预期的行为。这可能是最简单的解决方法。
  2. 读取行并使用sscanf()来处理它们。这通常是最好的解决方案。 (使用fgets()读取该行。)
  3. 在任何一种情况下,检查scanf()族函数是否返回正确的值(3)。并使用两个变量int c1, c2;来读取字符并验证用户输入了您需要的内容。

    最低限度的修正是:

    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int a, b, c, d;
        char c1, c2;
        printf("Enter a: ");
        if (scanf(" %c%d%c", &c1, &a, &c2) != 3 || c1 != '<' || c2 != '>')
            fprintf(stderr, "Bogus input!\n"), exit(1);
        printf("Enter b: ");
        if (scanf(" %c%d%c", &c1, &b, &c2) != 3 || c1 != '<' || c2 != '>')
            fprintf(stderr, "Bogus input!\n"), exit(1);
        printf("Enter c: ");
        if (scanf(" %c%d%c", &c1, &c, &c2) != 3 || c1 != '<' || c2 != '>')
            fprintf(stderr, "Bogus input!\n"), exit(1);
        printf("Enter d: ");
        if (scanf(" %c%d%c", &c1, &d, &c2) != 3 || c1 != '<' || c2 != '>')
            fprintf(stderr, "Bogus input!\n"), exit(1);
        double ans;
        ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
        ans=fabs(ans);
        printf("Formula 1 result = <%lf>\n", ans);
        return 0;
    }
    

    我在if语句之后对逗号运算符很懒。但是,使用函数来管理输入会更好:

    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    static void get_number(int *var, const char *name)
    {
        char c1, c2;
        printf("Enter %s: ", name);
        if (scanf(" %c%d%c", &c1, var, &c2) != 3 || c1 != '<' || c2 != '>')
        {
            fprintf(stderr, "Bogus input!\n");
            exit(1);
        }
    }
    
    int main(void)
    {
        int a, b, c, d;
    
        get_number(&a, "a");
        get_number(&b, "b");
        get_number(&c, "c");
        get_number(&d, "d");
    
        double ans;
        ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
        ans=fabs(ans);
        printf("Formula 1 result = <%lf>\n", ans);
        return 0;
    }
    

    最好还是使用:

    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    static int get_number(const char *name)
    {
        char buffer[4096];
    
        printf("Enter %s: ", name);
        if (fgets(buffer, sizeof(buffer), stdin) == 0)
        {
            fprintf(stderr, "EOF or error on input\n");
            exit(1);
        }
        char c1, c2;
        int val;
        if (sscanf(buffer, " %c%d%c", &c1, &val, &c2) != 3 || c1 != '<' || c2 != '>')
        {
            /* buffer contains a newline unless you typed more than 4095 characters before the newline */
            fprintf(stderr, "Bogus input (does not match <number>): %s", buffer);
            exit(1);
        }
        return val;
    }
    
    int main(void)
    {
        int a = get_number("a");
        int b = get_number("b");
        int c = get_number("c");
        int d = get_number("d");
        double ans = fabs((a*b/c + c*d/a) / (b*a/c + d*b/a));
        printf("Inputs: a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
        printf("Formula 1 result = <%lf>\n", ans);
        return 0;
    }
    

    请注意代码如何使用fgets()sscanf(),这意味着错误消息可以告诉用户他们输入的内容不是预期的内容。它还使用该函数返回值,从而显示更简单的代码。输出包括检查的输入值。您的提交系统可能不需要这样做,但在您开发代码时它肯定会对您有所帮助。

    您可以进行升级以处理double值作为输入;这并不难。