【问题标题】:Reading a value with a timer in C在 C 中使用计时器读取值
【发布时间】:2016-07-26 15:07:43
【问题描述】:

我正在编写一个乘法表程序来帮助我的侄女学习。我希望她能够有一定的时间来回答每个问题(因此 for 循环起到了延迟的作用)。延迟有效,因为在 delay 秒后程序输出“时间到了”!但是,程序仍然等待我输入一个值并在它评估 answer 之前按 enter 并检查它是“正确”还是“错误”(这不是通过放置 printf 和 scanf在for循环之后一起在循环内)。我知道延迟只是等待几秒钟,然后正常继续,这就是为什么我需要输入一个数字并按 Enter 键。但是,我不知道如何解决这个问题。

基本上,我希望程序在 delay 秒后自动“输入”并且她没有输入值,从而导致答案为“错误”。但是,如果她输入一个值并在 delay 秒结束之前按 Enter,我仍想检查它是“正确”还是“错误”。我已经寻找其他方法来做到这一点,但我根本无法做到这一点。这是到目前为止的代码(再次,我知道 for 循环延迟只会让程序等待 delay 秒,然后才能正常继续,但我不知道如何解决这个问题。

time_t start_time = 0;
int delay = 0;
int answer = 0;
int correct = 0;
int wrong = 0;

printf("How long should the delay be?:\t");
scanf("%d", &delay);

start_time = clock();
printf("\n2 x 4 =\t");

for( ;clock() - start_time <= delay*CLOCKS_PER_SEC; );

printf("\n\nTime's up!\n\n");
scanf("%d", &answer);

if(answer == 8)
{
    printf("\nCorrect!\n");
    ++correct;
}
else if(answer != 8)
{
    printf("\n\aWrong!\n");
    ++wrong;
}

编辑:我正在运行 Windows 并使用带有 mingw32 的 CodeBlocks。我只是希望程序是一个简单的 .exe 文件,它将通过 CMD 运行。 (虽然它已经这样做了)。

【问题讨论】:

  • 这在很大程度上取决于操作系统(Windows、Linux、...)。
  • 我问过了,但是当我问了一个几乎没有代码的问题时,有人将我引导到一个带有计时器的网页,我检查了那个网页,这就是我已经走了多远,但是我现在很难过。我将使用我的操作系统、IDE 和编译器编辑帖子。
  • 看看this SO question,但这并不简单。您可能需要重写输入函数来替换 scanf (无论如何这是个好主意,因为如果无法预测用户输入,则 scanf 非常糟糕)。
  • 最简单直接的方法是使用 threads
  • @n.m.:另一个线程将如何提供帮助?您仍然必须取消计时器以响应正确的输入,并取消输入以响应经过的计时器。通过在问题上抛出一个新线程都不能启用任何一个。您需要异步调用。多线程在这里是错误的异步方式。

标签: c winapi windows-console


【解决方案1】:

scanf() 无法实现您的目标,因为它是一个阻塞调用 - 在用户输入输入之前不会执行下一个代码行。这不是你想要的。

您可以使用另一个库函数kbhit() - 如果按下任何键,它将返回 > 0。但它不会告诉你按下了哪个键。为此,您必须致电getch()

kbhit 是 conio.h 的一部分

所以你的代码是:

bool bAnswered = false;
for( ;clock() - start_time <= delay*CLOCKS_PER_SEC; )
{
     if(kbhit() > 0)  //Some key is pressed
       {
           answer = getch(); //Read that key
           bAnswered = true; // User has answered 
       }
}

// Print message if there wasn't any key press.
if(bAnswered == false)
{
printf("\n\nTime's up!\n\n");
}

if(answer == 8)
{
    printf("\nCorrect!\n");
    ++correct;
}
else if(answer != 8)
{
    printf("\n\aWrong!\n");
    ++wrong;
}

上述代码的问题是您一次只能读取 1 个字符。我把它留给你实施。 此外,您需要编写额外的代码将 ASCII 转换为整数,因为 getch() 返回 ASCII 字符。

【讨论】:

  • 谢谢,辛苦了这么久。我是 C 的新手,人们一直对我的帖子投反对票,但事实是我仍在努力学习很多东西。再次感谢您。
  • OK 现在在此之上实现行编辑(除非您打算惩罚用户的可纠正拼写错误)。
【解决方案2】:

大部分有效。当用户开始输入然后超时到期时,我无法测试这种情况。我认为它应该在 Windows 中工作,但我只能在不太理想的 Windows 仿真下进行测试。用户可能必须在输入下一个答案之前按退格键。

#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>

int answer = 0;

DWORD WINAPIinput_thread(void*) 
{
    scanf("%d", &answer);
    return 0;
}

int main()
{
    srand(time(0));

    HANDLE h = (HANDLE)_beginthreadex(0, 5000, input_thread, 0, 0, 0);
    while (1) {
        int u = rand() % 7 + 2;
        int v = rand() % 7 + 2;
        printf ("%d * %d = ?   ", u, v);

        DWORD res = WaitForSingleObject(h, 20000);

        if (res == WAIT_TIMEOUT)
        {
            printf ("\nSorry, timed out!\n");
            FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
        }
        else
        {
            if (answer == u * v)
            {
                printf ("Congrats, you won!\n");
            }
            else
            {
                printf ("Sorry, wrong answer!\n");
            }
            CloseHandle(h);
            h = (HANDLE)_beginthreadex(0, 5000, input_thread, 0, 0, 0);
        }
    }

}

【讨论】:

    【解决方案3】:

    感谢您花时间确保您的侄女学习数学!我们都需要更多的技能。

    https://gist.github.com/DaemonDave/b2eda8f9fa6b8bbf90a5e1fc1147a461

    &lt;script src="https://gist.github.com/DaemonDave/b2eda8f9fa6b8bbf90a5e1fc1147a461.js"&gt;&lt;/script&gt;

    这是一个可以在带有 GCC 的 Ubuntu Linux 上运行的 math-tester.c 文件。你不需要conio,我找到了一个函数。

    我使用 3 件事来实现对您的要求的更改。我使用 kbhit 来测试要检查的字符,我使用 sleep 在 while 循环中等待第二个间隔,我使用命令行输入来询问以秒为单位的时间延迟。

    享受吧!

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多