我想要用C语言实现POSIX尾部。如果输入是文件(从argv接收到的文件名),那么我使用fseek来获取文件的末尾,因此实现起来有点容易。
但是当输入是标准输入时,我不能使用fseek。我以某种方式知道我可以做到:
FILE *f = stdin;
然后,我可以将stdin用作文件和fseek,一切都按预期工作(只需做一些小工作:D)。
仅是我的问题,可以吗?我的意思是(对我而言)像这样使用stdin有点不寻常。会不会有任何“安全性”或其他错误?我对我的尾巴做了很多测试,即使在边缘情况下也能正常工作。
这确实很奇怪,因为它没有帮助。 fseek
是否有效不受用作参数的变量名称的影响。
如果句柄用于纯文件,则可以成功。如果句柄不是用于纯文件的,它将无法成功。
fseek(stdin, ...)
正确。 (下面的代码。)
$ ./fseek_stdin <file
fghij
$ cat file | ./fseek_stdin
fseek: Illegal seek
fseek(f, ...)
正确。 (下面的代码。)
$ ./fseek_f <file
fghij
$ cat file | ./fseek_f
fseek: Illegal seek
但是将stdin
分配给另一个变量也没有害处。例如,您可以这样做
FILE *f;
if (...) {
f = stdin;
} else {
f = fopen(...);
}
或者您可能会这样做
void some_func(FILE *f) {
...
}
some_func(stdin);
这都是stdin
到另一个变量的完全合法的分配。
以下是早期测试中使用的文件:
file
:
abcdefghij
fseek_stdin.c
:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
if (fseek(stdin, 5, SEEK_CUR) < 0) {
perror("fseek");
return EXIT_FAILURE;
}
char *line = NULL;
size_t n = 0;
if (getline(&line, &n, stdin) < 0) {
perror("getline");
free(line);
return EXIT_FAILURE;
}
printf("%s", line);
free(line);
return EXIT_SUCCESS;
}
fseek_f.c
:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *f = stdin;
if (fseek(f, 5, SEEK_CUR) < 0) {
perror("fseek");
return EXIT_FAILURE;
}
char *line = NULL;
size_t n = 0;
if (getline(&line, &n, f) < 0) {
perror("getline");
free(line);
return EXIT_FAILURE;
}
printf("%s", line);
free(line);
return EXIT_SUCCESS;
}
两个程序的差异(为了便于阅读,略作按摩:]
$ diff -y fseek_{stdin,f}.c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int main(void) { int main(void) {
> FILE *f = stdin;
>
if (fseek(stdin, 5, SEEK_CUR) < 0) { | if (fseek(f, 5, SEEK_CUR) < 0) {
perror("fseek"); perror("fseek");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char *line = NULL; char *line = NULL;
size_t n = 0; size_t n = 0;
if (getline(&line, &n, stdin) < 0) { | if (getline(&line, &n, f) < 0) {
perror("getline"); perror("getline");
free(line); free(line);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("%s", line); printf("%s", line);
free(line); free(line);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }