【问题标题】:Break loop with keyboard input (R)带键盘输入的中断循环 (R)
【发布时间】:2016-12-09 20:45:51
【问题描述】:

我需要一个 R 循环来继续运行,直到用户按下一个键。像下面这样的东西。有任何想法吗?我是 R 新手

while(FALSE_after_user_input){
  queryWebApi()
  Sys.sleep(1)
}

编辑 1

我真正追求的是一种停止数据收集的方法。我有一个功能,我想每隔几秒钟运行一次来​​查询新数据。用户需要能够停止数据收集循环。

readline() 不起作用,因为它会停止执行数据收集循环

【问题讨论】:

    标签: r while-loop rstudio


    【解决方案1】:

    建议一: TCL/TK

    library(tcltk)
    win1 <- tktoplevel()
    butStop <- tkbutton(win1, text = "Stop",
      command = function() {
        assign("stoploop", TRUE, envir=.GlobalEnv)
        tkdestroy(win1)
    })
    tkgrid(butStop)
    
    stoploop <- FALSE
    while(!stoploop) {
        cat(". ")
        Sys.sleep(1)
    }
    cat("\n")
    

    部分代码借鉴自:A button that triggers a function call

    建议 2: 对标准输入进行非阻塞检查。 (请注意:C 不是我的核心能力,我是从网上的一些东西拼凑起来的。)主要思想是在C 中编写一个等待用户输入的函数,并从@987654328 调用它@。

    以下片段改编自Non-blocking user input in loop。将以下代码另存为kbhit.c

    #include <stdio.h>
    #include <unistd.h>
    #include <R.h>
    
    void kbhit(int *result)
    {
        struct timeval tv;
        fd_set fds;
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        FD_ZERO(&fds);
        FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
        select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
        *result = FD_ISSET(STDIN_FILENO, &fds);
    }
    

    然后,从命令行运行 R CMD SHLIB kbhit.c 将其编译为 R

    最后,在R 中,加载新创建的kbhit.so,编写一个返回C 函数输出的函数(kbhit),然后运行你的循环。 kbhit() 除非收到回车键,否则返回 0。请注意,停止循环的唯一方法是按 enter/return(或硬中断)——如果您想要更灵活的方法,请参阅上面的链接。

    dyn.load("kbhit.so")
    
    kbhit <- function() {
        ch <- .C("kbhit", result=as.integer(0))
        return(ch$result)
    }
    
    cat("Hit <enter> to stop\n")
    while(kbhit()==0) {
        cat(". ")
        Sys.sleep(1)
    }
    

    More details on the .C interface to R.

    在 Windows 机器上:

    kbhit.c

    #include <stdio.h>
    #include <conio.h>
    #include <R.h>
    
    void do_kbhit(int *result) {
        *result = kbhit();
    }
    

    R:

    dyn.load("kbhit.dll")
    
    kbhit <- function() {
        ch <- .C("do_kbhit", result=as.integer(0))
        return(ch$result)
    }
    
    cat("Hit any key to stop\n")
    while(kbhit()==0) {
        cat(". ")
        Sys.sleep(1)
    }
    

    附:我通过谷歌搜索把它破解了,所以不幸的是我不知道它是如何工作的或为什么工作(如果它对你有用的话!)。

    【讨论】:

    • 谢谢@WeihuangWong 没有图形用户界面有没有办法做到这一点? TCL/TK 是 GUI 库,对吗?如果情况变得更糟,我可以使用带有停止按钮的 GUI。
    • 编译器不高兴。我添加了#include &lt;sys/time.h&gt; #include &lt;Winsock2.h&gt;,现在我收到以下错误undefined reference to _imp__select@20' undefined reference to __WSAFDIsSet@8'
    • 您运行的是 Windows 吗?我在conio.h 中看到了使用kbhit 函数的示例,这可能对您有用。
    • 我在一台 Windows 机器上。你能提供一个使用 conio.h 的例子吗?我是一名 C#/JavaScript 开发人员,多年未接触 C。
    • 我试图通过 RStudio 运行它。我会将您的答案标记为正确,我已经协商了要求,因此我不再需要实施它。感谢您的帮助@WeihuangWong
    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多