变态重口极致另类在线-波多久久夜色精品国产-波多野结衣在线观看一区-波多野结衣在线观看一区二区-污污的网站免费阅读-污污视频网址

東坡下載:內容最豐富最安全的下載站!

首頁編程開發VC(VC++) → C程序緩沖輸入流關于getchar()與scanf()的思考

C程序緩沖輸入流關于getchar()與scanf()的思考

相關文章發表評論 來源:本站原創時間:2014/2/18 14:53:53字體大。A-A+

更多

作者:不詳點擊:307次評論:1次標簽: C程序緩沖

如題,本文深入了解了下C程序的緩沖輸入方面問題。

通常,系統使用行緩沖輸入,這意味著輸入的內容會在您按下回車鍵之時被傳輸給程序,按下回車鍵的同時還將傳輸一個編程時需要注意的換行字符。ANSIC把緩沖輸入作為標準。

為了說明何謂緩沖輸入,特舉了一個簡單的例子(別在意例子意義,意在說明何謂緩沖輸入):

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main (void)
{
    char ch;
    while (getchar() != 'a')
        continue;
    ch = getchar();
    putchar(ch);
    putchar('\n');
    return 0;
}

輸入下行:

Not alone!

會發現輸出為字符l,這就是緩沖輸入的體現。由于簡單,就不詳講了。

 

緩沖輸入通常給用戶帶來方便,他提供了在將輸入發送至程序前對其進行編輯的機會,但在使用字符輸入時這會給編程人員帶來麻煩。其主要問題在于緩沖輸入需要您按下回車鍵來提交您的輸入。這一動作還傳輸一個程序必須處理的換行符。

尤其是scanf()函數和getchar()函數混用的時候。這是因為getchar()讀取每個字符,包括空格、制表符和換行符;而scanf()在讀取數字時則會跳過空格、制表符和換行符。為了說明它產生的問題,舉例如下。該程序讀取一個字符和兩個數作為輸入,然后使用由所輸入的兩個數字指定的行數和列數來打印該字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* 程序單1 */
#include <stdio.h>
void display (char cr, int lines, int width);
int main(void)
{
    int ch;         /* 要打印的字符 */
    int rows, cols; /* 行數和列數 */
    printf ("Enter a character and two integers: \n");
    while ((ch = getchar()) != '\n')
    {
        scanf ("%d %d", &rows, &cols);
        display (ch, rows, cols);
        printf ("Enter another character and two integers: \n");
        printf ("Enter a newline to quit.\n");
    }
    printf ("Bye.\n");
    return 0;
}
void display(char cr, int lines, int width)
{
    int row, col;
    for (row = 1; row <= lines; row++)
    {
        for (col = 1; col <=width; col++)
            putchar(cr);
        putchar('\n');  /* 結束本行,開始新的一行 */
    }
}

書上也說這個程序是有這大問題的,我們也來看下問題在哪。

運行時輸入c 2 3,程序如期打印2行c字符,每行3個。然后該程序提示輸入第二組數據,并在您還沒能做出響應之前就退出了!這就是緊跟在第一個輸入行的3后面的那個換行符所導致的問題。scanf()函數將該換行符留在了輸入隊列中。而getchar()由于并不跳過換行符,所以在下一個循環時您輸入其他內容之前,這一換行符由getchar()讀出,然后將其賦值給ch,而這正是終止循環的條件。

書中也給出了解決方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 程序單2 */
#include <stdio.h>
void display (char cr, int lines, int width);
int main(void)
{
    int ch;         /* 要打印的字符 */
    int rows, cols; /* 行數和列數 */
    printf ("Enter a character and two integers: \n");
    while ((ch = getchar()) != '\n')
    {
        scanf ("%d %d", &rows, &cols);
        display (ch, rows, cols);
        while (getchar() != '\n')   //添加的語句
            continue;
        printf ("Enter another character and two integers: \n");
        printf ("Enter a newline to quit.\n");
    }
    printf ("Bye.\n");
    return 0;
}
void display(char cr, int lines, int width)
{
    int row, col;
    for (row = 1; row <= lines; row++)
    {
        for (col = 1; col <=width; col++)
            putchar(cr);
        putchar('\n');  /* 結束本行,開始新的一行 */
    }
}

看到這里,可能就有人說了,你這樣照搬照抄有何意思。下面就來說下我自己當時的一些疑惑吧。

在程序單1時,我想了下輸入為cr 2 3時結果會是怎樣,當時真沒想出來。之后輸入運行了下,輸出:

Enter another character and two integers:

Enter a newline to quit.

rrr

rrr

Enter another character and two integers:

Enter a newline to quit.

Bye.

Press any key to continue

當時看到這些時更加困惑了,為什么會這樣,c呢?百思不得其解。所以我又在程序單2中輸入cr 2 3,剛開始輸出如下:

Enter another character and two integers:

Enter a newline to quit.

并要求繼續輸入。當時頗感無語,完全沒懂。然后又慢慢輸入:

1

2

3

結果:

111

111

Enter another character and two integers:

Enter a newline to quit.

這個對了!那么為什么前面輸入cr 2 3時是那樣輸出呢。按了下換行程序結束后苦思冥想。

 

現在真是想通了,理解的透徹,我來說下吧:

在程序單1輸入cr 2 3時,getchar()讀取了輸入隊列中的c之后,scanf()無法讀取r及其之后的字符,只能使用默認的值。而這時的rows和cols的值由于只是在前面聲明并沒有賦值,所以一般是負的大數。就假設這一次循環的輸入為c -16653 -16652,帶入display程序,當然是什么都沒顯示啦。然后輸出了兩行提示信息。而這時由于緩沖的輸入隊列中有值,不等您反應繼續帶入,即r 2 3,而這就是之后所輸出的內容了。說到這里您可以把程序單1中的rows和cols聲明時分別初始化為1和2,看下結果就知道了。

至于程序單2,要先知道添加的while語句的作用。它把scanf()輸入后的所有字符,包括換行符都給剔除了。這樣能讓循環準備好讀取即將輸入的下一行開始的第一個字符。也就是說,您輸入cr 2 3時,他先分別像程序單1中那樣輸入c -16653 -16652,把您輸入的c之后的r 2 3給剔除了包括3之后的換行符,然后輸出兩行提示等待您的再次輸入。

 

PS:好,寫到這里也差不多了(其實全部手碼的,信不信→_→實體書還是有麻煩的),今天感悟頗大,收獲頗豐。一直以為C學的還好,今天拿起以前買的C Primer Plus隨便翻了翻發現有好多不懂,才知道實在是想當然了,我會的只是C的語法規則而已?戳8.5(創建更友好用戶界面)和8.6(輸入確認),終于明白了我們大學生的編程只擁有算法的正確性,而算法的健壯性真的是不堪入目,也終于明白了一個真正的程序所需要擁有的東西以及編寫一個能用的軟件有多艱難。下面再給出書中描述的輸入流與字符的關系,個人感覺受教了。

 

輸入流與字符:

如下一行輸入:

is 28 12.4

在您眼中,該輸入是一串字符后面跟著一個整數,然后是一個浮點值。對C程序而言,該輸入是一個字節流。第一個字節是字母i的字符編碼,第二個字節是字母s的字符編碼,第三個字節是空格字符的字符編碼,第四個字節是數字2的字符編碼,等等。

雖然輸入流由字符組成,但如果您指示了scanf()函數他就可以將這些字符轉換成數值。例如,考慮下面輸入:

42

如果您在scanf()中使用%c說明符,該函數將只讀取字符4并將其存儲在一個char類型的變量中。如果您使用%s說明符,該函數會讀取兩個字符,即字符4和2,并將它們存儲在一個字符串中。如果使用%d說明符,則scanf()讀取同樣的兩個字符,但是隨后它會繼續計算與它們相應的整數值為4*10+2,即42;然后講該整數的二進制表示保存到一個int變量中。如果使用%f說明符,則scanf()讀取這兩個字符,計算它們對應的數值42,然后以內部浮點表示該值,并將結果保存在一個float變量中。

 

C程序將輸入視為一個外來字節的流。簡言之,輸入由字符組成,但scanf()可以將輸入轉換成整數或浮點值。使用像%d或%f這樣的說明符能限制可接受的輸入的字符類型,但getchar()和使用%c的scanf()接收任何字符。

擴展知識

相關評論

閱讀本文后您有什么感想? 已有 人給出評價!

  • 2791 喜歡喜歡
  • 2101 頂
  • 800 難過難過
  • 1219 囧
  • 4049 圍觀圍觀
  • 5602 無聊無聊
熱門評論
最新評論
第 1 樓 本機地址CZ88.NET 網友 客人 發表于: 2017/2/23 22:07:05
为什么“添加的while语句能使程序剔除scanf( )输入后的所有字符,包括换行符”。怎么解释?

支持( 0 ) 蓋樓(回復)

昵稱:
表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
字數: 0/500 (您的評論需要經過審核才能顯示)

本類常用軟件

主站蜘蛛池模板: 午夜高清免费观看视频 | 好男人www社区资源免费观看 | 国产成人小视频 | 韩国三级日本三级在线观看 | 国产黄色大全 | 天天做天天爱天天影视综合 | 成在线人免费视频一区二区三区 | 9299yy看片淫黄大片在线 | 香蕉欧美 | 欧美日韩国产手机在线观看视频 | 亚洲一区日韩二区欧美三区 | 每日更新国产 | 成人午夜毛片在线看 | eeuss秋霞成人影院 | 国产视频一区在线播放 | 激情四月婷婷 | 亚洲成av人片在线观看 | 丝袜美腿美女被狂躁动态图片 | 成人国产精品免费软件 | 靠逼久久 | 黄色免费在线观看网址 | 中文字幕天天躁日日躁狠狠躁免费 | 99九九99九九九视频精品 | 亚洲欧美精品一区 | 在线播放国产一区 | 日日摸夜夜爽人人添 | 日日夜夜狠狠 | 免费看黄视频网站 | 日韩午夜高清福利片在线观看 | 免费亚洲一区 | 日韩 国产 欧美 精品 在线 | 亚洲日日做天天做日日谢 | 亚洲欧美久久婷婷爱综合一区天堂 | 337p日本大胆欧洲色噜噜高清 | 亚洲欧美日韩中文v在线 | 国产高清在线精品一区二区三区 | 黄色一级视频免费观看 | 国产成人免费在线视频 | 日韩一区二区三区四区 | 插曲的痛一卡二卡三卡 | 欧美00xx|