2010-10-19 72 views
3

我的程序需要接受3種輸入的輸入文件下命令:如何閱讀既argv的和重定向從輸入文件

./Myprogram input.txt 
./Myprogram < input.txt 
./Myprogram 

我在考慮使用argc檢查參數的個數解決前兩種情況(因爲重定向不算作參數)。但後來我堅持最後一個案例,它只是等待用戶輸入。

我想知道是否有方法可以告訴shell命令中是否存在重定向?

對於更復雜的場景,例如混合重定向和argv形式(請參見下文)。有沒有辦法做到這一點,或者它只是一個糟糕的設計,用於獲取用戶命令?

./Myprogram input1.txt input2.txt input3.txt 
./Myprogram input1.txt < input2.txt input3.txt 
./Myprogram 

任何幫助將不勝感激!

Z.Zen

+1

你想爲第三種情況做什麼?如果您只是從標準輸入讀取數據,則第二個和第三個數據可以被視爲相同。另一方面,如果你使用例如'curses'或'readline',那麼第三個可能會不同。 – 2010-10-19 03:57:24

+0

查看Herb Sutter的「More Exceptional C++」。如果我沒有記錯,它解決了這個問題。 – 2010-10-19 14:09:24

回答

6

重定向將永遠不會被您的程序視爲參數。所以在:

./Myprogram input.txt 
./Myprogram < input.txt 
./Myprogram 

第二和第三種形式是相同的。至於你的第二組的可能性:

./Myprogram input1.txt input2.txt input3.txt 
./Myprogram input1.txt < input2.txt input3.txt 
./Myprogram 

第二行等同於:

./Myprogram input1.txt input3.txt < input2.txt 

,它也無法區分:

./Myprogram input1.txt input3.txt 

(唯一不同的福利,其中標準輸入實際上來自)。

的典型方式一些程序處理在命令行中指定的標準輸入和文件的混合輸入是接受"-"作爲一個特殊的文件名,意思是「使用標準輸入作爲參數列表這個位置輸入文件」。如果參數列表爲空,許多此類程序將默認處理單個列表"-"

+0

謝謝!似乎我忘記了第二和第三個案件是相同的程序。由於我不需要知道另一端是否有人,因此這兩種情況的處理代碼應該是相同的。我想我會盡量避免複雜場景中的第二種情況,因爲這不是用戶通常所期望的,而且對於我的程序而言,這僅僅是沒有必要的。 – 2010-10-19 04:16:14

0

我想知道是否有方法可以判斷shell命令中是否存在重定向?

號但從你的程序的角度來看,有這兩種情況之間沒有區別:

./Myprogram < input.txt 
./Myprogram 

在這兩種情況下,程序不採取任何命令行參數,並會得到它的輸入來自標準輸入。
在第一種情況下,它是shell將文件input.txt的內容連接到程序的stdin您的程序對此無所謂。

+1

雖然這個答案是正確的,但OP可能真的想知道是否可以檢測stdin是終端還是普通文件。 – 2010-10-19 04:04:30

1

@R ..對於通常的情況是正確的。

如果您想在案例#3但不是#2中進行交互行爲,除了讓終端逐行緩衝用戶輸入外,您可以使用isatty(特別是isatty(0))來確定另一端是否有人。

這不是標準C,但也不是終端或shell的概念!

4

的基本算法是:

if (there are no arguments left after parsing options) 
    call_function(stdin); 
else 
{ 
    foreach remaining argument 
    { 
     FILE *fp; 
     if (strcmp(argument, "-") == 0) 
      call_function(stdin); 
     else if ((fp = fopen(argument, "r")) == 0) 
      ...error handling... 
     else 
     { 
      call_function(fp); 
      fclose(fp); 
     } 
    } 
} 

您可以將文件名傳遞給「call_function()」太多,有時我寫與指定的輸出文件流的代碼。該函數('call_function()')處理一個文件 - 讀到文件末尾。它不關閉文件;它被給了一個開放的文件,不應該關閉它。

當然,第一個'if'處理I/O重定向的情況。

我寫了很多年了,處理這個循環的函數。無論何時我需要在這種'UNIX過濾器'成語中編寫命令 - 這經常是這樣,它簡化了我的生活。隨着標準化的錯誤報告包,它大大簡化了生活。將它作爲一個函數也允許我使用它的變體,例如在文件被覆蓋之前創建文件的備份,或者如果函數成功完成,則安全地覆蓋文件。

+0

感謝您告訴我這個經過測試的過濾算法! – 2010-10-19 04:20:30

+1

特殊處理''''''''參數爲'stdin'可能會有用。 – jfs 2010-10-19 19:21:22

+1

@ J.F.Sebastien:哦,是的;好點 - 這是埋在功能(我最後修改2 1/2年前)。 'if(strcmp(argument,「 - 」)== 0)call_function(stdin);其他{文件* fp = ...如上...}。 – 2010-10-19 20:55:41

0

可以通過在標準輸入上使用select()來判斷是否爲數據。這不會告訴你是否有重定向(你不能告訴你什麼時候該文件是空的,或者由於某種原因用戶在你的程序有機會測試它之前設法在標準輸入中加入了某些東西)。它是否適合您的案例取決於您想在邊緣案例中做什麼。

或者,您可以在stdin上使用isatty()來確定它是否是tty。這是大多數程序會做的,以確定它們是否是交互式的,在您的情況下可能會更好。

現在,您可能會注意到,在第三種情況下等待用戶輸入的阻塞是所有標準工具所做的,並且可能是大多數用戶對您的程序的期望。