我可以用代码作为输入的方法

Can I make a method with code as input?

本文关键字:输入 方法 代码 我可以      更新时间:2023-10-16

我是c++的初学者,目前使用arduino(类似于c++,我被告知在这里问这个问题)。

我写了下面的代码:
int buttonPinState = digitalRead(buttonPin);
  if (buttonPinState != lastButtonPinState) {
    if (buttonPinState == 1) {  
      counter++; //Any random code goes here.
    }
  }
  lastButtonPinState = buttonPinState;

是否有可能从这段代码中创建一个方法,在这里我可以将"counter++;"更改为我需要执行的任何内容?

你可以使用指向函数的指针作为参数,然后你可以在if块中执行它。

void function(void (*arbitrary_function)()) {
    int buttonPinState = digitalRead(buttonPin);
    if (buttonPinState != lastButtonPinState) {
        if (buttonPinState == 1) {  
            arbitrary_function();
        }
    }
    lastButtonPinState = buttonPinState;
}
void arbitrary_function_1() {
    // some code here
}

void arbitrary_function_2() {
    // some other code here
}
void loop() {
     ...
     function(&arbitrary_function_1);
     ...
     function(&arbitrary_function_2);
     ...
}

可以。我不确定你的问题是否这么简单,如果buttonPinState == 1!=lastButtonPinState,你想执行一个调用

说明您所期待的条件是否为真,即按钮已按下。

你不需要两个单独的if条件,你可以使用&&和做你想做的是

方案1:

int buttonPinState = digitalRead(buttonPin);
  if ( (buttonPinState != lastButtonPinState) && (buttonPinState == 1) ) 
  {  
      counter++; //increment or do anything.
  }
  lastButtonPinState = buttonPinState;

方案二:

通过调用函数

int buttonPinState = digitalRead(buttonPin);
  if ( (buttonPinState != lastButtonPinState) && (buttonPinState == 1) ) 
  {  
      functionCall(); //Call function to execute anything
  }
  lastButtonPinState = buttonPinState;
int functionCall()
{
   counter++;//increment counter
   // do your activity 
   return 0;
}

(我将一般问题与其Arduino特定对偶分开)

一般考虑

推荐: SICP 。它与Arduino无关,但它是一个很好的编程入门,免费提供,并且会教你正确的术语和概念。

[看来你缺少很多通用的编程概念;

你的问题可能不是Arduino特定的,而且与你认为的C或c++的关系更小]

一般来说,看起来您显然想要一流的函数值或元编程工具。因此,请阅读更多关于函数式编程和元编程的内容。对于像Arduino这样的小系统,它可能看起来像一个XY问题,你应该激发你的问题。

第一类函数通常使用闭包实现。C没有它们,而c++只有在c++ 11之后才有它们(但我不确定你的Arduino交叉编译器是否符合c++ 11)。在c++ 11中,您将使用匿名函数、lambda表达式和std::function。

很可能,Arduino上可用的编程语言不提供第一类函数和闭包。然后,您将通过回调使用函数指针(它们存在于普通C99中),即使用附加的约定传递一些客户端数据。然后你可以把这些(函数指针+回调客户端数据)看作是穷人实现闭包的约定。

或者,您可以考虑在运行时生成一些代码,然后调用它。这是元编程的一种形式。你可能想要一些JIT编译库(如GCCJIT或libjit),但这些要求可执行代码可以坐在RAM(如在每一个冯·诺依曼架构),这可能不是许多Arduino板的情况(代码只在Flash ROM中,在一些哈佛架构)。

连续的抽象概念与CPS也间接相关。


返回Arduino:

也许你可以把你的代码想象成某种有限状态或下推堆栈自动机,或者某种字节码解释器。(所以我猜你并不真的需要元编程,或者第一类闭包,即使你的问题与它们有关)。也许可以将每个按钮与一些回调相关联(即使用指针数组和回调客户端数据)。,例如

/// signature of callbacks
typedef void button_callback_sigt(int buttoncode, void*clientdata);
#define NB_BUTTONS 16
struct button_callback_st {
  button_callback_sigt* funptr; // function pointer
  void* data; // client data
};
struct button_callback_st buttoncb[NB_BUTTONS];

然后需要一些其他代码来初始化该数组,并在按下按钮时运行回调(并处理键反弹)。也许一些回调可能会更新这个数组(例如,如果一些按钮是模态的,比如键盘上的shift键)。

您可能希望有一个"通用"事件循环来处理按钮,并删除故障和键反弹(遵循关注点分离设计原则)。一旦确定按钮按下是真实的(不是寄生的),它将调用适当的回调:

int buttonnumber = .... ;
(*buttoncb[buttonnumber].funptr) (buttonnumber, buttoncb[buttonnumber].data);

回调的一个具体例子可能是增加一些全局计数器。这里是相关按钮的编号(实际上,您最好有一个enum来描述按钮)

#define COUNTBUTTON 3

这里是计数器,一个全局变量:

extern int counter;

递增的实际工作在这个回调函数中。它的第二个参数是计数器的地址。

void counter_cbfun(int buttoncode, void*data) {
  int* pc = (int*)data;
  if (buttoncode == COUNTBUTTON)
     (*pc) ++;
};

初始化

  buttoncb[COUNTBUTTON].funptr = counter_cbfun; // function address
  buttoncb[COUNTBUTTON].data = (void*)&counter;

注:发人深省:http://norvig.com/21-days.html