------------------------------------------------------------------------ <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); 使用這個參數,你可以完成許多強大的功能呦!
引用: