2010-10-19 58 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。这是大多数程序会做的,以确定它们是否是交互式的,在您的情况下可能会更好。

现在,您可能会注意到,在第三种情况下等待用户输入的阻塞是所有标准工具所做的,并且可能是大多数用户对您的程序的期望。