2011-05-19 205 views
2

我正在寫一個程序,讀取從標準輸入迴路,使用功能與fgets,如下所示:使用與fgets非阻塞函數C++

while(fgets(buffer2, BUFFERSIZE , stdin) != NULL){ 
    //Some code 
} 

我想我的代碼是不可阻擋,那就是:當用戶沒有輸入時,我不希望程序保持'fgets'行。
我該怎麼做?

+4

我會這樣做使用單獨的線程。 – 2011-05-19 08:17:55

回答

1

你基本上有兩種選擇:

  1. 運行在一個單獨的線程循環。
  2. 檢查您的操作系統是否支持一些用於非阻塞IO的API。
+2

或3. select()/ poll()等...? :_) – 2011-05-19 08:25:36

+0

@Tony - 實際上,它實際上取決於@Dror需要什麼以及整個代碼是什麼,因爲如果它是單個線程,它可能會阻止其他地方,並且不再檢查用戶輸入。 – 2011-05-19 08:27:35

+0

@Kiril:當然......但在提出的問題中沒有排除3。乾杯。 – 2011-05-19 08:30:59

0

這聽起來有點像矯枉過正,但這是我想到的那個。

使用2個不同的線程 - 一個使用這個循環和等待阻塞(我不認爲這可以做到非阻塞)。當有東西被讀取時,將其推入管道。

與此同時,另一個線程會做任何它需要做的事情,並不時檢查管道中的數據(顯然,你希望這是異步的,或者至少我是這樣做的。意味着不同的線程)

但是,然後,你需要很好地同步這兩個線程。您應該檢查您的操作系統關於多線程和IO操作。

2

如果你有一個正確的POSIX環境,您可以使用select()poll()調用 fgets() ... read()前檢查對stdin的描述符輸入。

(謝謝!)低於一月的評論解釋了爲什麼你不能用這種方法使用fgets() ...草率,有緩衝的FILE對象一個額外層和數據已經可以等待雖然select()覺得沒有什麼更多關於文件描述符......防止您的程序及時響應,並且如果其他系統在發送更多的數據之前正在等待已發送數據的響應,則可能掛起stdin

+1

還不夠,你必須把句柄設置爲非阻塞模式(因爲在再次調用select/poll之前你總是需要讀出它,並且這會阻止沒有),你需要確保你總是讀完它,因爲fgets讀取的不僅僅是返回值,所以你可能仍然有數據緩存,但select會等待,因爲底層描述符沒有更多的信息。 – 2011-05-19 08:32:19

+0

@Jan:是的,絕對.. 。傻的我。這意味着 - 沒有阻塞的標準輸入 - 你必須使用'read()'而不是'fgets()'並且自己處理線條的組合(根據我的經驗,這可能會稍微繁瑣或者效率稍低)... – 2011-05-19 09:03:26

3

fgets()是一個阻塞函數,它的意思是等待數據可用。

如果要執行異步I/O,您可以使用select()poll(),或epoll()。然後在存在可用數據時從文件描述符執行讀取。

這些函數使用FILE *手柄的文件描述符,通過檢索:

int fd = fileno(f); 

如果使用的是Unix或Linux,那麼一個解決方案,可以標記文件所用的文件描述符是無阻塞。例如:

#include <fcntl.h> 
FILE *handle = popen("tail -f /als/als_test.txt", "r"); 
int fd = fileno(handle); 
flags = fcntl(fd, F_GETFL, 0); 
flags |= O_NONBLOCK; 
fcntl(fd, F_SETFL, flags); 

fgets現在應該非blockng,將返回一個空並設置錯誤代碼爲您服務。

+0

請注意非集體性國王I/O - 從我讀過的內容來看,它可以與pipes和ttys一起使用,但不是常規文件,因此'./prog Thanatos 2011-05-19 08:38:12

0

在Linux上,您可以通過按ctrl-d來指定輸入的結尾,當然,您也可以使用單獨的線程來執行此操作。