【问题标题】:How to determine if stdin is empty如何判断标准输入是否为空
【发布时间】:2017-11-16 02:19:44
【问题描述】:

我有一个小项目要为学校做。我们有一个生成迷宫的程序。 我们可以输入参数来生成不同的迷宫,甚至可以将其作为图片。

我们这样称呼它:

./测试

./test --arg1 val --arg2 val --etc

我们被要求将参数解析为我们放入标准输入的文件,如下所示:

./test

现在我必须能够使用上述每一行调用程序。带参数的那行有效,带有 stdin 程序的那行有效,但没有任何东西的那行不再有效。

所以我应该检查用户是否在标准输入中发送了一些文件,我用文件调用程序,否则我用正常方式调用它。我尝试使用 feof,但它无法工作,因为 stdin 甚至在 eof 中都没有任何内容。 当我在没有参数或文件的情况下调用程序时,它会等待用户写一些它不应该写的东西。

基本上我的代码应该是这样的

int main()
{
    int v;
    if (stdin!=NULL)) { //if a file has been passed "./test <test.txt"
        scanf("%d",&v);
    }
    else {  //if no files has been passed "./test "
        printf("no file forwarded \n"); 
        return 1;
    }
    if (v<50) {
        printf("you drive slow\n");
    }
    else {
        printf("you drive fast\n");
    }
    return 0;
}

但显然(stdin != NULL) 不起作用。那么有没有办法检查标准输入是否有东西? 我问了我的同学,其中一个告诉我有关使用 fgetc 获取第一个 char 然后如果真的有 char 则将其放回但是当我尝试使用 fgetc 时,如果没有 char 则等待我放一个字符输入。

那么我如何检查标准输入是否为空或其中是否有文件(不使用新库)?

提前谢谢你 祝你有美好的一天

如果我不完全清楚,请告诉我,我不是母语人士,我有一些困难,因为这是一个技术问题

【问题讨论】:

  • 许多希望从文件中读取参数的程序将@filename 作为打开该文件名的参数。

标签: c


【解决方案1】:

听起来您想根据命令行上提供的参数或从文件通过管道输入的参数来运行程序。如果是这样,你应该首先检查命令行中是否提供了参数:

if (argc > 1) {
  //parse argv
}

然后,检查stdin是否为空,如果没有则从stdin中读取参数:

else if ((fseek(stdin, 0, SEEK_END), ftell(stdin)) > 0)
{
  rewind(stdin);
  char buffer[1024];
  fgets(buffer, 1024 , stdin);
  //parse args read in from stdin
}
else
{
  //no redirection
}

【讨论】:

  • feof 总是返回 0,因为 stdin 中没有 eof。我希望能够不带参数、带参数或带文件调用程序 目前我只能带参数或带文件调用它
  • 如果您不带参数调用它,您将通过查看argc 知道这一点。如果您提供带有./test &lt; file 的文件,feof 将不会返回 0,并且您知道这种方式。有什么问题?
  • 当我尝试使用 feof 时它根本不起作用也许我错过了它我会再试一次我用示例代码编辑我的问题,以便在我使用 feof 时更精确如果我用文件询问它可以正常工作如果我不带参数或文件询问它可以正常工作当我输入文件时它等待输入(不应该是这种情况)!feof(stdin)返回0,当我不它也返回 0
  • 它在没有参数时等待输入,因为你有scanf,如果你不想等待输入,只需取出scanf。我一定是错过了什么......
  • 好吧:如果我提供了一个文件,它应该读取它(所以它使用 scanf 来读取提供的文件)如果我不提供文件它会给出错误(这个程序只是简化版本)它应该检查标准输入中是否提供了文件,因此当没有文件时它不应该等待输入。 feof 不起作用,因为它总是返回相同的东西文件。试试你机器上的代码,你会明白我在说什么
【解决方案2】:

好的,我找到了一个解决方案,它不是最好的,因为我不应该使用外部库,但现在它可以工作,我希望它对某人有用:

feof 是个好主意,但它确实不起作用,原因是如果你什么都不写,stdin 永远不会有 EOF。因此,如果您提供一个文件,因为您必须在没有文件时解析该文件,它将尝试解析用户输入的内容。

首先你必须包含

#include <unistd.h>

然后

int v;
    if (!isatty(STDIN_FILENO)) //if stdin is not a terminal (a file was provided)
    {
         scanf("%d",&v);
    }
    else { //if stdin is a terminal (no file provided)
        printf("no file forwarded \n"); 
        return 1;   
    }
    if (v<50){printf("you drive slow\n");}
    else {printf("you drive fast\n");}
    return 0;

它将检查标准输入是否是终端。 此解决方案有效,但如果有人在不使用外部库的情况下拥有一个,那就太酷了!

【讨论】:

  • isatty() 不是标准 C 库的一部分。 &lt;unistd.h&gt; 也不是。
【解决方案3】:

如何判断stdin是否为空(?)

getchar()读取1个字符。

int ch = getchar();
if (ch == EOF) {
  if (feof(stdin)) puts("stdin empty");
  else             puts("stdin error"); // very rare
} else {
  ungetc(ch, stdin); // put back
  puts("stdin not empty");
}

【讨论】:

  • 我讨厌你,但这是正确的答案。如果你问如何做其他有用的事情,比如如何确定标准输入的大小,你会得到相同的确切答案。 Stdin 并不意味着有未来的眼光,所以我们被困在做一些骇人听闻的事情。话虽这么说,但不确定您是否总是能够将其转换为标准输入,因为它并不总是一个文件,至少在所有平台上都是这样。
  • @LeifMessingerLOAF 回复:“不确定你是否总是能够取消etc”,推回一个就可以了。 "保证一个字符的回送。如果在同一流上调用 ungetc 函数的次数过多,而没有对该流进行干预读取或文件定位操作,则该操作可能会失败"
猜你喜欢
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2019-03-20
  • 1970-01-01
相关资源
最近更新 更多