如何忽略scanf中的浮点数(“%d”)?

时间:2013-08-20 15:42:41

标签: c scanf

如果用户为整数变量输入浮点数,我想打印无效输入。那可能吗?

 int a;
 scanf("%d",&a); // if user enters 4.35 print invalid input 

我曾尝试过像这样的角色

  if(scanf("%d",&a)==1);
  else printf("invalid input");

但如何处理浮动数字。如果用户输入4.35,它会截断为4,但我想要无效输入。

9 个答案:

答案 0 :(得分:11)

由于小数点前的任何数字的浮点数的开头看起来像一个整数,因此无法单独使用%d检测到这一点。

您可以考虑使用fgets()阅读整行,然后使用sscanf()进行分析:

int a;
int n;
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0 && sscanf(line, "%d%n", &a, &n) == 1)
   ...analyze the character at line[n] for validity...

(是的,我的意思是与1进行比较; %n转换规范不会计入sscanf()等的返回值。

scanf()执行此操作的一件事是在输入数字之前跳过空白行。如果这很重要,你必须编写一个循环来读取(非空)行,然后解析非空行。您还需要确定线路上有多少尾随垃圾(如果有的话)。是否允许空白?标签?阿尔法字符?标点?

答案 1 :(得分:4)

您必须将其作为双精度读取,然后检查它是否为整数。检查它是否为整数的最佳方法是使用modf,它返回double的小数部分。如果有,则表示您有错误:

double d;
scanf("%lf", &d);

double temp;
if(modf(d, &temp)){
  // Handle error for invalid input
}

int a = (int)temp;

这将允许小数点后只有0 s的整数或浮点数,例如54.00000。如果你想把它视为无效,你最好逐个阅读,并确认每个字符都在09之间(ascii 48到57)。

答案 2 :(得分:3)

这不能通过读取int来查看停止扫描的内容。

经典成语

char buf[100];
if (fgets(buf, sizeo(buf), stdin) == NULL) {
  ; // deal with EOF or I/O error
}
int a;
char ch;
if (1 != sscanf(buf, "%d %c", &a, &ch)) {
  ; // Error: extra non-white space text
}

答案 3 :(得分:2)

您可以使用strtol()strtod()并比较结束指针,例如这样:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char buffer[100];
    char * endptr_n;
    char * endptr_d;
    long n;
    double d;

    fgets(buffer, 100, stdin);
    n = strtol(buffer, &endptr_n, 10);
    if ( endptr_n == buffer ) {
        fputs("You didn't enter a number.", stderr);
        return EXIT_FAILURE;
    }

    d = strtod(buffer, &endptr_d);

    if ( *endptr_d == '\0' || *endptr_d == '\n' ) {
        if ( endptr_d == endptr_n ) {
            puts("You entered just a plain integer.");
        } else {
            puts("You entered a floating point number - invalid.");
        }
    } else {
        puts("You entered garbage after the number - invalid.");
    }

    return EXIT_SUCCESS;
}

输出:

paul@local:~/src/c$ ./testint
2
You entered just a plain integer.
paul@local:~/src/c$ ./testint
2.3
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
3e4
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
4e-5
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
423captainpicard
You entered garbage after the number - invalid.
paul@local:~/src/c$

它不使用scanf(),但这是一件好事,它避免了在您读取的整数之后手动检查输入的需要。

显然,如果线路上唯一的东西是数字,那么很多事情就变得没必要,因为你可以立即拨打strtol()并立即检查*endptr_n,但是如果有其他东西的话这就是你如何做到这一点,例如如果你想接受一个整数后跟任何非数字的整数,但不是一个浮点然后是同一个东西,你可以删除if ( *endptr_d == '\0' || *endptr_d == '\n' )逻辑。

编辑:更新了代码以显示对*endptr的检查。

答案 4 :(得分:1)

这个更简单:

#include <stdio.h>

int main() 
{
    int a;
    long double b;

    scanf("%f",&b);
    a = (int) b;

    a == b ? printf("%d\n",a) : printf("Invalid input!");

    return 0;
} 

输入:4
输出:

4

输入:4.35
输出:

 Invalid input

答案 5 :(得分:1)

这是一个简单的方法:

#include <stdio.h>

int main(int argc, char **argv) {
    int d;
    printf("Type something: ");

    // make sure you read %d and the next one is '\n'
    if( scanf("%d", &d) == 1 && getchar() == '\n' ) {
        printf("%d\n", d);
    }

    return 0;
}

$ a.exe
Type something: 312312.4214

$ a.exe
Type something: 2312312
2312312

$ a.exe
Type something: 4324.

$

答案 6 :(得分:1)

首先,scanf没有任何问题。当用户输入浮动时,他们实际输入一个数字点号。因此,编写scanf来检测该数据条目。

main()
  {
       char c1[2];
       int num1;

       int nr_nums;

       nr_nums = scanf("%d%1[.e0123456789]", &num1, &c1);

       if (nr_nums == 1) {printf("\ndata = %d", num1);}
       if (nr_nums == 2) {printf("\nInvalid");}

 }

根据评论的建议,修改此代码的另一种可能的数据输入格式为1.或3e-1。

此代码了解您的要求的基础知识。它接受Integer数据输入并检测何时输入浮点数。

答案 7 :(得分:0)

如果您将数字表示为字符串(当您使用了fgets时),您可以运行for循环并将每个字符与'。'进行比较。

答案 8 :(得分:-1)

我可以看到的另一个选择如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{

 char mystring[31];
 scanf("%30s[0-9]\n", mystring);
 int mynumber = atoi(mystring);
 printf("here is your integer: %d", mynumber);
 getchar();
 getchar();
 return 0;











 }