歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言判斷用戶是否輸入-非阻塞函數kbhit

C語言判斷用戶是否輸入-非阻塞函數kbhit

日期:2017/3/1 9:07:37   编辑:Linux編程

一、基礎研究

要從地址讀取數據,肯定是要定義一個指針變量p,用它來實現變換地址和取值的功能。另外程序是當兩個條件中的某一個出現時才停止,所以應該用while~do循環語句循環輸出n和d,並用while進行判斷。這裡實現三個問題:

(1)循環地把值轉換成地址。

(2)判斷偏移地址是否為0xffff。

(3)判斷用戶是否輸入了‘q’。

前兩個問題比較好實現,對於第三個問題我們需要注意的是c語言是怎麼處理用戶輸入的。之前做匯編課設的時候我們研究過匯編對於輸入的處理,並且嘗試過兩個中斷,一個是要中止等待用戶輸入的,一個是不中止等待的。現在我們的需求就類似於第二個中斷,即等待用戶輸入同時不停止程序的運行。

首先寫了一個程序如下:

編譯時警告說0xffff在比較中超過常量范圍,也就是超過int型的范圍,將整個程序的int改成long後警告消失。int是兩個字節,應該正好能夠容納偏移地址0xffff,為什麼比較時會超出范圍呢?難道是與比較的機制有關嗎?這裡作為一個問題來擴展研究。

將編譯之後的程序進行連接,出現錯誤:getchar()函數沒有定義,這說明在我們當前連接的obj文件裡沒有getchar()函數,解決的辦法有兩個:(1)用#include<stdio.h>導入頭文件。(2)不使用getchar()函數。在這裡我們先嘗試第二種方法,scanf()函數會暫停程序等待輸入,並且在輸入完後還要按回車才能繼續向下執行,所以不符合我們的需求。查找資料發現getche()函數不用敲回車就可以將字符輸入,而getch()函數不用敲回車,也不顯示,只是將字符輸入進行處理。而且這兩個函數也不需要導入其他文件,修改後的程序如下:

這時發現還有一個問題:每次循環都還要用戶輸入字符才能向下進行,就是說函數是阻塞的。在網上查找資料發現輸入函數都是阻塞型的,那麼我們可以調整思路,檢測用戶是否輸入。查找資料發現輸入檢測函數有kbhit()函數,如果有輸入它會返回一個非0值,沒有就返回0,修改後的函數如下:

運行程序,它會不停地打印地址和地址的值,直到用戶輸入字符q。

但是運行結果發現:當地址為0xffff時,程序並沒有停止:

將程序改成如下所示也不行:

這裡可能是判斷語句有問題,結果將判斷語句改為p==(long *)0xffff之後程序在地址為0xffff時可以停止,修改的程序為:

之前是對數進行比較,修改後是對指針進行比較,那為什麼對數進行比較會出錯呢?我們覺得是因為將p強制類型轉換成long會出錯,再次修改程序如下:

發現雖然有警告,但是程序仍能正常執行,這說明用long型確實會對地址判斷有影響。

二、擴展研究

(1)int是兩個字節,應該正好能夠容納偏移地址0xffff,為什麼比較時會警告超出范圍呢?

答:因為int是帶正負的類型,它的最高位為符號位,而0xffff是unsigned int類型,所以會超出范圍。這裡把它進行強制類型轉換就行了。

(2)Getchar()的實現方式。

答:getchar 由宏實現:#define getchar() getc(stdin)。所以要與頭文件相關聯,它不是真正的函數,而是定義為預處理器宏。

(3)為什麼用(long)p==0xffff判斷時會識別不到0xffff,導致循環停不下來?

答:同樣這裡應該是unsigned long類型。

三、研究總結

c語言是接近底層的語言,這在它和匯編的聯系上可以看出來。之前做課設時要用到非阻塞中斷,在這裡是用到非阻塞函數,問題是相似的,只不過實現的語言變了。但是只要我們掌握了程序設計的精髓,其他的就只是語法上的實現問題了。

還有,獨立分析和思考的能力真的很重要,我們不要養成隨便問問題的習慣,要先自己思考,抓住問題的本質,提出自己的猜想,然後在詢問別人或者查資料去證實,這樣自己解決問題的能力才能夠得到成長。

Copyright © Linux教程網 All Rights Reserved