为什么这会接受无效输入?

时间:2012-10-15 05:11:15

标签: c

我在c

中有一个三角形程序
#include <stdio.h>

// A function which decides the type of the triangle and prints it
void checkTriangle(int s1, int s2,int s3)
{
    // Check the values whether it is triangle or not.
    if ((s1 + s2 > s3 && s1 +  s3 > s2 && s2 + s3 > s1) && (s1 > 0 && s2 > 0 && s3 > 0))
    {
        // Deciding type of triangle according to given input.
        if (s1 == s2 && s2 == s3)
            printf("EQUILATERAL TRIANGLE");
        else if (s1 == s2 || s2 == s3 || s1 == s3)
            printf("ISOSCELES TRIANGLE\n");
        else
            printf("SCALENE TRIANGLE \n");
    }
    else
        printf("\nTriangle could not be formed.");
}

int main(void)
{
    // Initializing variables
    int a,b,c;

    // Getting input from user
    printf("Please enter the sides of triangle");

    printf("\nPlease enter side 1:");
    scanf("%d",&a);

    printf("Please enter side 2:");
    scanf("%d",&b);

    printf("Please enter side 3:");
    scanf("%d",&c);

    // Calling function in order to print type of the triangle.
    checkTriangle(a,b,c);
}

当输入为:

7b

它给出了一个错误,这就是我想要的,但当我输入这样的数据时:

7
7
7b 

它忽略'b'并将7作为整数 - 但为什么呢?我该如何防止这种情况?

我想要做的是为

提供错误
7
7
7b

5 个答案:

答案 0 :(得分:3)

如果您希望能够使用用户的输入检测错误,例如行不是有效的十进制整数,那么您可以执行以下操作:

  • 使用fgets(buffer, size, stdin)
  • 将输入读入缓冲区
  • 使用strtoul(buffer, &endptr, 10)将缓冲区解析为十进制整数(基数 10 ),其中endptrchar*
  • endptr将指向buffer中的第一个无效字符,即。最后一个成功解析后的字符
  • 现在如果*endptr == '\0',即。 endptr指向buffer的末尾,整个字符串被解析为有效的十进制整数

答案 1 :(得分:1)

如果你真的希望每个数字在一个单独的输入行上,并且整个行都是有效的数字或空格,那么你可能需要忘记scanf()和家人并使用fgets()strtol()代替。

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>

static int read_side(void)
{
    char buffer[4096];
    if (fgets(buffer, sizeof(buffer), stdin) == 0)  // EOF
        return -1;
    char *end;
    errno = 0;
    long result = strtol(buffer, &end, 10);
    if (result < 0 || errno != 0) // Neither errors nor negative numbers are allowed
        return -1;
    if (end == buffer)     // Nothing was convertible
        return -1;
    while (isspace(*end))
        end++;
    if (*end != '\0')      // Non-spaces after the last digit
        return -1;
    if (result > INT_MAX)  // Result too big for `int`
        return -1;
    return result;
}

(如果您需要接受任何有效的int值但是区分错误,那么您将传入指向该函数的指针并在出错时返回-1或在成功时返回0,并将安全结果分配给指针。)

是的,正确地完成这项工作确实非常繁琐。是的,分析strtol()的结果就像那样棘手;你必须要非常小心。 (并且有一个外部的机会我忘记检查可检测到的错误情况。)不,我认为你不能用scanf()等做同等工作;特别是,scanf()溢出时的行为未定义。

答案 2 :(得分:0)

%d只接受整数。尝试使用scanf()中的%x进行十六进制十进制输入。

最好你可以输入字符串然后使用isnumeric()进行检查,否则请使用scanf("%[^\n]s", word),如@mou建议。

答案 3 :(得分:0)

你不应该使用scanf或者使用scanf(&#34;%[^ \ n] s&#34;,word);或者像get()一样使用某些东西 还把d或x放在我的例子的末尾而不是字符串:P

答案 4 :(得分:0)

将输入读入字符串缓冲区。解析字符串以逐个提取任何类型的数值。