在C中两次阅读Stdin


    int getLineCount() {
        int ret = 0;
        char c;
        while ((c = fgetc(stdin)) != EOF)
            if (c == 'n')
                ret++;
        return ret + 1;
    }
    void fill(char *WORD) {
        int charIndex = 0;
        char c;
        while ((c = fgetc(stdin)) != EOF) {
           *(WORD + charIndex++) = c;
        }
    }
    int main() {
        int lineNum = getLineCount();
        char *WORD = (char*)calloc(lineNum * 18,sizeof(int));
        fill(WORD);
        return 0;
    }

这是我代码的一部分,我的问题是(如您所见):

我正在尝试两次读取 stdin 的内容,但在 getLineCount 函数之后,它停留在 EOF 上,我无法在填充函数中再次读取它。

我在 Linux 中使用此命令从用户那里获取 stdin;

$./output < text_file.txt

有没有办法将标准回滚到起始角色?如果没有,我该如何解决此问题?

谢谢。

您可以使用

rewind(stdin)将流设置回文件的开头,但请注意,它不能保证有效,特别是如果流是管道、终端或设备。

您的分配方案不正确:您可以计算文件的大小,然后分配那么多字节,但当前(char*)calloc(lineNum * 18,sizeof(int));为每行分配类型 int 大小的 18 倍。一些带有短行的文件将适合此数组,而其他文件将调用未定义的行为。

请注意,必须将c定义为int,以便c = fgetc(stdin);正确存储所有值,包括EOF特殊值。

不要使用 rewind .

当然,您可以保存从 stdin 读取的数据(如果它对于主内存来说太大,则可能保存在文件中)并对其进行操作。

另一种可能性是:

struct callback {
  void (*call) (char, void *);
  void * data;
};
void with_characters_from(FILE * file, struct callback const * callbacks, size_t count) {
  int c;
  while ((c = fgetc(file)) != EOF) {
    char character = c & 0xFF;
    for (size_t i = 0; i < count; ++i) {
      callbacks[i].call(character, callbacks[i].data);
    }
  }
}

你反向控制,这样你的函数就不再"从"stdin中"拉出数据",而是数据(字符)被"推送"到"它们。请注意,这可能会导致回调地狱,并且在 C 中,您牺牲了很大一部分类型安全(以及代码清晰度.. 没有第一类函数/闭包......叹息)。

一个小测试:

struct counter_data {
  char const character;
  unsigned count;
};
void counter (char character, void * vptr) {
  struct counter_data * data = vptr;
  if (character == data->character) {
    ++(data->count);
  }
}
int main() {
  struct counter_data data [2] = {
    {'a', 0}, {'x', 0}};
  struct callback callbacks [2] = {
    {&counter, &(data [0])},
    {&counter, &(data [1])}};
  with_characters_from (stdin, callbacks, 2);
  printf("Counted %c %u times n", data [0].character, data [0].count);
  printf("Counted %c %u times n", data [1].character, data [1].count);
  return 0;
}

如前所述,对于您的特定示例,您应该考虑一种完全不同的方法:如果可能的话,事先计算所需的大小。如果超过该大小(应始终测试该大小),请使用realloc以获取更大的内存块。

相关内容

  • 没有找到相关文章

最新更新