scanf

在学习C语言的时候,printf()是我们学到的第一个函数,相信“hello world”这个例子大家都不会陌生吧,接着就是scanf()这个函数了,这个函数的功能是格式输入,它的函数原型是:

  int scanf(const char *format,⋯);

  这个函数的基本用法这里就不说了,这里介绍一些这个函数使用中常见的问题及解决方法:

  第一,连续输入两个或多个字符的时候,第二次输入直接跳过了如:

  int main()

  {

  char a,b;

  scanf(“%c”,&a);

  scanf(“%c”,&b);

  return 0;

  }

  输入 a回车 然后就退出了。

  这个问题有很多说法有说是缓冲区没有清除,有说stdin这个流的问题,这里我们不去追究,这里介绍几个解决这种问题的方法:

  int main()

  {

  char a,b;

  scanf(“\n%c”,&a);

  scanf(“\n%c”,&b);或 scanf(“ %c”,&b);%c前有空格

  return 0;

  }

  这次再编译一下就没有问题了。

  第二,使用scanf()函数输入一句话的时候,如:

  int main()

  {

  char string[50] ;

  scanf(“%s”,string);

  printf(“%s\n”,string);

  return 0;

  }

  输入:hello world!

  结果:hello

  显然这个结果没有达到我们的要求。

  解决方法:

  int main()

  {

  char string[50] ;

  scanf(“%[^\n]”,string);

  printf(“%s\n”,string);

  return 0;

  }

  重新编译一下,没有问题了吧!

  这里如果要是连续输入多个语句的话也会出现连续输入字符的那种问题,当然解决方法也相同了。

  这里是最常见的几个问题,可能还有其他的解决方法,希望和大家相互交流,能力有限有问题希望大家多多指教。

  “本文由华清远见http://www.embedu.org/index.htm提供”

<1>        本意:接收字符串. 
       写成代码:void main()
                 {
                 char *str;
                 scanf("%s",str);
                 printf("string is: %s\n",str);
                 }
   符合愿意代码:char *str=NULL;
                 str=malloc(128*sizeof(char) );
                 scanf( "%s\n", str );
           点评:指针需要你手动给它分配空间,并手动指向该空间如果没有,指针指向哪里,是不确定的
                 也就是说,你scanf得到的数据存放到哪里是不一定的因此,偶尔有运行正常是你运气好
                 错误才是正常的 
-----------------------------------------------------------------------
<2>        本意:接收输入的a,b值. 
       写成代码:int a,b;
                 scanf("%d%d",a,b);
   符合愿意代码:int a,b;
                 scanf("%d%d",&a,&b);
           点评:这是不合法的。Scanf函数的作用是:按照a、b在内存的地址将
                 a、b的值存进去。“&a”指a在内存中的地址。
------------------------------------------------------------------------
<3>        本意:在Input字符串后输入数值. 
       写成代码:int num;
                 Scanf("Input %d", & num);
     实际应输入:Input 1234 或者 Input1234
   符合愿意代码:int num;
                 printf("Input";
                 scanf("%d",&num);
------------------------------------------------------------------------  
<4>        本意:接收填入的数据. 
       写成代码:#include <stdio.h>
                 main()
                {
                 int num;
                 printf("please input the student's score: ";
                 scanf("%d",&num);

                 if((num<0)||(num>100))
                 {
                      printf("The score put isnt fine. please run and input again.";
                 }
                 else if(num>90)
                 {
                      printf("The grade is A.";
                 }
                
                 else if((num>80)&&(num<90))
                 {
                     printf(..................
                     .............
                 }
                 ..............
                        
                 }
     实际应输入:这个程序是没错,不过如果有人要存心捣乱, 输入时不是输入数字,而是其
                 他的什么字符,那么congratulations,这个程序崩溃掉了.
   符合愿意代码:#include <stdio.h>
                 main()
                {
                 int num,int result=0;
                 printf("please input the student's score: ";
                  
                 while(result==0)
                {
                 fflush(stdin);  /*  清空输入缓冲区. */
                 if(result!=1)printf("lease input a digital score: ";
                 result=scanf("%d",&num);  
                }
                ............................
                }
           点评:scanf函数执行成功时的返回值为成功读取的变量数,如果第一个变量的读取既告失败则返回值为0.   
                 我们可以通过判断scanf函数执行的返回值,  可以制止用户不正确地输入,从而控制程序的流程.
           另 :#include <stdio.h>
                 int main()
                {
                       char b[2];
                       scanf("%s", b);
                       printf("%s\n", b);
                }
                如果输入的字符比较多例如10个,就会seg fault,可见scanf是不安全的,没有检查缓冲区。
                同样,把上面的scanf换成gets,效果是一样的。(而且编译的时候有warning,不让用gets)。
                fgets是安全的,这样用法:
                fgets(b, 2, stdin);
                注意,这样子其实只读了一个字符,第二个字符是0。所以如果输入是sad,则b[0]='s', b[1]=0.
                由此可见,读入字符串时,fgets更安全。
------------------------------------------------------------------------                     
<5>        本意:接收带空格等的字符串. 
       写成代码:#include <stdio.h>
                 void main(){
                 char c[100];
                 scanf("%s", c);
                 printf("%s", c);
                 }
           输入:welcome to come here
           输出:welcome
   符合愿意代码:换用gets();
           点评:因为输入终端的buffer把空白字符(包括空格。\t等)当成字符串分隔符,
                 你用过命令行参数就明白了,main函数的参数是 int main(int,char*[])
------------------------------------------------------------------------  
<6>        本意:接收规定精度的数据. 
       写成代码:scanf("%7.2f",&a);
     实际应输入:
   符合愿意代码:
           点评:这样做是不合法的,输入数据时不能规定精度。
------------------------------------------------------------------------  
<7>        本意:正确输入a,b的值. 
       写成代码:#include <stdio.h>
                 int main()
                 {
                  int a,b,c;  /*计算a+b*/
                  scanf("%d,%d",&a,&b);
                  c=a+b;
                  printf("%d+%d=%d",a,b,c);
                 }
           现象:一旦输入了错误的类型,程序不是死锁,就是得到一个错误的结果。
   符合愿意代码:#include <stdio.h>
                 int main()
                {
                 int a,b,c;  /*计算a+b*/
                 while(scanf("%d,%d",&a,&b)!=2)fflush(stdin);
                 c=a+b;
                 printf("%d+%d=%d",a,b,c);
                }
           点评:scanf()函数执行成功时的返回值是成功读取的变量数,也就是说,
                 你这个scanf()函数有几个变量,如果scanf()函数全部正常读取,
                 它就返回几。但这里还要注意另一个问题,如果输入了非法数据,
                 键盘缓冲区就可能还个有残余信息问题。
------------------------------------------------------------------------  
<8>        本意:可以连续多次接受数据. 
       写成代码:#include <stdio.h>
                 int main()
                 {
                    int a;
                    char c;
                    do
                    {
                        scanf("%d",&a);
                        scanf("%c",&c);
                        printf("a=%d     c=%c\n",a,c);
                        /*printf("c=%d\n",c);*/
                    }while(c!='N');
                 }
           现象:scanf("%c",&c);这句不能正常接收字符
   符合愿意代码:#include <stdio.h>
                 int main()
                 {
                    int a;
                    char c;
                    do
                   {   scanf("%d",&a);
                       fflush(stdin);
                        scanf("%c",&c);
                        fflush(stdin);
                        printf("a=%d     c=%c\n",a,c);
                    }while(c!='N');
                 }      
           点评:我们用printf("c=%d\n",c);将C用int表示出来,启用printf("c=%d\n",c);这一句,
                 看看scanf()函数赋给C到底是什么,结果是 c=10 ,ASCII值为10是什么?换行即\n.
                 对了,我们每击打一下"Enter"键,向键盘缓冲区发去一个“回车”(\r),一个“换行"
                 (\n),在这里\r被scanf()函数处理掉了(姑且这么认为吧^_^),而\n被scanf()函数
                “错误”地赋给了c.
             另:fflush(FILE *stream)函数,其主要功能:可将所有缓冲区数据写入指定的流文件将
                 清空缓冲区。
------------------------------------------------------------------------  
<9>        本意:接收float型数值. 
       写成代码:#include "stdio.h" 
                main() 
                { 
                 int i=0; 
                 struct BOOK 
                  { 
                     char bookName[100]; 
                     float bookPrice; 
                  }; 
                  struct BOOK book[10]; 
                  for(i=0;i<10;i++) 
                  { 
                      scanf("%f",&book[i].bookPrice); 
                  } 
                } 
           现象:  编译通过,但运行时报错(TC3.0): 
                   scanf : floating point formats not linked. 
                   Abnormal program termination 。 
   符合愿意代码:#include "stdio.h" 
                main() 
                { 
                  int i=0; 
                 float t=0; 
                 struct BOOK 
                 { 
                    char bookName[100]; 
                    float bookPrice; 
                  }; 
                  struct BOOK book[10]; 
                  for(i=0;i<10;i++) 
                  { 
                      scanf("%f",&t); 
                      book[i].bookPrice=t; 
                  } 
                } 
   相关参考资料:
Description: 
  This document explains why you might be getting the error 
  FLOATING POINT FORMATS NOT LINKED : ABNORMAL PROGRAM TERMINATION 
  and tells you how to resolve it.  The problems and solutions 
  below apply to ALL versions of Turbo C, Turbo C++, and Borland 
  C++, except where noted. 
  What are floating point formats? 
  Floating point formats are a collection of formatting information 
  used to manipulate floating point numbers in certain runtime 
  library functions such as scanf() and atof(). 
  When will this be fixed? 
  There are no current plans to fix this because it is not a bug. 
  The intent is to avoid linking the floating point formats (about 
  1K of overhead) when they are not required.  The tradeoff of this 
  feature is that the programmer must explicitly request that the 
  floating point formats to be linked in for some programs which 
  manipulate floats in a limited and specific fashion. 
  How do I resolve the error message? 
  Since you can get the error in a number of different ways, check 
  the following list of potential causes to find out how to resolve 
  the error.  These are listed in order of most common to least 
  common causes. 
  1.  CAUSE:  Floating point set to .  Your have your 
      floating point option set to None when it should be set to 
      either Emulation or 80x87. 
      FIX:  Set Floating Point to  or <80x87>.  In the 
      Integrated Development Environment (IDE), this is either 
      under Options | Compiler | Advanced Code Generation or 
      Options | Compiler | Code Generation | More, depending upon 
      which compiler you have.  With the command line compiler, use 
      the appropriate -f switch. 
  2.  CAUSE:  Misordered libraries when executing TLINK 
      (Cx.LIB listed before EMU.LIB will cause the error.) 
      FIX:  This possibility usually occurs only when you are using 
      the command line compiler and are explicitly calling TLINK 
      separately from BCC or TCC.  When executing TLINK, change the 
      order of the libraries to 
           [user libs] [GRAPHICS.LIB] EMU.LIB MATHx.LIB Cx.LIB 
                  (libraries in brackets are optional) 
      Note:  There is a misprint in the Borland C++ Tools & 
      Utilities Guide on page 58 that displays the wrong order for 
      libraries on the TLINK command line.  The ordering shown in 
      the manual is exactly what will cause floating point formats 
      not linked. 
  3.  CAUSE:  Either the compiler is overoptimizing, or the 
      floating point formats really do need to be linked in because 
      your program manipulates floats in a limited and specific 
      fashion.  Under certain obscure conditions, the compiler will 
      ignore floating point usage in scanf().  (e.g., trying to 
      read into a float variable that is part of an array contained 
      in a structure.) 
      FIX:  If you have Borland C++ 3.0 or later, read Part A.  If 
      you have Borland C++ 2.0 or any Turbo C or Turbo C++ 
      compiler, read Part B.  This fix is the only fix that will 
      solve a "RINTF : Floating point formats not linked" error 
      message occurring with inline assembly. 
      Part A (BC++ 3.0 or later): 
          Add the following to one source module: 
              extern _floatconvert; 
              #pragma extref _floatconvert 
          The README and HELPME!.DOC files that shipped with 
          Borland C++ 3.0 incorrectly say that only 
              #pragma extref _floatconvert 
          is required in order to resolve the FPFNL error.  If you 
          do not include the "extern _floatconvert;" line you will 
          get the error "Undefined symbol _floatconvert."  You will 
          also get the same undefined symbol if the "extern 
          _floatconvert" comes after the #pragma line instead of 
          before.  Note that the #pragma line does not have a 
          semicolon at the end of the line.  If you put a semicolon 
          there, you will get the error "Bad pragma directive 
          syntax." 
          The README that shipped with Borland C++ 3.1 says that 
              extern void _floatconvert(); 
              #pragma extref _floatconvert 
          This should work, as well.  It doesn't really matter 
          whether _floatconvert is a variable or a function; it 
          only matters that it is some symbol that the linker will 
          recognize. 
          The HELPME!.DOC for BC++ 3.1 has the correct two lines to 
          add. 
      Part B (BC++ 2.0 or TC or TC++): 
          Add the following force_fpf() function to one source 
          module.  It is not necessary to call this function; just 
          include it in one of your modules. 
          static void force_fpf() 
          { 
              float x, *y; /* Just declares two variables */ 
              y = &x;      /* Forces linkage of FP formats */ 
              x = *y;      /* Suppress warning message about x */ 
          } 
  4.  CAUSE:  Forgetting to put the address operator & on the scanf 
      variable expression.  For example, 
          float foo; 
          scanf("%f", foo); 
      FIX:  Change the code so that the & operator is used where it 
      is needed.  For example, the above code should be 
          float foo; 
          scanf("%f", &foo); 
  5.  CAUSE:  A bug in Turbo C 2.0 when using scanf() 
      FIX:  Obtain and apply the patches in TC2PAT.ARC.  This file 
      can be downloaded from the Languages / C++ / Patches section 
      on DLBBS (408-439-9096). 
  6.  CAUSE:  A bug in Turbo C 2.01 when using atof() or strtod() 
      FIX:  Obtain and apply the patches in TC21PT.ARC.  This file 
      can be downloaded from the Languages / C++ / Patches section 
      on DLBBS (408-439-9096). 
  7.  CAUSE:  You are trying to create a Phar Lap DOS Extender 
      application with the Integrated Development Environment 
      (IDE). 
      FIX:  Phar Lap includes an executable called BCC286.EXE with 
      their DOS Extender.  This program calls Borland's command- 
      line compiler (BCC) and command-line linker (TLINK).  Since 
      the linker in the IDE is different than the linker at the 
      command line, you cannot create Phar Lap DOS Extender 
      applications in the IDE and expect them to run properly.  If 
      you try to do so, you might get a floating point formats not 
      linked error message.  The fix is to use the command line 
      tools, BCC and TLINK, instead of the IDE. 
  Keywords:  FPFNL , APT 
  DISCLAIMER: You have the right to use this technical information 
  subject to the terms of the No-Nonsense License Statement that 
  you received with the Borland product to which this information 
  pertains. 
------------------------------------------------------------------------  
其他:   
   在scanf函数中,我们可以使用 %c来读取一个字符,使用 %s 读取一个字符串. 但是读取字
符串时不忽略空格,读字符串时忽略开始的空格,并且读到空格为止,因此我们只能读取一个单
词,而不是整行字符串.因此一般使用fgets来读取一个字符串.其实scanf函数也可完成这样的
功能,而且还更强大.
   这里主要介绍一个参数,%[ ] ,这个参数的意义是读入一个字符集合. [ ]是个集合的标
志,因此%[ ]特指读入此集合所限定的那些字符, 比如 %[A-Z] 是输入大写字母,一旦遇到不在
此集合的字符便停止. 如果集合的第一个字符是" ^ ", 这说明读取不在" ^ " 后面集合的字
符,既遇到" ^ " 后面集合的字符便停止.注意此时读入的字符串是可以含有空格的.
  Eg.  输入一个字符串, 这个字符串只含有小写字符.遇到第一个不是小写字符时停止.
      scanf("%[a-z],str);
  Eg.  想输入一个字符串, 遇到 "." 停止,可设计如下:
     scanf("%[^.]", str); 
    使用这个参数,你可以完成许多强大的功能呦!
------------------------------------------------------------------------------------------------------------------------
总结:  通常来讲,scanf函数和他的一些参数并不是很常用,主要是因为:
       1.许多系统的scanf函数都有漏洞. (典型的就是TC再输入浮点型时有时会出错).
       2.用法复杂,容易出错.
       3.编译器作语法分析时会很困难,从而影响目标代码的质量和执行效率.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值