目錄
1、printf()函數
1.1、printf()函數中的標記
1.2、輸出最小寬度(width)
1.3、精度(.precision)
2、scanf()函數
2.1、scanf(“輸入控制符”, 輸入參數)
2.2、scanf(“輸入控制符非輸入控制符”, 輸入參數);
2.3、字符串和轉義字符
2.4、注意事項
1、printf()函數
printf()函數是C語言標準輸出函數,用于將格式化后的字符串輸出到標準輸出(對應終端的屏幕)。使用printf函數需要聲明在頭文件#include<stdio.h>
下。
認識一個函數先了解它的原型
int printf ( const char * format, ... );
返回值:正確返回輸出的字符總數,錯誤返回負值。
那怎么調用printf()函數呢?調用格式:
printf("格式化字符串", 輸出表列)
格式化字符串包含三種對象,分別為:
(1)字符串常量;
(2)格式控制字符串;
(3)轉義字符。
字符串常量原樣輸出,在顯示中起提示作用。輸出表列中給出了各個輸出項,要求格式控制字符串和各輸出項在數量和類型上應該一一對應。其中格式控制字符串是以 % 開頭的字符串,在 % 后面跟有各種格式控制符,以說明輸出數據的類型、寬度、精度等。后面將詳細介紹字符串。
printf() 的格式控制字符串組成如下:
%[flags][width][.prec][length]type
%[標志][最小寬度][.精度][類型長度]類型
上面五個選項中,類型是必不可少的,type用于規(guī)定輸出數據的的類型。下表列出一些轉換說明和各自對應的輸出類型。
轉換說明 | 輸出 | 示例 |
%a | 浮點數、十六進制數和p記數法 (C99/C11) | printf("%a",3.14);輸出0x1.91eb851eb851fp+1 |
%A |
浮點數、十六進制數和p記數法 (C99/C11) | printf("%A",3.14);輸出0X1.91EB851EB851FP+1 |
%c | 單個字符 | printf("%c",a);輸出字符a |
%d | 有符號十進制整數 | printf("%d",10);輸出十進制數字10 |
%e | 浮點數,e記數法 | printf("%e",3.14e10);輸出3.140000e+10 |
%E | 浮點數,e 記數法 | printf("%E",3.14e10);輸出3.140000E+10 |
%f | 浮點數,十進制記數法 | printf("%f",3.14);輸出浮點數3.14 |
%g | 根據值的不同,自動選擇%f 或%e。%e 格式用于指數小于-4 或者大于或等于精度時 | printf("%g",0.00000123);輸出1.23e-07 printf("%g",0.123);輸出0.123 |
%G | 根據值的不同,自動選擇%f 或%E。%E 格式用于指數小于-4 或者大于或等于精度時 | printf("%G",0.00000123);輸出1.23E-07 printf("%G",0.123);輸出0.123 |
%i | 有符號十進制整數(與%d 相同) | printf("%i",123);輸出123 |
%o | 無符號八進制整數 | printf("%o",12);輸出14 |
%p | 指針 | printf("%p","hello");輸出00B07B30 |
%s | 字符串 | printf("%s","hello");輸出hello |
%u | 無符號十進制整數 | printf("%u",123);輸出123 |
%x | 無符號十六進制整數,使用十六進制數 0f | printf("%x",123);輸出0x7b |
%X | 無符號十六進制整數,使用十六進制數 0F | printf("%X",123);輸出0x7B |
%% | 打印一個百分號 | printf("%%");輸出% |
其中有一些我們在之前就有接觸過(%d,%c,%u等等),這里并不是全部,但以上這些是比較常用的,希望讀者可以多加練習從而記住。
1.1、printf()函數中的標記
標記 | 含義 |
- | 待打印項左對齊。即,從字段的左側開始打印該項項 |
+ | 有符號值若為正,則在值前面顯示加號:若為負,則在值前面顯示減號 |
空格 | 有符號值若為正,則在值前面顯示前導空格(不顯示任何符號): 若為負,則在值前面顯示減號+標記覆蓋一個空格 |
# | 把結果轉換為另一種形式。如果是%o格式,則以0開始: 如果是%x或X格式,則以0x或 0X開始:對于所有的浮點格式,#保證了即使后面沒有任何數字,也打印一個小數點字符。對于%q 和%G 格式,#防止結果后面的 0被刪除 |
0 | 對于數值格式,用前導0代替空格填充字段寬度。對于整數格式,如果出現-標記或指定精度,則忽略該標記 |
這里附上我當時學習的代碼和運行截圖:
1.2、輸出最小寬度(width)
用十進制整數來表示輸出的最少位數。若實際位數多于指定的寬度,則按實際位數輸出,若實際位數少于定義的寬度則補以空格或0。width的可能取值如下:
width | 描述 | 示例 |
---|---|---|
數值 | 十進制整數 | printf("%06d",1000);輸出:001000 |
* | 星號。不顯示指明輸出最小寬度,而是以星號代替,在printf的輸出參數列表中給出 |
printf("%0*d",6,1000); 輸出:001000 |
1.3、精度(.precision)
精度格式符以“.”開頭,后跟十進制整數??扇≈等缦拢?/p>
.precision | 描述 |
.數值 | 進制整數。 (1)對于整型(d,i,o,u,x,X),precision表示輸出的最小的數字個數,不足補前導零,超過不截斷。 (2)對于浮點型(a, A, e, E, f ),precision表示小數點后數值位數,默認為六位,不足補后置0,超過則截斷。 (3)對于類型說明符g或G,表示可輸出的最大有效數字。 (4)對于字符串(s),precision表示最大可輸出字符數,不足正常輸出,超過則截斷。 precision不顯示指定,則默認為0 |
.* | 以星號代替數值,類似于width中的*,在輸出參數列表中指定精度 |
在 printf() 的實現中,在調用 write 之前先寫入 IO 緩沖區(qū),這是一個用戶空間的緩沖。系統(tǒng)調用是軟中斷,頻繁調用,需要頻繁陷入內核態(tài),這樣的效率不是很高,而 printf 實際是向用戶空間的 IO 緩沖寫,在滿足條件的情況下才會調用 write 系統(tǒng)調用,減少 IO 次數,提高效率。
可以參考一下我之前寫的則篇博客:printf函數輸出問題_sakura0908的博客-CSDN博客
之前說過,大部分C函數都有一個返回值,這是函數計算并返回給主調程序的值??梢园逊祷刂蒂x給一個變量,也可以用于計算,還可以作為參數傳遞??傊梢韵肫渌狄粯邮褂?。
printf()函數也有一個返回值,它返回打印字符的個數,不知道這個函數值的意義的話,當我們做C語言相關題目的時候總會寫錯。這里給讀者一個很經典的測試案例,看一下讀者能否得出正確結果
int main()
{
int A=43;
printf("%d\n",printf("%d",printf("%d",A)));
}
同一段代碼,可能有些人得出的結果是不一樣,但通過運行代碼,通過系統(tǒng)獲得的答案是4321,有可能和讀者心目中的答案不一樣,現在我們來剖析一下這段代碼的結果,為什么是4321呢?
前面講述了printf()函數的返回值是打印字符的個數,而且函數返回值也可以作為函數參數。結合下圖應該就很容易理解了。
?
2、scanf()函數
學完printf()函數,接下來學習scanf()函數,scanf()函數是C語言標準輸入函數,通過鍵盤給程序中的變量賦值。使用scanf函數需要聲明在頭文件#include<stdio.h>
下。scanf函數返回成功讀取的項數。
scanf函數的原型:
int scanf(const char *format, ...);
scanf函數的使用格式:
1、scanf(“輸入控制符”, 輸入參數);
2、scanf(“輸入控制符非輸入控制符”, 輸入參數);
2.1、scanf(“輸入控制符”, 輸入參數)
功能:將從鍵盤輸入的字符轉化為“輸入控制符”所規(guī)定格式的數據,然后存入以輸入參數的值為地址的變量中
int main(void)
{
int input;
input = 10;
printf("input = %d\n", input);
//希望在程序里面可以修改input的值,就需要用到scanf函數
scanf("%d", &input);
printf("input = %d\n", input);
return 0;
}
?
“輸入控制符”和“輸出控制符”是一模一樣的。?比如一個整型數據,通過 printf 輸出時用%d
輸出,通過?scanf 輸入時同樣是用%d。怎么理解scanf函數這一行的代碼呢?
首先要理解的是從鍵盤輸出的全部都是字符,比如從鍵盤輸入123,它表示的并不是數字123,而是字符'1'、字符'2'和字符'3'。操作系統(tǒng)內核就是這樣操作的,操作系統(tǒng)在接受鍵盤數據時都將它當成字符來接收的。這時就需要“輸入控制符”將它轉化一下。%d的含義就是要將從鍵盤輸入的這些合法的字符轉化成一個十進制數字。經過 %d 轉化完之后,字符 123 就是數字 123 了。然后就要理解&這個符號是什么,&是一個取地址運算符,&后面加變量名表示“該變量的地址”,所以&input就表示變量input的地址。&input又稱為“取地址input”,就相當于將數據存入以變量input的地址為地址的變量中。
ok,現在返回來看一下上面代碼的scanf函數的用法,這句語句的意思就是:從鍵盤上輸入字符 30,然后%d
將這兩個字符轉化成十進制數 30,最后通過 “取地址 input” 找到變量 input?的地址,再將數字 30放到以變量 input 的地址為地址的變量中,即變量 input 中,所以最終的輸出結果就是input=30
。
注意:
為什么不直接說“放到變量input中”?而是說“放到以變量input的地址為地址的變量中”?因為這么說雖然很繞口,但是能加強對 &input 的理解,這么說更能表達 &input的本質和內涵。很多人在學習 scanf 的時候,經常將“變量 i”和“變量 i 的地址”混淆,從而思維開始混亂,等深刻了解 &i 的含義之后就可以不那么說了。
2.2、scanf(“輸入控制符非輸入控制符”, 輸入參數);
這種用法現在應該是很少人使用或者基本就沒人使用,但是總有頭鐵的人使用。經常有人問,為什么 printf 中可以有“非輸出控制符”,而 scanf 中就不可以有“非輸入控制符”。事實上不是不可以有,而是沒有必要!
int main(void)
{
int input;
scanf("input = %d", &input);
printf("input = %d\n", input);
return 0;
}
在 printf 中,所有的“非輸出控制符”都要原樣輸出。同樣,在 scanf 中,所有的“非輸入控制符”都要原樣輸入。所以在輸入的時候,input=
?必須要原樣輸入。比如要從鍵盤給變量 input賦值 30,那么必須要輸入input=123
才正確,少一個都不行,否則就是錯誤。
在使用scanf函數的時候,沒有必要加\n,因為scanf中\(zhòng)n不起換行的作用,它不但什么作用都沒有,我們還要原樣將它輸入一遍。
scanf函數允許一次給多個變量賦值。通過鍵盤給多個變量賦值與給一個變量賦值其實是一樣的。比如給兩個變量賦值就寫兩個?%d
,然后“輸入參數”中對應寫上兩個 “取地址變量” ;給三個變量賦值就寫三個?%d
,然后“輸入參數”中對應寫上三個 “取地址變量” 。
雖然 scanf 中沒有加任何“非輸入控制符”,但是從鍵盤輸入數據時,給多個變量賦的值之間一定要用空格、回車或者 Tab 鍵隔開,用以區(qū)分給不同變量賦的值。而且空格、回車或 Tab 鍵的數量不限,只要有就行。一般都使用一個空格。
當用 scanf 從鍵盤給多個變量賦值時,scanf 中雙引號內多個“輸入控制符”之間千萬不要加逗號。
最后重要的事情講三次!scanf“輸入參數”的取地址符&
千萬不要忘了!scanf“輸入參數”的取地址符&
千萬不要忘了!scanf“輸入參數”的取地址符&
千萬不要忘了!初學者很容易忘記這個符號,從而導致程序有問題,但是要記住printf函數的“輸出參數”是不帶取地址符的。
2.3、字符串和轉義字符
字符串是一個或多個字符的序列,比如:“hello world”。
雙引號不是字符串的一部分。雙引號僅告知編譯器它括起來的是字符 串,正如單引號用于標識單個字符一樣。
C語言沒有專門用于儲存字符串的變量類型,字符串都被儲存在char類型的數組中。數組由連續(xù)的存儲單元組成,字符串中的字符被儲存在相鄰的存儲單元中,每個單元儲存一個字符。
?數組末尾位置的字符\0。這是空字符。C 語言用它標記字符串的結束??兆址皇菙底?,它是非打印字符,其ASCII 碼值是(或等價于)0。C中的字符串一定以空字符結束,這意味著數組的容量必須至少比待存儲字符串中的字符數多1。字符串看上去比較復雜!必須先創(chuàng)建一個數組,把字符串中的字符逐個放入數組,還要記得在末尾加上一個\0。還好,計算機可以自己處理這些細 節(jié)。
那么,什么是數組?可以把數組看作是一行連續(xù)的多個存儲單元。用更正式的說法是,數組是同類型數據元素的有序序列。后面會詳細探討。
如何利用printf函數和scanf函數輸出輸入字符串呢?輸入控制符和輸出控制符都是%s。
%s告訴printf()打印一個字符串,%s告訴scanf()要接收一個字符串類型數據,我們不用把空字符放入字符串末尾,scanf()在讀取輸入時就已完成這項工作。注意,scanf函數在遇到第一個空白(空格、制表符或換行符)時就不再讀取輸入,如果我們要輸入帶有空格的字符串是不能使用scanf函數的,需要用到其他輸出函數,后面再講這些,scanf函數其實已經滿足我們初學者大部分的需求
字符串與字符
字符串常量"x"和字符常量'x'不同。區(qū)別之一在于'x'是基本類型 (char),而"x"是派生類型(char數組);區(qū)別之二是"x"實際上由兩個字符組成:'x'和空字符\0。通過下圖更好的理解:
?在初次認識字符串的時候必不可少要認識的就是strlen這個字符串相關函數
strlen函數的原型:
size_t strlen ( const char * str );
strlen函數作用:計算字符串?str?的長度,直到空結束字符,但不包括空結束字符。
這個函數的作用好像和關鍵字sizeof的作用很相似,但實際上是有很大的區(qū)別的,下面來一個測試案例來直觀的認識這一點:
?對于我們手動輸入的字符串hello,兩種方式得出的結果卻不相同,這是為什么呢?sizeof就是一個計算數據類型所占空間大小的單目運算符,在計算字符串的空間大小時,包含了結束符\0的位置;而strlen是一個計算字符串長度的函數,使用時需要引用頭文件#include <string.h>,不包含\0,即計算\0之前的字符串長度。
當我們使用printf函數輸出一些字符串的時候,會發(fā)現一些“錯誤”情況,例如:
會發(fā)現我們預想的情況對比實際情況少了一個\和\t,這是為什么呢?
這是因為有轉義字符的存在,轉義字符顧名思義就是轉變意思。轉義字符以\
或者\x
開頭,以\
開頭表示后跟八進制形式的編碼值,以\x
開頭表示后跟十六進制形式的編碼值。對于轉義字符來說,只能使用八進制或者十六進制。
轉義字符 | 意義 | 示例 |
\a | 響鈴 | printf("\a");電腦發(fā)出蜂鳴 |
\b | 退格,將當前位置移到前一列 | printf("123\b");輸出12 |
\f | 換頁,將當前位置移到下頁開頭 | 無 |
\n | 換行,將當前位置移到下一行開頭 | printf("123\n");輸出123換行 |
\r | 回車,將當前位置移到本行開頭 | printf("123\r456");輸出456 |
\t | 水平制表 | printf("\t123");輸出8個空格123 |
\v | 垂直制表 | 無 |
\\ | 反斜杠 | printf("\\");輸出\ |
\' | 單引號 | printf("\'");輸出‘ |
\" | 雙引號 | printf("\”");輸出“ |
\? | 問號 | printf("\?");輸出? |
\0oo | 八進制(oo必須是有效的八進制數,即每個o可表示0~7中的一個數) | printf("\077");輸出?(?的ASCll值為63) |
\xhh | 十六進制(hh必須是有效的十六進制數,即每個h可表示0~f中的一個數) | printf("\x3f");輸出? |
2.4、注意事項
1、參數的個數一定要對應
和printf函數一樣的,“輸出控制符” 和 “輸出參數” 無論在 “順序上” 還是在 “個數上” 一定要一一對應。這句話同樣對 scanf 有效,即 “輸入控制符” 和 “輸入參數” 無論在 “順序上” 還是在 “個數上” 一定要一一對應。
2、輸入的數據類型一定要與所需要的數據類型一致
在 scanf 中,對于從鍵盤輸入的數據類型、scanf中“輸入控制符”的類型、變量定義的類型,這三個類型一定要一致,否則就是錯的。雖然編譯的時候不會報錯,但從程序功能的角度講就是錯的,則無法實現我們需要的功能。
寫一個小案例測試一下:
?
?但是,很明顯我們是輸入了a的,為什么變量卻顯示未初始化呢?
在 scanf 中,從鍵盤輸入的一切數據,不管是數字、字母,還是空格、回車、Tab 等字符,都會被當作數據存入緩沖區(qū)。
存儲的順序是先輸入的排前面,后輸入的依次往后排。按回車鍵的時候 scanf 開始進入緩沖區(qū)取數據,從前往后依次取。
但 scanf 中 %d 只識別“十進制整數”。對 %d 而言,空格、回車、Tab 鍵都是區(qū)分數據與數據的分隔符。當 scanf 進入緩沖區(qū)中取數據的時候,如果 %d 遇到空格、回車、Tab 鍵,那么它并不取用,而是跳過,繼續(xù)往后取后面的數據,直到取到“十進制整數”為止。對于被跳過和取出的數據,系統(tǒng)會將它從緩沖區(qū)中釋放掉。未被跳過或取出的數據,系統(tǒng)會將它一直放在緩沖區(qū)中,直到下一個 scanf 來獲取。
但是如果 %d 遇到字母,那么它不會跳過也不會取用,而是直接從緩沖區(qū)跳出。所以上面這個程序,雖然 scanf 進入緩沖區(qū)了,但用戶輸入的是字母 a,所以它什么都沒取到就出來了,而變量 input 沒有值,即未初始化,所以輸出就是 –858993460。
但如果將 %d 換成 %c,那么任何數據都會被當作一個字符,不管是數字還是空格、回車、Tab 鍵它都會取回。
3、使用 scanf 之前使用 printf 提示輸入文章來源:http://www.zghlxwxcb.cn/news/detail-758777.html
程序寫好之后,編譯、鏈接、執(zhí)行,然后彈出運行窗口,出現一個光標在那不停地閃。對于編寫程序的人來說他知道要輸入什么,但是對于用戶而言,用戶怎么知道是什么意思呢?所以之前的程序都缺少提示信息!因此在使用scanf之前,最好先用printf提示用戶以什么樣的方式輸入,這樣可以大大提高代碼的質量。文章來源地址http://www.zghlxwxcb.cn/news/detail-758777.html
到了這里,關于C語言入門篇——輸入輸出篇的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!