scanf()常犯错误

------------------------------------------------------------------------
<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()常犯错误

时间: 2024-11-07 05:19:35

scanf()常犯错误的相关文章

web前端常犯错误集锦

html部分 1.head中不加doctype的类型,会导致浏览器兼容性的问题 2. id用数字来表示 3.文件编码与meta规定的charset不一致 Mysql部分 Mysql两个常见引擎 ,区别 1.MyIsAM 我的理解是作为只读表,则使用该引擎,该引擎对查询有优化,并且改善了索引树的空间利用率:该引擎没有事务的控制:不太容易发生死锁 2.InnoDB 事务表引擎,保证事务的完整性:如果该表更新频繁,则使用该表引擎:如果数据量巨大,也应该使用该表引擎,并且有自己的缓冲池: 容易发生死锁

Python 新手常犯错误

Python 新手常犯错误(第二部分) 转发自:http://blog.jobbole.com/43826/ 作用域 在这篇文章里,我们来关注作用域在Python被误用的地方.通常,当我们定义了一个全局变量(好吧,我这样说是因为讲解的需要——全局变量是不好的),我们用一个函数访问它们是能被Python理解的: 1 2 3 bar = 42 def foo():     print bar 在这里,我们在foo函数里使用了全局变量bar,然后它也如预想的能够正常运行: 1 2 >>> fo

女性求职常犯错误你中枪了吗?

在郴州找工作的求职群中,女性也占据了主要地位.但是,女性在这个社会上貌似不是那么好找工作.在女性的观念里,她们往往很容易地认为她们的成就和技术不如男人,她们常常没有足够的信心来相信和认知自己的能力,小编身边有女性朋友也存在着一些对性别求职的错误理解.如果你是女性,你在求职时是否也犯了以下这些常见的错误? 一.不相信自己是优秀的 这个是女性最常犯的一个错误认知,以前遇到过一个在餐厅做服务员的女士,她用自己的劳动养活了自己以及他的家庭,但是当我问她,你是否觉得自己是个职场女性,她连忙否决,觉得自己只

【小编亲历】10个新手UI设计师常犯错误,小编已中招,你呢?

以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 新手入坑,难免会做蠢事,犯错误.当初,作为UI设计新手菜鸟的小编, 也没少犯错误,走弯路.所以,小编这里为大家分享10个当初常犯的设计错误,希望能够帮助刚入行的小伙伴们尽量少走一些弯路. 接下来我们就一起看看都有哪些坑吧: 1.从未归类整理设计文件和资料 事实上,在最初开始UI设计阶段,小编根本就不知道:设计相关文件资料是需要从一开始就打包分类整理,以确保其他团队成员能够随时查看和取用. 而且重点

C语言常犯错误

语言的最大特点是:功能强.使用方便灵活.C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误.看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考. 1.书写标识符时,忽略了大小写字母的区别. main() { int a=5; printf("%d",A); } 编译程序把a和A认为是两个不同

缺乏经验的管理者有哪些常犯错误?

这个问题源自国外网友在Quora上的提问.亚马逊 AmazonSmile 的总经理 lan McAllister 在 Quora 上对这个的回答,他列举了他初当管理者时犯的错误,或者是看到其他新任的管理者所犯的一些错误,并分享如何去避免这些问题. 下面是我初当管理者时犯的一些错误,或者是看到其他新任的管理者犯的错误.经验丰富的管理者仍然会犯一些这样的错误,然而有望少一些: 一.绩效管理 1. 处理绩效问题不及时-问题出现便一发不可收拾.早一点注意到绩效问题,你会给出善意的纠正性反馈.如果你没有及

扩展欧几里得算法(extended Euclidean algorithm)的一个常犯错误

1 int exGcd(int x,int y,int& a,int& b) //ax+by=gcd(x,y) 2 { 3 if(!y) { a=1; b=0; return x; } 4 int res=exGcd(y,x%y,a,b); 5 int t=a; a=b; b=t-x/y*b; 6 return res; 7 } int exGcd(int x,int y,int& a,int& b) //ax+by=gcd(x,y) { if(!y) { a=1; b=0

新手产品常犯错误

一个完整的迭代期,基本流程是 收集需求-->分析需求-->确定迭代期目标-->开发-->测试-->发布 1.忽视文档 好好写文档,很重要!尤其初次合作,大家没默契. 协作同步  Google Doc 2.迷恋UI细节 应该先想好核心功能,满足用户需求,快速发布,听取意见,然后迭代更新 ---- NB的产品经理,在于对人性的把握 界面,交互等,是相对容易学习的. 用户需求,了解人性,才是产品经理最核心的技能.

android常犯错误记录(二)

检查 minSdkVersion什么的是不是和你依赖的包一样,它上面也有个小提示,显示本地的11,依赖的为15,那就改成15好了,重新build好了