在C中阅读Stdin Twice

时间:2016-03-01 21:53:15

标签: c input buffer stdin stdio

    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

有没有办法将stdin回滚到起始角色?如果没有,我该如何解决这个问题?

感谢。

2 个答案:

答案 0 :(得分:1)

您可以使用rewind(stdin)将流设置回文件的开头,但请注意,它不能保证正常工作,尤其是当流是管道,终端或设备时。

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

请注意,c必须int定义为c = fgetc(stdin);才能正确存储包括EOF特殊值在内的所有值。

答案 1 :(得分:1)

请勿使用export interface Tweet { id: number; text: string; } @Component({ selector: 'tweet', template: ` {{tweet.text}} `, inputs: ['tweet'] }) export class TweetComponent { public tweet: Tweet; } // This works when in the context of another component's template like: <tweet [tweet]="tweet"></tweet> // code to manually initialize var tweetEl = document.createElement('tweet'); var body = document.querySelector('body'); body.appendChild(tweetEl); var comp = new TweetComponent(); comp.tweet = tweet; bootstrap(TweetComponent, [provide(TweetComponent, {useValue: comp})]);

当然,您可以保存从stdin读取的数据(如果文件太大而无法存储在主存储器中),并对其进行操作。

另一种可能性是:

rewind

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

A small test

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);
    }
  }
}

如前所述,对于您的特定示例,您应该考虑采用完全不同的方法:如果可能,请事先计算所需的大小。如果你超过了那个大小(你应该总是测试它),那么使用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; } 来获得更大的内存。