仅从命令行重定向读取 STDIN
Reading from STDIN from command line redirection only
我的目标是拥有一个可以从 C 文件重定向中获取用户输入的程序。
$ ./hello < input.txt
但是当没有重定向或参数时,程序将输出一条消息:
$ ./hello
There is nothing to read!
由于文件重定向直接进入标准输入,我正在使用 scanf 读取文件的内容。但是,当我在没有重定向的情况下启动程序时,scanf
等待输入,我的目标是仅从命令行上的重定向获取它,如果没有任何内容,它会输出消息
直到不可移植地检查 stdin 是否为 tty,shell 无法判断输入来自何处,它只能判断输入是否已经存在。你没有说你在哪个平台上,我假设你真正想要的只是/为了不阻塞读取/ - 你可以通过以非阻塞方式轮询 stdin
来实现:
#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>
int poll_stdin() {
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
size_t read_stdin(char *buf, size_t max) {
size_t n = 0;
while ((n < max) && (poll_stdin())) {
read(STDIN_FILENO, &buf[n++], 1);
}
if (n < max-1) buf[n] = '[=10=]';
return n;
}
int main(int argc, char *argv[]) {
char buf[255];
size_t len;
buf[255] = '[=10=]';
len = read_stdin(buf, 255);
if (len == 0) printf("No input!\n");
else printf(">%s\n", buf);
return 0;
}
输出:
dtrombley@squall:~$ echo 'Hello, world!' > hello.txt
dtrombley@squall:~$ ./main
No input!
dtrombley@squall:~$ ./main < hello.txt
>Hello, world!
使用 isatty()
这正是它的用途。
请注意,并非所有系统都提供健全的 isatty(),但任何声称符合 POSIX 的 *nixen 都可以正常工作。这是我当前的 *nixen 代码(适用于 C):
#include <stdbool.h>
#include <unistd.h>
bool my_isatty( int id )
{
return (0 <= id) and (id <= 2) and isatty( id );
}
Windows 上有各种各样的皱纹,特别是如果你使用的是 MSYS2 shell(它使用管道实现命令 window,大声笑,所以你必须玩用一些低级 OS 的东西来检查。
我的目标是拥有一个可以从 C 文件重定向中获取用户输入的程序。
$ ./hello < input.txt
但是当没有重定向或参数时,程序将输出一条消息:
$ ./hello
There is nothing to read!
由于文件重定向直接进入标准输入,我正在使用 scanf 读取文件的内容。但是,当我在没有重定向的情况下启动程序时,scanf
等待输入,我的目标是仅从命令行上的重定向获取它,如果没有任何内容,它会输出消息
直到不可移植地检查 stdin 是否为 tty,shell 无法判断输入来自何处,它只能判断输入是否已经存在。你没有说你在哪个平台上,我假设你真正想要的只是/为了不阻塞读取/ - 你可以通过以非阻塞方式轮询 stdin
来实现:
#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>
int poll_stdin() {
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
size_t read_stdin(char *buf, size_t max) {
size_t n = 0;
while ((n < max) && (poll_stdin())) {
read(STDIN_FILENO, &buf[n++], 1);
}
if (n < max-1) buf[n] = '[=10=]';
return n;
}
int main(int argc, char *argv[]) {
char buf[255];
size_t len;
buf[255] = '[=10=]';
len = read_stdin(buf, 255);
if (len == 0) printf("No input!\n");
else printf(">%s\n", buf);
return 0;
}
输出:
dtrombley@squall:~$ echo 'Hello, world!' > hello.txt
dtrombley@squall:~$ ./main
No input!
dtrombley@squall:~$ ./main < hello.txt
>Hello, world!
使用 isatty()
这正是它的用途。
请注意,并非所有系统都提供健全的 isatty(),但任何声称符合 POSIX 的 *nixen 都可以正常工作。这是我当前的 *nixen 代码(适用于 C):
#include <stdbool.h>
#include <unistd.h>
bool my_isatty( int id )
{
return (0 <= id) and (id <= 2) and isatty( id );
}
Windows 上有各种各样的皱纹,特别是如果你使用的是 MSYS2 shell(它使用管道实现命令 window,大声笑,所以你必须玩用一些低级 OS 的东西来检查。