code cũ anh đang đọc lại :V
cách này hạn chế ở chỗ mình phải tự xử lý ký tự nhập vào, có thể là phím mũi tên hoặc nút HOME/END, backspace, del, v.v… rồi in ra tương ứng. Vì phải tự xóa dòng rồi in ra lại mỗi lần có keyboard input nên hàm timedLineInput phải hạn chế số lượng ký tự nhập vào để ko có xuống dòng trong console :V
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <conio.h>
#include <windows.h>
std::string timedLineInput(std::chrono::milliseconds waitDuration, size_t maxLen = 60, bool showTimer = true,
                           DWORD sleepDurationPerFrame = 30);
int main() {
    std::string s = timedLineInput(std::chrono::seconds(5), 10);
    std::cout << s << "\n";
}
std::string timedLineInput(std::chrono::milliseconds waitDuration, size_t maxLen, bool showTimer,
                           DWORD sleepDurationPerFrame) {
    std::string buff;
    size_t cursorIndex = 0;
    using namespace std::chrono;
    const auto deadline = steady_clock::now() + waitDuration;
    bool dirty = true;
    for (;; Sleep(sleepDurationPerFrame)) {
        if (steady_clock::now() >= deadline) { // time's up
            if (showTimer) std::cout << "\r" << std::fixed << std::setprecision(2) << std::setw(5) << 0.0;
            break;
        }
        if (showTimer) dirty = true;
        if (_kbhit()) {
            dirty = true;
            int ch = _getch();
            if (ch == '\r' || ch == '\n') break; // break at \r or \n
            if (ch == '\b') {                    // backspace
                if (!buff.empty()) {             // there is character to delete
                    buff.erase(--cursorIndex, 1);
                    printf("\b \b"); // delete last character on screen (a hack)
                }
            } else if (ch == 0xE0) { // DEL, arrow keys, ... emits 2 characters 0xE0
                ch = _getch();       // and this character
                if (ch == 0x53) {    // DEL
                    if (!buff.empty()) {
                        if (cursorIndex == buff.size()) {
                            buff.erase(--cursorIndex);
                            printf("\b \b");
                        } else {
                            buff.erase(cursorIndex, 1);
                        }
                    }
                } else if (ch == 0x4b) { // left arrow
                    if (cursorIndex > 0) cursorIndex--;
                } else if (ch == 0x4d) { // right arrow
                    if (cursorIndex < buff.size()) cursorIndex++;
                } else if (ch == 0x47) { // Home
                    cursorIndex = 0;
                } else if (ch == 0x4f) { // End
                    cursorIndex = buff.size();
                }
            } else if (buff.size() < maxLen) {
                buff.insert(cursorIndex++, 1, ch);
            }
        }
        if (dirty) {
            std::cout << "\r" << std::string(10 + maxLen, ' ') << '\r'; // clear line
            if (showTimer) {
                const duration<double> timeLeft = deadline - steady_clock::now();
                std::cout << std::fixed << std::setprecision(2) << std::setw(5) << timeLeft.count() << "s    ";
            }
            std::cout << buff;
            std::cout << std::string(buff.size() - cursorIndex, '\b');
            std::cout << std::flush;
        }
        dirty = false;
    }
    std::cout << "\n";
    return buff;
}
edit: code cũ cũ nữa ko xài <chrono>:
#include <conio.h>
#include <windows.h>
#include <string>
#include <iostream>
#include <cstdio>
///////////////////////////////////////////////////////////////////////
/// \brief Input with time limit.
/// Prevent user from inserting more input after time limit has been spent.
/// \param timeLeft Time limit, in milliseconds.
/// \param maxLen Maximum input length (to prevent long input that
/// causes a new line).
/// \return Input string.
///////////////////////////////////////////////////////////////////////
std::string timedLineInput(unsigned int timeLeft, size_t maxLen = 40);
int main()
{
    std::string s = timedLineInput(11000);
    std::cout << s << "\n";
}
std::string timedLineInput(unsigned int timeLeft, size_t maxLen)
{
    std::string buff;
    size_t cursorIndex = 0;
    DWORD deadline = GetTickCount() + timeLeft;
    while (1)
    {
        DWORD now = GetTickCount();
        timeLeft = deadline < now ? 0 : deadline - now;
        if (!timeLeft) break;
        if (kbhit())
        {
            int ch = getch();
            if (ch == '\r' || ch == '\n') break;
            if (ch == '\b') //backspace
            {
                if (!buff.empty()) //there is character to delete
                {
                    buff.erase(--cursorIndex, 1);
                    printf("\b \b"); //delete last character on screen (a hack)
                }
            }
            else if (ch == 0xE0) //DEL, arrow keys, ... emits 2 characters 0xE0
            {
                ch = getch();    //and this character
                if (ch == 0x53) //DEL
                {
                    if (!buff.empty())
                    {
                        if (cursorIndex == buff.size())
                        {
                            buff.erase(--cursorIndex);
                            printf("\b \b");
                        }
                        else
                        {
                            buff.erase(cursorIndex, 1);
                        }
                    }
                }
                else if (ch == 0x4b) //left arrow
                {
                    if (cursorIndex > 0) cursorIndex--;
                }
                else if (ch == 0x4d) //right arrow
                {
                    if (cursorIndex < buff.size()) cursorIndex++;
                }
                else if (ch == 0x47) //Home
                {
                    cursorIndex = 0;
                }
                else if (ch == 0x4f) //End
                {
                    cursorIndex = buff.size();
                }
            }
            else if (buff.size() < maxLen)
            {
                buff.insert(cursorIndex++, 1, ch);
            }
        }
        printf("\r%79s", ""); //clear line
        //5 is magic number for time limit < 100s.
        //For 100s < time limit < 1000s use 6, or convert to minutes...
        printf("\r%5.2fs    %s", timeLeft / 1000.0, buff.c_str());
        //set cursor position without gotoxy...
        printf("\r%5.2fs    %s", timeLeft / 1000.0, buff.substr(0, cursorIndex).c_str());
        Sleep(64); //decrease this number until there is no blinking on screen
    }
    printf("\r%5.2fs    %s\n", timeLeft / 1000.0, buff.c_str());
    return buff;
}
xài <chrono> đẹp hơn ở chỗ nhập vào seconds hay milliseconds gì nó cũng rõ ràng =]