使用FILE * f = stdin;

问题描述 投票:-1回答:1

我想要用C语言实现POSIX尾部。如果输入是文件(从argv接收到的文件名),那么我使用fseek来获取文件的末尾,因此实现起来有点容易。

但是当输入是标准输入时,我不能使用fseek。我以某种方式知道我可以做到:

FILE *f = stdin;

然后,我可以将stdin用作文件和fseek,一切都按预期工作(只需做一些小工作:D)。

仅是我的问题,可以吗?我的意思是(对我而言)像这样使用stdin有点不寻常。会不会有任何“安全性”或其他错误?我对我的尾巴做了很多测试,即使在边缘情况下也能正常工作。

c file stdin tail fseek
1个回答
0
投票

这确实很奇怪,因为它没有帮助。 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;
}                                                }
© www.soinside.com 2019 - 2024. All rights reserved.