0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

字符串的輸入輸出及相關(guān)函數(shù)

AGk5_ZLG_zhiyua ? 來(lái)源:未知 ? 作者:佚名 ? 2017-09-14 11:52 ? 次閱讀

周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》,電子版已無(wú)償性分享到電子工程師與高校群體,在公眾號(hào)回復(fù)【程序設(shè)計(jì)】即可在線閱讀。書本內(nèi)容公開(kāi)后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。經(jīng)周立功教授授權(quán),本公眾號(hào)特對(duì)本書內(nèi)容進(jìn)行連載,愿共勉之。

第一章為程序設(shè)計(jì)基礎(chǔ),本文為1.8.2 字符串常量第二點(diǎn):字符串的輸入輸出。

(1)scanf()函數(shù)和gets()函數(shù)

scanf()函數(shù)

在讀取字符串時(shí),scanf()和轉(zhuǎn)換格式符%s只能讀取一個(gè)單詞,比如:

scanf("%s\n", str);

在scanf函數(shù)調(diào)用中,不需要在str前添加&,因?yàn)閟tr是數(shù)組名,編譯器在將它傳遞給函數(shù)時(shí),會(huì)將它當(dāng)作指針來(lái)處理。調(diào)用時(shí),scanf函數(shù)會(huì)跳過(guò)空字符,然后讀入字符并存儲(chǔ)到str中,直到遇到空字符為止,scanf函數(shù)始終會(huì)在字符串末尾存儲(chǔ)一個(gè)空字符。

gets()函數(shù)

在程序中經(jīng)常要讀取一整行輸入,而不僅僅是一個(gè)單詞,gets()就是用于處理這種情況的。它讀取整行輸入直至遇到換行符,然后丟棄換行符存儲(chǔ)其余字符,并在這些字符的末尾添加一個(gè)空字符使其成為一個(gè)字符串。它經(jīng)常和puts()配對(duì)使用,該函數(shù)用于顯示字符串,并在末尾添加換行符。即gets()是從標(biāo)準(zhǔn)輸入設(shè)備中輸入若干個(gè)字符,并保存到參數(shù)s指向的字符數(shù)組中,直到文件結(jié)束或讀到一個(gè)換行符。換行符將被丟棄,在輸入最后一個(gè)字符后會(huì)立即寫入一個(gè)結(jié)束符'\0'。其函數(shù)原型如下:

char *gets(char *s);

其中的s指向保存輸入字符串的內(nèi)存空間,如果gets()成功地獲得了字符串,則返回s,否則返回NULL。比如,通過(guò)命令行輸入一個(gè)字符'9',但'9'不是整數(shù)9,如果將'9'-'0',則會(huì)得到整數(shù)9。即:

char cStr[256];

int cmdNum;

cmdNum = getchar() - '0';

gets(cStr); //清空緩沖區(qū)

如果將數(shù)組作為參數(shù)傳遞,則傳遞的是指向數(shù)組首元素的指針,當(dāng)gets()作為被調(diào)用函數(shù)時(shí),則完全不知道數(shù)組究竟有多大,而調(diào)用者又不能向gets()傳遞緩沖區(qū)的大小,因此gets()無(wú)法檢查數(shù)組的長(zhǎng)度。顯然必須有足夠的空間保存輸入的字符串,否則可能出現(xiàn)莫名其妙的問(wèn)題。如果你故意將尺寸很大的數(shù)據(jù)傳遞給gets(),就可以達(dá)到數(shù)組越界且改寫返回地址的目的。1988年名震互聯(lián)網(wǎng)的“互聯(lián)網(wǎng)蠕蟲(chóng)”病毒,就是利用了gets()的這個(gè)弱點(diǎn)。

由于gets()的不安全行為造成了隱患,因此制定C11標(biāo)準(zhǔn)的委員采取了強(qiáng)硬的態(tài)度,直接從標(biāo)準(zhǔn)中廢除了gets()函數(shù)。不妨自己編寫一個(gè)輸入函數(shù),假設(shè)函數(shù)不會(huì)跳過(guò)空字符,在第一個(gè)換行符(不存儲(chǔ)到字符串中)處停止讀取,且忽略額外的字符。其函數(shù)原型如下:

int readLine(char str[], int n);

readLine()函數(shù)主要由一個(gè)循環(huán)構(gòu)成,只要str中還有空間,此循環(huán)就會(huì)調(diào)用getchar()函數(shù)逐個(gè)讀入字符并將它存儲(chǔ)在str中,在讀入換行符時(shí)循環(huán)終止,詳見(jiàn)程序清單 1.40。

程序清單 1.40 readLine()函數(shù)的實(shí)現(xiàn)

1 int readLine(char str[], int n)

2 {

3 int ch, i = 0;

4

5 while((ch = getchar()) != '\n')

6 if(i < n)

7 str[i++] = ch;

8 str[i] = '\0';

9 return 0;

10 }

(2)printf()函數(shù)和puts()函數(shù)

printf()函數(shù)

轉(zhuǎn)換格式符s%允許printf()寫字符串,與puts不同的是,printf()不會(huì)自動(dòng)地在每個(gè)字符串的末尾加上一個(gè)換行符,因此必須在參數(shù)中指明應(yīng)該在哪里使用換行符。比如:

char str[] = "hello world";

printf("%s\n", str);

printf()會(huì)逐個(gè)寫字符串中的字符,直到遇到空字符為止。如果只想顯示字符串的一部分,可以使用轉(zhuǎn)換格式符%.ps,這里的p是顯示的字符數(shù)量。比如,顯示hello:

printf("%.5s\n", str);

puts()函數(shù)

雖然printf()用起來(lái)比較復(fù)雜,但可以打印多個(gè)字符串。除了printf(),C標(biāo)準(zhǔn)庫(kù)還提供了puts(),其函數(shù)原型如下:

int puts(const char *s);

其中,s為指定輸出的字符串,puts()函數(shù)將參數(shù)s指向的字符串輸出到標(biāo)準(zhǔn)輸出設(shè)備中,但不輸出結(jié)束符'\0'。在輸出字符串后,puts()函數(shù)會(huì)多輸出一個(gè)換行符'\n',然后通過(guò)標(biāo)準(zhǔn)輸出設(shè)備顯示指定的字符串。如果顯示成功,則返回0,否則返回預(yù)定義常量EOF。puts()如何知道在何處停止呢?該函數(shù)在遇到空字符時(shí)就停止輸出,所以必須確保有空字符。

(3)fgets()函數(shù)和fputs()函數(shù)

fgets()函數(shù)

fgets()和fputs()分別是gets()和puts()針對(duì)文件的定制的版本,fgets()通過(guò)第2個(gè)參數(shù)限制讀入的字符數(shù)來(lái)解決溢出的問(wèn)題,該函數(shù)專門用于處理文件輸入。如果第2個(gè)參數(shù)的值是n,那么fgets()將讀入n-1個(gè)字符,或遇到第1個(gè)換行符為止。如果讀到一個(gè)換行符將它存儲(chǔ)在字符串中,這點(diǎn)與gets()不同,gets()會(huì)丟棄換行符。

fgets()的第1個(gè)參數(shù)與gets()一樣,也是存儲(chǔ)輸入位置的地址(char *類型),第2個(gè)參數(shù)是一個(gè)整數(shù),表示待輸入字符串的大小,最后一個(gè)參數(shù)是文件指針,指定待讀取文件。如果讀入從鍵盤輸入的數(shù)據(jù),則以標(biāo)準(zhǔn)輸入stdin作為參數(shù),該標(biāo)識(shí)定義在stdio.h中。其調(diào)用示例如下:

fgets(buf, STLEN, fp);

其中,buf是char類型數(shù)組的名稱,STLEN是字符串的大小,fp是指向FILE的指針。以上面的gets()為例,fgets()讀取輸入直到第1個(gè)換行符的后面,或讀到文件結(jié)尾,或讀取STLEN-1個(gè)字符,然后fgets()在末尾添加一個(gè)空字符使之成為一個(gè)字符串,字符串的大小是其字符數(shù)加上一個(gè)空字符。如果fgets()在讀到字符上限之前已經(jīng)讀完一整行,它會(huì)將表示行結(jié)尾的換行符放在空字符前面。fegts()在遇到EOF時(shí)將返回NULL,因此可以利用這一機(jī)制檢查是否到達(dá)文件結(jié)尾。如果未遇到EOF,則返回它的地址。

fgets()存儲(chǔ)換行符有好處也有壞處,壞處是你可能不想將換行符存儲(chǔ)在字符串中,這樣的換行符會(huì)帶來(lái)一些麻煩。好處是對(duì)于存儲(chǔ)的字符串而言,檢查末尾是否有換行符可以判斷是否讀取了一整行。如果不是一整行,則要妥善處理一行中剩下的字符。

首先,如何處理?yè)Q行符?一個(gè)方法是在已經(jīng)存儲(chǔ)的字符串中查找換行符,并將其替換成空字符。假設(shè)\n在st中:

while(st[i] != '\n' )

i++;

st[i] = '\0';

其次,如果仍有字符串留在輸入行怎么辦?一個(gè)可行的辦法是,如果目標(biāo)數(shù)組裝不下一整行輸入,就丟棄那些多出的字符。即讀取但不存儲(chǔ)輸入,包括\n:

while(getchar() != '\0')

continue;

為何要丟棄輸入行中余下的字符?因?yàn)檩斎胄兄卸喑鰜?lái)的字符會(huì)留在緩沖區(qū)中,成為下一次讀取語(yǔ)句的輸入。比如,如果下一條讀取語(yǔ)句要讀取的是double類型的值,就可能導(dǎo)致程序崩潰,而丟棄輸入行余下的字符是為了保證讀取語(yǔ)句與鍵盤輸入同步。既然沒(méi)有這樣的函數(shù),那么就創(chuàng)建一個(gè),s_gets()函數(shù)詳見(jiàn)程序清單 1.41。

程序清單1.41 s_gets()函數(shù)

1 char * s_gets(char *st, int n)

2 {

3 char *ret_value;

4 int i = 0;

5

6 ret_value = fgets(st, n, stdin);

7 if(ret_value){

8 while(st[i] != '\n' && st[i] != '\0')

9 i++;

10 if(st[i] == '\n')

11 st[i] = '\0';

12 else

13 while(getchar() != '\0')

14 continue;

15 }

16 return ret_value;

17 }

如果fgets()返回NULL,說(shuō)明讀到文件結(jié)尾或出現(xiàn)讀取錯(cuò)誤,s_gets()跳過(guò)了這個(gè)過(guò)程。其中的循環(huán):

while(st[i] != '\n' && st[i] != '\0')

i++;

遍歷字符串,直到遇到換行符或空字符。如果先遇到換行符,下面的if語(yǔ)句將其替換成空字符;如果先遇到空字符,else部分便丟棄輸入行的剩余字符,然后返回與fgets()相同的值。

盡管s_gets()用于替換fgets()已經(jīng)有了很大的改進(jìn),但還是不完美。如果遇到不合適的輸入時(shí),它毫無(wú)反應(yīng)。它丟棄多余的字符時(shí),也不通知程序也不告知用戶,請(qǐng)讀者完善。

fputs()函數(shù)

由于fgets()將換行符放在字符串的末尾(假設(shè)輸入行不溢出),通常要與fputs()配對(duì)使用,除非該函數(shù)不在字符串末尾添加換行符。

fputs()函數(shù)接受兩個(gè)參數(shù):第1個(gè)是字符串的地址,第2個(gè)是文件指針,指明要寫入的文件,該函數(shù)根據(jù)傳入地址找到的字符串寫入指定的文件中。如果要顯示在計(jì)算機(jī)顯示器上,應(yīng)使用標(biāo)準(zhǔn)輸出stdout作為參數(shù)。和puts()不同的是,puts()在打印字符串時(shí),不會(huì)在其末尾添加換行符。其調(diào)用示例如下:

fputs(buf, fp);

其中,buf是字符串的地址,fp用于指定目標(biāo)文件。注意,gets()丟棄輸入中的換行符,但puts()在輸出中添加換行符。而另一方面,fgets()保留了輸入中的換行符,fputs()在輸出中不會(huì)添加換行符。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    566

    瀏覽量

    20384

原文標(biāo)題:周立功:字符真正價(jià)值在于形成字符序列——字符串的輸入輸出

文章出處:【微信號(hào):ZLG_zhiyuan,微信公眾號(hào):ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    字符串函數(shù)測(cè)試學(xué)習(xí)工程

    字符串函數(shù)測(cè)試學(xué)習(xí)工程
    發(fā)表于 07-01 16:38 ?6次下載

    Labview之字符串長(zhǎng)度函數(shù)

    Labview之字符串長(zhǎng)度函數(shù),很好的Labview資料,快來(lái)下載學(xué)習(xí)吧。
    發(fā)表于 04-19 10:43 ?0次下載

    基于STM32單片機(jī)發(fā)送字符串函數(shù)

    最近由于要調(diào)試一個(gè)SMS發(fā)送短信的模塊,該模塊需要發(fā)送一系列AT指令,且需要字符串發(fā)送,但是STM32官方給的usart.c中并沒(méi)有直接發(fā)送字符串函數(shù),因此寫了一個(gè)發(fā)送字符串
    發(fā)表于 01-04 15:05 ?4738次閱讀

    C語(yǔ)言的字符串處理函數(shù)

    指針是神奇的,指向整型的指針int *p1,可以操作整型數(shù)組int a[];指向字符型的指針char *p2,可以操作字符數(shù)組(字符串)char str[];更靈活的是,在函數(shù)的傳遞中
    發(fā)表于 07-24 17:37 ?4次下載
    C語(yǔ)言的<b class='flag-5'>字符串</b>處理<b class='flag-5'>函數(shù)</b>

    LabVIEW的常用字符串操作教程免費(fèi)下載

    字符串操作與信息的保存和顯示密不可分,而字符串操作運(yùn)用也是LabⅥEW程序設(shè)計(jì)的一個(gè)難點(diǎn),因此熟練使用字符串操作函數(shù)是使用LabⅥEW進(jìn)行編程所必備的能力之
    發(fā)表于 08-21 14:51 ?25次下載
    LabVIEW的常用<b class='flag-5'>字符串</b>操作教程免費(fèi)下載

    C語(yǔ)言編程字符串函數(shù)匯總資源下載

    C語(yǔ)言編程字符串函數(shù)匯總資源下載
    發(fā)表于 04-15 16:18 ?9次下載
    C語(yǔ)言編程<b class='flag-5'>字符串</b><b class='flag-5'>函數(shù)</b>匯總資源下載

    C語(yǔ)言輸入輸出

    不對(duì)的地方請(qǐng)指出。1. 標(biāo)準(zhǔn)輸入輸出函數(shù)getchar():讀入一個(gè)字符 putchar():輸出一個(gè)字符 gets():讀
    發(fā)表于 12-14 18:52 ?3次下載
    C語(yǔ)言<b class='flag-5'>輸入輸出</b>

    字符串函數(shù)重寫練習(xí)

    字符串函數(shù)重寫練習(xí):字符串比較、字符串拼接、字符串查找、字符串拷貝、內(nèi)存比較、內(nèi)存拷貝、內(nèi)存初始
    的頭像 發(fā)表于 05-05 15:02 ?1874次閱讀

    C語(yǔ)言總結(jié)_字符串函數(shù)封裝練習(xí)

    字符串函數(shù)重寫練習(xí):字符串比較、字符串拼接、字符串查找、字符串拷貝、內(nèi)存比較、內(nèi)存拷貝、內(nèi)存初始
    的頭像 發(fā)表于 08-14 09:42 ?890次閱讀

    C語(yǔ)言_字符串與指針的練習(xí)

    這篇文章涉及到字符串與指針知識(shí)點(diǎn)的相關(guān)練習(xí)。浮點(diǎn)數(shù)與字符串互轉(zhuǎn)、字符串拷貝、字符串比較、指針交換變量、指針優(yōu)先級(jí)、數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換、內(nèi)存拷貝
    的頭像 發(fā)表于 08-14 09:51 ?1381次閱讀

    字符串相關(guān)知識(shí)

    TCL 中的數(shù)據(jù)類型只有一種:字符串。這些字符串可以是字母、數(shù)字、布爾值、標(biāo)點(diǎn)符號(hào)等特殊字符的組合。在某些特殊命令的作用下,字符串可以向其他數(shù)據(jù)類型轉(zhuǎn)換。下面將系統(tǒng)的講解或回顧下
    的頭像 發(fā)表于 03-29 11:41 ?996次閱讀

    MySQL替換字符串函數(shù)REPLACE

    MySQL是目前非常流行的開(kāi)源數(shù)據(jù)庫(kù)管理系統(tǒng)之一,它具有強(qiáng)大的功能和性能。其中之一的字符串函數(shù)REPLACE,可以用于替換字符串中的指定字符字符串
    的頭像 發(fā)表于 11-30 10:44 ?1248次閱讀

    oracle中拼接字符串函數(shù)

    在Oracle中,我們可以使用 CONCAT 函數(shù)來(lái)拼接字符串。CONCAT 函數(shù)接受兩個(gè)參數(shù),它將這兩個(gè)參數(shù)連接起來(lái)并返回相應(yīng)的字符串結(jié)果。 語(yǔ)法示例: CONCAT(string1
    的頭像 發(fā)表于 12-06 09:49 ?2349次閱讀

    labview中常用的字符串函數(shù)有哪些?

    在LabVIEW中,常用的字符串函數(shù)廣泛覆蓋了對(duì)字符串的各種操作,包括但不限于格式化、搜索、替換、連接、計(jì)算長(zhǎng)度等。以下是一些常用的字符串函數(shù)
    的頭像 發(fā)表于 09-04 15:43 ?136次閱讀

    labview字符串如何轉(zhuǎn)換為16進(jìn)制字符串

    在LabVIEW中,將字符串轉(zhuǎn)換為16進(jìn)制字符串是一個(gè)常見(jiàn)的需求,尤其是在處理數(shù)據(jù)通信和硬件接口時(shí)。LabVIEW提供了多種方法來(lái)實(shí)現(xiàn)這一轉(zhuǎn)換,包括使用內(nèi)置函數(shù)、編寫VI(Virtual
    的頭像 發(fā)表于 09-04 15:54 ?411次閱讀