如何通过使用C ++的stdin获取可用数据的大小:当STDIN未被重定向时

时间:2016-01-05 07:14:09

标签: c++ c windows winapi

虽然Question A被标记为重复,但引用的Question B and its answers仅解决部分问题:重定向STDIN时。因此,当STDIN未被重定向时,我再次问Question A同样的问题。

我的问题:当STDIN未重定向时,如何确定STDIN中的可用大小?请不要只使用PeekConsoleInput回答,还要包含一个示例,因为如果可能的话,我没有找到如何使用它来完成工作的示例。

Question A and its answers确实提到过"输入事件和字符之间没有一对一的对应关系#34;这就是为什么我认为PeekConsoleInput不是这个问题很好的解决方案,因为函数实际上是查看事件而不是输入内容。或者,也许有人可以用某种切割方式使用PeekConsoleInput ......

- 更新 - @ mikedu95 起初,我测试了mikedu95的答案,它似乎有效。 但是,睡眠功能不是我想要的。请记住,程序在收听STDIN输入时需要同时执行某些操作。因此我将其修改为以下测试代码:

    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD input_record;
    DWORD nb_read, nb_chars = 0, i;
    string line;

    printf("You have 5 seconds to type some text\n");

    while (true) {
        bool status = PeekConsoleInput(hStdin, &input_record, 1, &nb_read);
        if (!status) {
            int err = GetLastError();
            cout << "err=" << err << endl;
            break;
        }

        ReadConsoleInput(hStdin, &input_record, 1, &nb_read);
        if (input_record.EventType == KEY_EVENT) {
            KEY_EVENT_RECORD record = input_record.Event.KeyEvent;
            if (record.bKeyDown) {
                if (record.uChar.AsciiChar != '\r') {
                    line += record.uChar.AsciiChar;
                    cout << record.uChar.AsciiChar;
                    cout.flush();
                } else {
                    cout << endl << "got line: " << line << endl;
                    line = "";
                }
            }
        }
    }

它基本上有效。然而,它引发了另一个问题:我必须处理原始密钥。它捕获上面代码中line字符串中的每个键,包括shift键,后退空格。另外,我必须将键回到控制台,否则我看不到它正在输入文本。我真的想用cin.getline(buf, size)来获取一行,我可以在点击&#39; Enter&#39;之前编辑该行,并处理最终输入而不是原始输入。

- Update-- 另一个想法是使用cin.rdbuf()->in_avail(),但它似乎不起作用。检查cin.rdbuf() - &gt; in_avail()的while循环永远不会返回0以外的值。事实上,内联编辑功能从未触发过,当我输入一些字符时,我看不到任何回应。

1 个答案:

答案 0 :(得分:0)

事实上,您只是在寻找使用PeekConsoleInput的示例:

#include <Windows.h>

// Ignore events from keys like ctrl, alt, etc.
#define is_char(x) (isprint((x)) || isspace((x)))

int main(void)
{
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD input_records[50];
    DWORD nb_read, nb_chars = 0, i;

    printf("You have 5 seconds to type some text\n");
    Sleep(5000);

    PeekConsoleInput(hStdin, input_records, 50, &nb_read);
    printf("read %u input events\n", nb_read);

    for (i = 0; i < nb_read; i++) {
        if (input_records[i].EventType == KEY_EVENT) {
            KEY_EVENT_RECORD record = input_records[i].Event.KeyEvent;

            if (record.bKeyDown && is_char(record.uChar.AsciiChar)) {
                nb_chars += record.wRepeatCount;
            }
        }
    }

    printf("%u are chars\n", nb_chars);

    return 0;
}