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()常犯錯誤


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM