检查,如果输入是一个数字,如果不是返回到输入 [英] check if input is a number and if not return to input

查看:106
本文介绍了检查,如果输入是一个数字,如果不是返回到输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我是新来这个网站,我是新来编程。我在我的第一本书,我爸爸做了功课,他不知道codeS做什么,但我想这样做。因此,这里是我想做的事:
我想创建一个程序就像一个计算器,你输入一个值A和值B,然后程序会显示我已经做到了A + B的结果,问题是,如果我输入一个字符程序保持阅读其他codeS。以下是我已经写了,也许你会更好地理解。

 的#include<&stdio.h中GT;
#包括LT&;&CONIO.H GT;
#包括LT&;&文件ctype.h GT;
无效的主要(无效)
  {
   INT val_a;
   INT val_b;
   INT结果;   的printf(写了一些A =);
   scanf函数(%d个,&安培; val_a);
   如果(ISDIGIT(val_a))
   {
    的printf(\\ NWRITE数目B =);
    scanf函数(%d个,&安培; val_b);
   }
其他
  的printf(\\倪说数\\ n);
结果= val_a + val_b;
的printf(%D +%D =%d个,val_a,val_b,结果);
残培();
的printf(\\ 033 [2J); \\\\清除屏幕
}

所以,我想的是,该方案将回来,我要输入数字A.
我在谷歌找到关于标签的,但我不明白什么:D。也许有人可以张贴我想这样我可以研究它的例子。

我应该写我的名字?也许下一次:P

PS:我希望有人会在我写的找到一个NOOB错误,并告诉我这件事。 :祈祷:


解决方案

批判

 的#include<&stdio.h中GT;
#包括LT&;&CONIO.H GT;

那么,你是在Windows上工作。

 的#include<&文件ctype.h GT;
无效的主要(无效)

的返回类型的main() INT ,即使你会发现很多的例子来与此相反。

  {
    INT val_a;
    INT val_b;
    INT结果;    的printf(写了一些A =);
    scanf函数(%d个,&安培; val_a);

您应该从 scanf()的测试返回值,看看它是否能够读取数字或没有。

 如果(ISDIGIT(val_a))

此测试作品,但它会检查数量是否进入了范围48..57(一个值是ASCII,CP1252,统一code,ISO 8859-1等codeS对于数字 0 '9')。这可能不是你脑子里的东西。

  {
        的printf(\\ NWRITE数目B =);
        scanf函数(%d个,&安培; val_b);

在用户输入一个换行符,所以前面的换行符OT了的printf()格式字符串是没有必要的,但它也没有害处。有关检查同样的评论 scanf()的在这里也适用。

 }
    其他
        的printf(\\倪说数\\ n);

这是好事,做错误检查。但是,你继续向前,即使你检测到错误。你真的需要停下来。

 结果= val_a + val_b;
    的printf(%D +%D =%d个,val_a,val_b,结果);

从总体上看,最好是用新行结束线。它刷新的数据文件或屏幕。

 的getch();
    的printf(\\ 033 [2J); \\\\清除屏幕

的printf()格式字符串是不可移植。既然你包括< CONIO.H> ,你应该使用 clrscr()(这可能不发送转义序列,或等价物,向终端)。我不相信,有必要清除屏幕在节目的最后,但我的工作主要是在Unix系统上,而不是在Windows中。

 }

由于MSVC仍然是一个C89编译器,你应该包括返回0; 在程序返回成功状态的结束

重写

添加所有的变化,你会结束:

 的#include<&stdio.h中GT;
#包括LT&;&CONIO.H GT;INT主要(无效)
{
    INT val_a;
    INT val_b;
    INT结果;    的printf(写了一些A =);
    如果(scanf的(%d个,&放大器;!val_a)= 1)
    {
        的printf(我说一些\\ n);
        残培();
        clrscr();
        返回(1);
    }
    的printf(\\ NWRITE数目B =);
    如果(scanf的(%d个,&放大器;!val_b)= 1)
    {
        的printf(我说一些\\ n);
        残培();
        clrscr();
        返回(1);
    }    结果= val_a + val_b;
    的printf(%D +%D =%d个\\ N,val_a,val_b,结果);
    残培();
    clrscr();
    返回(0);
}

当您已经了解编写函数,你可能COM preSS,为:

 的#include<&stdio.h中GT;
#包括LT&;&CONIO.H GT;静态INT get_a_number(为const char *提示)
{
    int值;
    的printf(提示);
    如果(scanf的(%d个,&放大器;!值)= 1)
    {
        的printf(我说一些\\ n);
        残培();
        clrscr();
        出口(1);
    }
    返回值;
}INT主要(无效)
{
    INT val_a = get_a_number(写了一些A =);
    INT val_b = get_a_number(写了一些B =);
    INT结果= val_a + val_b;
    的printf(%D +%D =%d个\\ N,val_a,val_b,结果);
    残培();
    clrscr();
    返回(0);
}

get_a_number()函数不是一个通用的功能,但由于它封装code常见的一块正是在这样的背景下是有用的。


  

      
  • 子程序调用允许我们总结的违规的参数列表。

  •   
  • 子程序本身总结了code的的规律

  •   

这是从Kernighan的&放大器报价; Plauger,编程风格的要素。


使用的atexit()

在code以上进行了更新,包括残培() clrscr()所有退出路径(并删除的#include<&文件ctype.h GT; 因为没有从它的功能被用于任何更多)。这是写出来的这两个功能重复调用滋扰。为了避免这个问题的另一种方法是编写一个程序退出时调用的功能; 你的的atexit()函数,它在&LT宣布其注册>

 的#include<&stdio.h中GT;
#包括LT&;&CONIO.H GT;
#包括LT&;&stdlib.h中GT;静态无效wait_at_exit(无效)
{
    残培();
    clrscr();
}静态INT get_a_number(为const char *提示)
{
    int值;
    的printf(提示);
    如果(scanf的(%d个,&放大器;!值)= 1)
    {
        的printf(我说一些\\ n);
        出口(1);
    }
    返回值;
}INT主要(无效)
{
    的atexit(wait_at_exit);
    INT val_a = get_a_number(写了一些A =);
    INT val_b = get_a_number(写了一些B =);
    INT结果= val_a + val_b;
    的printf(%D +%D =%d个\\ N,val_a,val_b,结果);
    返回(0);
}

这code的main()假定你可以混合语句(如的atexit())和声明(如 INT val_a )随意。即由双方目前(2011年)和标准C的旧的(1999)版本允许的,但不是由标准C.原(1989)版本允许我相信MSVC坚持原来的标准。如果是这样,你可能需要编写的main()为:

  INT主要(无效)
{
    的atexit(wait_at_exit);
    {
    INT val_a = get_a_number(写了一些A =);
    INT val_b = get_a_number(写了一些B =);
    INT结果= val_a + val_b;
    的printf(%D +%D =%d个\\ N,val_a,val_b,结果);
    }
    返回(0);
}

这是一个很好的讨论点内部块(内大括号)内的code是否应缩进一个额外的水平或没有。你总是在允许的花括号括起来code块的起始声明变量,这样可以让我写调用的atexit()然后再定义并使用这些变量。

如果您了解敏捷编程,你会发现,咒语之一是:


  • 干,MDASH;不要重复自己

上面的重写,以避免反复 getscr()通话可能被认为是口头禅的应用。同样与 get_a_number()功能;它应用干的口头禅。


试图再次

如果您希望程序回去,如果用户犯了错误他们打字再次提示,那么你需要修改 get_a_number()功能。而且,由于该功能大幅增长较为复杂,你的绝对的需要使用作业的功能。你也碰到与 scanf()的问题;它不允许你执行每行一个号码。如果键入 1 2 响应第一个提示,第一次调用 get_a_number()会读的人;空白,停止解析(并把再利用空白背面),并与值1第二次调用 get_a_number()将输出提示符返回,但与返回值2无需用户输入任何东西。如果这不是你想要的行为,那么你必须安排读取整个第一线和扫描数量,然后丢弃休息。还有另外一个原因过虑。如果用户键入 A 而不是 1 时, scanf()的将永远不会读任何东西;它会进入一个循环,发现了 A 是无效的数字,返回0,转换完成后,你的code可能会在一个无限循环结束,提示输入和读取 A 。这样的问题是为什么很多人(特别是我)避免使用 scanf()的

要避免大多数上述问题的最简单方法是使用与fgets()的sscanf()

 枚举{MAX_LINELENGTH = 4096};
枚举{MAX_ATTEMPTS次= 10};静态INT get_a_number(为const char *提示)
{
    int值;
    焦线[MAX_LINELENGTH]
    诠释计数= 0;
    而(的fputs(提示,标准输出)= EOF和放大器;!&安培;
           与fgets(线,的sizeof(线),标准输入)!= 0)
    {
        如果(sscanf的(行,%D,&安培;价值)== 1)
            返回值;
        如果(计数++盐MAX_ATTEMPTS次)
        {
            的printf(我给的,我不明白你正在输入的内容\\ n);
            出口(1);
        }
        的printf(我说,请输入号码\\ n);
    }    的printf(哎呀!我得到了EOF或错误;再见\\ n);
    出口(1);
}

这涵盖了相当多的问题。通常,它是回显错误的数据是个好主意。你可以做到这一点与

 的printf(我不明白你的意思,当你键入:\\ n%S \\ n
               我说,请输入号码\\ n,行);

本使用'相邻字符串连接,并显示收到什么程序的用户,这往往可以帮助用户了解什么是错的。

我用的fputs(提示,标准输出)而不是的printf(提示)来输出提示。要么可以使用(的printf(提示)!= 0 将是检验)​​,但有一个微弱的优势的fputs(),因为如果有人设法颠覆你的程序,并获得进入提示,的printf()会尝试处理它不是传递参数,而的fputs()不跨preT其参数字符串的。这里,差别是可以忽略的;它可以合理地认为我是过于复杂的事情。但程序的安全性也是你最终学习的东西,和技术,如不使用的printf(变量)可以帮助让你的程序更具弹性。 (实际上,并发症是解释;在code是相当简单)

另一个详细讨论的焦点是应该有一个 fflush()的fputs()和前与fgets()?这将是可能的额外的条件 fflush(stdout中)== 0&放大器添加;&放大器; 来的回路控制,但在实践中它通常是不必要的。它只会有所作为,如果标准输入是从比端子和标准输出正想文件以外的东西来了。所以,我离开了出来。

在循环prevents事情计数器会严重歪曲—程序退出,而不是永远流连,折腾谁也不能得到正确的数据输入的用户。你曾经有一个程序弹出一个对话框,在其中你只能打确定按钮(即使它也不行),然后用同一个​​盒子回来,一遍又一遍又一遍?我希望不会为你着想。我有;这让我很沮丧,当它发生。

你可以看到为什么它是有利的,写的code get_a_number()只有一次,而不是两次;这将是一个很大的重复。

So, I am new to this site and I am new to programming. I am at my first book and my dad gave a "homework", he doesn't know the codes to do what this, but I want to do it. So here it is what I want to do: I want to create a program like a calculator where you input a value A and a value B and then the program shows the result of A + B. I have done that, the problem is that if I input a character the program keeps reading the other codes. Here is what i have written, maybe you will understand better.

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
void main(void)
  {
   int val_a;
   int val_b;
   int result;

   printf("Write a number A=");
   scanf("%d", &val_a);
   if(isdigit(val_a))
   {
    printf("\nWrite a number B=");
    scanf("%d", &val_b);
   }
else
  printf("\nI said number.\n");
result = val_a + val_b;
printf("%d + %d = %d", val_a, val_b, result);
getch();
printf("\033[2J");   \\ to clear the screen
}

So what I want is that the program will come back to where I have to input the number A. I found on google about labels, but I didn't understand anything :D. Maybe someone can post an example of what I want so I can study it.

Should i write my name? Maybe next time :P

PS: I hope someone will find a NOOB mistake in what I wrote and tell me about it. :pray:

解决方案

Critique

#include <stdio.h>
#include <conio.h>

So you are working on Windows.

#include <ctype.h>
void main(void)

The return type of main() should be int, even though you'll find lots of examples to the contrary.

{
    int val_a;
    int val_b;
    int result;

    printf("Write a number A=");
    scanf("%d", &val_a);

You should be testing the return value from scanf() to see whether it was able to read a number or not.

    if (isdigit(val_a))

This test 'works', but it checks whether the number entered was a value in the range 48..57 (which are the ASCII, CP1252, Unicode, ISO 8859-1, etc codes for the digits '0' to '9'). This probably wasn't what you had in mind.

    {
        printf("\nWrite a number B=");
        scanf("%d", &val_b);

The user entered a newline, so the newline in front ot the printf() format string is not necessary, though it is also not harmful. The same comment about checking scanf() applies here, too.

    }
    else
        printf("\nI said number.\n");

It is good to do error checking. However, you continue onwards even if you detect the error. You really need to stop.

    result = val_a + val_b;
    printf("%d + %d = %d", val_a, val_b, result);

On the whole, it is best to end lines with a newline. It flushes the data to the file or screen.

    getch();
    printf("\033[2J");   \\ to clear the screen

The printf() format string is not portable. Given that you included <conio.h>, you should probably use clrscr() (which probably does send that escape sequence, or an equivalent, to the terminal). I'm not convinced that it is necessary to clear the screen at the end of the program, but I work mainly on Unix systems, not with Windows.

}

Given that MSVC is still a C89 compiler, you should include return 0; at the end of the program to return a success status.

Rewritten

Adding all the changes, you'd end up with:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    int val_a;
    int val_b;
    int result;

    printf("Write a number A=");
    if (scanf("%d", &val_a) != 1)
    {
        printf("I said number.\n");
        getch();
        clrscr();
        return(1);
    }
    printf("\nWrite a number B=");
    if (scanf("%d", &val_b) != 1)
    {
        printf("I said number.\n");
        getch();
        clrscr();
        return(1);
    }

    result = val_a + val_b;
    printf("%d + %d = %d\n", val_a, val_b, result);
    getch();
    clrscr();
    return(0);
}

When you've learned about writing functions, you might compress that to:

#include <stdio.h>
#include <conio.h>

static int get_a_number(const char *prompt)
{
    int value;
    printf(prompt);
    if (scanf("%d", &value) != 1)
    {
        printf("I said number.\n");
        getch();
        clrscr();
        exit(1);
    }
    return value;
}

int main(void)
{
    int val_a  = get_a_number("Write a number A=");
    int val_b  = get_a_number("Write a number B=");
    int result = val_a + val_b;
    printf("%d + %d = %d\n", val_a, val_b, result);
    getch();
    clrscr();
    return(0);
}

The get_a_number() function is not a general purpose function, but it is useful in this context since it encapsulates a common piece of code.

  • A subroutine call permits us to summarize the irregularities in the argument list.
  • The subroutine itself summarizes the regularities of the code.

That's a quote from Kernighan & Plauger, "The Elements of Programming Style".


Using atexit()

The code above was updated to include getch() and clrscr() on all exit paths (and to remove #include <ctype.h> since none of the functions from it were used any more). It's a nuisance to write out the two function calls repeatedly. Another way to avoid that problem is to write a function that is called when the program exits; you register it with the atexit() function, which is declared in <stdlib.h>:

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

static void wait_at_exit(void)
{
    getch();
    clrscr();
}

static int get_a_number(const char *prompt)
{
    int value;
    printf(prompt);
    if (scanf("%d", &value) != 1)
    {
        printf("I said number.\n");
        exit(1);
    }
    return value;
}

int main(void)
{
    atexit(wait_at_exit);
    int val_a  = get_a_number("Write a number A=");
    int val_b  = get_a_number("Write a number B=");
    int result = val_a + val_b;
    printf("%d + %d = %d\n", val_a, val_b, result);
    return(0);
}

That code in main() assumes you can mix statements (such as atexit()) and declarations (such as int val_a) arbitrarily. That is permitted by both the current (2011) and old (1999) versions of Standard C, but was not permitted by the original (1989) version of Standard C. I believe MSVC adheres to the original standard. If so, you probably need to write that main() as:

int main(void)
{
    atexit(wait_at_exit);
    {
    int val_a  = get_a_number("Write a number A=");
    int val_b  = get_a_number("Write a number B=");
    int result = val_a + val_b;
    printf("%d + %d = %d\n", val_a, val_b, result);
    }
    return(0);
}

It is a fine discussion point whether the code inside the inner block (the inner braces) should be indented an extra level or not. You're always allowed to declare variables at the start of a block of code enclosed in braces, so that allows me write the call to atexit() and then define and use those variables.

If you read about Agile programming, you'll find that one of the mantras is:

  • DRY — Don't Repeat Yourself

The rewrites above to avoid the repeated getscr() calls could be considered an application of that mantra. Similarly with the get_a_number() function; it to applies the DRY mantra.


Trying again

If you want the program to go back and prompt again if the user makes a mistake in their typing, then you need to modify the get_a_number() function. And, because the function grows considerably more complex, you definitely need to be using a function for the job. You also run into a problem with scanf(); it doesn't allow you to enforce one number per line. If you typed 1 2 in response to the first prompt, the first call to get_a_number() would read the one and the blank, stop parsing (and put the blank back for reuse), and return with the value 1. The second call to get_a_number() would output the prompt but return with the value 2 without the user typing anything more. If that's not the behaviour you want, then you have to arrange to read the whole first line and scan for the number, and then discard the rest. There's another reason for worrying too. If the user types a instead of 1, the scanf() will never read anything more; it will go into a loop, finding that the a is not valid as a digit, returning 0 conversions complete, and your code will probably end up in an infinite loop, prompting for input and reading the a. This sort of problem is why many people (particularly me) avoid using scanf().

The simplest way to avoid most of the problems above is with fgets() and sscanf():

enum { MAX_LINELENGTH = 4096 };
enum { MAX_ATTEMPTS   = 10   };

static int get_a_number(const char *prompt)
{
    int value;
    char line[MAX_LINELENGTH];
    int count = 0;
    while (fputs(prompt, stdout) != EOF &&
           fgets(line, sizeof(line), stdin) != 0)
    {
        if (sscanf(line, "%d", &value) == 1)
            return value;
        if (count++ > MAX_ATTEMPTS)
        {
            printf("I give in; I don't understand what you're typing\n");
            exit(1);
        }
        printf("I said please enter a number.\n");
    }

    printf("Oops: I got EOF or an error; goodbye!\n");
    exit(1);
}

That covers quite a lot of issues. Often, it is a good idea to echo back the erroneous data. You could do that with:

        printf("I didn't understand what you meant when you typed:\n%s\n"
               "I said please enter a number.\n", line);

This uses 'adjacent string concatenation', and shows the user what the program received, which can often help the user understand what's wrong.

I used fputs(prompt, stdout) instead of printf(prompt) to output the prompt. Either could be used (printf(prompt) != 0 would be the test), but there is a slight advantage to fputs() because if someone managed to subvert your program and get a % into the prompt, the printf() would try to process an argument it was not passed, whereas fputs() does not interpret its argument string at all. Here, the difference is negligible; it can reasonably be argued that I'm over-complicating things. But the security of programs is also something you end up learning, and techniques such as "do not use printf(variable)" can help make your programs more resilient. (Actually, the complication is the explanation; the code is quite simple.)

Another detailed discussion point is 'should there be a fflush() after fputs() and before fgets()?' It would be possible to add the extra 'condition' fflush(stdout) == 0 && to the loop control, but in practice it is usually unnecessary. It would only make a difference if standard input was coming from something other than the terminal and standard output was going to a file. So, I left it out.

The counter in the loop prevents things going badly awry — the program exits rather than hang around forever, frustrating the user who can't get the data entered correctly. Have you ever had a program pop up a dialog box at which you can only hit the 'OK' button (even though its not OK) and then come back with the same box again, over and over and over again? I hope not for your sake. I have; it frustrates me when it happens.

And you can see why it is advantageous to write the code in get_a_number() just once, rather than twice; that would be a lot of repetition.

这篇关于检查,如果输入是一个数字,如果不是返回到输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆