【问题标题】:Catch user input when running while loop in C在 C 中运行 while 循环时捕获用户输入
【发布时间】:2020-10-03 16:51:56
【问题描述】:

我用 C 编写了一个斐波那契数列。它运行良好,并且提供的数字也超过 3e100。

但我的问题是,用户想要在中间停止打印过程并退出循环,如何捕获用户输入?

例如,如果他输入他想要系列的前 100 个数字,然后改变主意并想退出打印过程,而它在中间。该怎么做?

我想过在循环运行时捕获^c (CTRL+C),但我不确定如何做到这一点。

这是我的代码:

printf("Welcome to Fibonacci Series Mode.\n\nEnter how many numbers do you want from the series, from the start: ");
scanf("%d", &N);
x = 0;
y = 1;
F = 3;
Numbering = 3;
printf("Here is Your Series:\n\n");
if (N == 1)
{
    printf("[1] 0\n");
    Sleep(1000);
}
if (N == 2)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(1075);
}
if (N == 3)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(75);
    printf("[3] 1\n");
    Sleep(1075);
}
if (N > 3)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(75);
}
while (N > 3 && F <= N)
{
    xy = x + y;
    printf("[%.0d] %.5g\n", Numbering, xy);
    Sleep(75);
    x = y;
    y = xy;
    F++;
    Numbering++;
}
Sleep(1000);
}

这只是我整个代码的一部分,我没有在这里包含,这就是为什么你看不到 main() 和头文件的原因。

【问题讨论】:

  • 是否存在非法值,如-1
  • @FiddlingBits 我不这么认为。导致其所有正整数
  • 这能回答你的问题吗? Ctrl + C interrupt event handling in Linux
  • @FiddlingBits 我理解负数的部分,但是我如何在循环运行时捕获负数?
  • 我看不出有什么问题:Ctrl-C 将中断您的程序,而无需您做任何特别的事情。所以我不确定你是否尝试过你想要的:你可能会对它已经工作感到惊讶。 Ctrl-C 将立即结束程序,然后用户可以使用不同的输入重新运行它。如果你想要一些其他的行为,你必须用简单的英语陈述你想要的。

标签: c loops input


【解决方案1】:

在 C 中,IO 默认是阻塞的。所以如果你想在循环过程中收听用户输入,你必须等待用户的输入才能继续。

解决方案是使用signals。特别是 SIGINT 与 CTRL + C。现在 可以在您的程序端捕获此信号以进行一些清理或您想要的任何其他操作。您可能关心的是在收到SIGINT 时创建一个优雅退出的函数,而不是在打印期间立即退出。

如果你想捕捉信号,你可以使用这个-

#include  <signal.h>

void SIGINT_handler(int sig)
{
     // Ignore the signal's default behaviour
     signal(sig, SIG_IGN);
     // Do graceful printing/cleanup here
     exit(0);
}

现在你需要把这个函数绑定到SIGINT,你可以在main中做这个

signal(SIGINT, INThandler);

注意:这是一个非常简单的示例,旨在为您指明正确的方向。由于您在代码中使用了printf,因此中断。

IO 期间的信号拦截很难做到正确。如果信号在printf 调用过程中被调用怎么办? 行为可能不是您希望的样子

更多信息here

【讨论】:

  • 那么用户在打印过程的任何时候输入^c 都会终止这个过程?但我希望它只是暂停打印过程,验证是否真的要退出,然后退出,不是整个程序,而是整个代码的前一部分(刚刚退出循环)。而在验证过程中,如果用户不小心点击了^c,想要继续打印过程怎么办?对于这种情况,它使用if-elseBreak;continue; 吗?
  • @UnfreeHeX 在拦截信号时,可以使用任何控制语句甚至 IO 来确认用户是否真的想退出之类的东西。只需确保在while 循环中使用可由信号处理程序修改的条件。因此,一旦触发信号处理程序,它就可以停止循环。
  • 使用信号是正确的方法。 -- 但是请阅读并理解信号处理的文档。信号处理程序中的标准 I/O 可能不是最好的主意。在你做对之前可能需要一些实验。此外,如果您打算在信号处理程序和循环之间使用一些公共变量,则需要阅读volatile。 -- 我多年前遇到的一个突出的信号示例是dd,它在接收到信号 USR1 时打印其当前进度。也许您喜欢研究它的来源。
  • @UnfreeHeX 如果您认为这篇文章回答了您的问题,请考虑通过单击投票旁边的勾号将其标记为答案。这可能会帮助将来寻找您问题的人:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 2020-02-15
  • 2017-08-29
  • 2020-02-12
相关资源
最近更新 更多