【问题标题】:Returning program to pre-triggered state将程序返回到预触发状态
【发布时间】:2013-03-17 18:02:06
【问题描述】:

首先这会被触发:

if ((temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) | (temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit))
     activateAlarm(channelID);

激活警报被触发,然后从那里:

void activateAlarm(int channelID);   
{  while (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit || temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit)
   {    
    logSubsystem(temperatureChannel[channelID].currentTemperature); 
   }    
}

然后在以下情况下触发警报屏幕:

int logSubsystem(int currentTemperature)

case 'F': //if user input is 'F'
case 'f': //if user input is 'f'        

            currentTemperature--;
            printf("your current exceeded temp is %i\n \n", currentTemperature);    
            if (currentTemperature <= 100 || currentTemperature >= 50);
                  compareLimit();
                break; //exits loop

如何设置此功能,以便如果用户使用 F 递减并使当前温度低于限制(50),那么它将返回到 compareLimit 功能和要求上限/下限触发状态为FALSE,程序恢复到原来的预警状态?

【问题讨论】:

  • 上下文不足。根据您的问题,您可能需要:1. while 循环,2. longjmp(),3. ???
  • 我还能给你看什么?我只是不想用不必要的代码给你增加负担
  • 这也很好。特别是,我很想知道activateAlarm() 函数的作用。
  • 它用于创建一个while循环条件,以便如果温度处于高/低限制区域,那么它会初始化logSubSystem,这是一组允许用户打印的case语句小消息。但是,我想弄清楚的是,他们在进入 logSubSystem 后如何回到 main
  • 顺便说一句,您的第一个代码中有错误。您使用了按位或而不是逻辑或。

标签: c function operators


【解决方案1】:

我认为你会从对程序如何流动的思考中受益匪浅。现在,我可以推断出你的程序流程是:

  • 您有一个外部循环来检查温度,至少在一个通道 ID 上。在该循环中,您有第一次向我们展示的 if 语句。
  • 然后激活警报会做一些其他的事情,但循环直到温度下降,调用logSubsystem
  • logSubsystem 然后大概会获取某种用户输入,然后您希望它从那里调用您的初始函数,大概称为准备限制。

问题是这些功能都没有完成。他们都互相调用,你最终会得到一个堆栈溢出。很好,因为这是该网站的名称,但不是您想要的。

您基本上需要的是一个状态机。您需要跟踪值、查看这些值并调用对这些值进行操作的返回函数。应该只有一个循环,它应该根据这些值来控制所发生的一切。好消息是,您已经准备好所有这些了。 temperatureChannel 正在为您跟踪值,并且您有很多 while 循环。

让我给你我建议你的程序应该流动的方式:

bool checkTemperatureValuesOutOfRange(int channelID) {
    // this is just a convenience, to make the state machine flow easier.
    return (temperatureChannel[channelID].currentTemperature > temperatureChannel[channelID].highLimit) || // note the || not just one |
           (temperatureChannel[channelID].currentTemperature < temperatureChannel[channelID].lowLimit);
} 

void actOnUserInput() {
    char input = // ... something that gets a user input.  It should check if any is available, otherwise return.
    switch (input) {
        case 'F':
        case 'f':
             temperatureChannel[channelID].currentTemperature--;
             break; // This doesn't exit the loop - it gets you out of the switch statement
}

void activateAlarm(int channelID) {
    // presumably this does something other than call logSubsystem?
    // if that's all it does, just call it directly
    // note - no loop here
    logSubsystem(channelID); 
}

void logSubsystem(int channelID) { // Not the current temperature - that's a local value, and you want to set the observed value
    // I really think actOnUserInput should be (an early) part of the while loop below.
    // It's just another input for the state machine, but I'll leave it here per your design
    // Presumably actually logs things, too, otherwise it's an unnecessary function
    actOnUserInput();
}

while (TRUE) { // this is the main loop of your function, and shouldn't exit unless the program does
    // do anything else you need to - check other stuff
    // maybe have a for loop going through different channelIDs?
    if (checkTemperatureValuesOutOfRange(channelID)) {
         activateAlarm(channelId);
    // do anything else you need to
}

我相信您可以看到您的代码和我的代码之间存在很多差异。以下是一些需要考虑的关键事项:

  • 现在所有函数都返回了。主 while 循环调用检查状态的函数,并调用更改状态的函数。
  • 我强烈建议将用户输入作为主 while 循环的一部分。这只是状态机的另一个输入。获取它,采取行动,然后检查您的状态。您可能需要从用户那里获得一些意见,否则您一开始就永远不会陷入糟糕的状态。
  • 现在,每次都会发生激活警报。使用您显示的代码,这很好 - 因为 logSubsystem 是所有被调用的。如果您只希望警报响一次,请在 temperatureChannel[channelId] 中保留一个布尔跟踪器,表示警报是否响起,在 activateAlarm 中将其设置为 true,然后根据 checkTemperatureValuesOutOfRange 的返回值将其重置为 false。
  • 与其将自己留在 activateAlarm/logSubsystem 区域,不如每次返回,并检查您的值,看看您是否还在那里。这是关键点 - 你的功能应该是快速的,而不是垄断你的处理器。让每个函数只做一种事情,并让所有控制都来自主循环。

我对您的代码进行了很多更改,我不知道您是否可以进行所有更改,但您需要类似的东西。它更加强大,并为您提供全方位成长的空间。

【讨论】:

  • Scott...非常感谢您深思熟虑的回复...我不知道这种情况是堆栈溢出,但这是我学到的其他东西 :) 不过我在想我需要在函数之后停止调用函数,并专注于从我的 main 调用它们,而不是别的。非常感谢您的回复...
  • 没问题。每次添加函数时,都会将其推入函数堆栈。这是分配包含可执行语句的所有内存和包含局部变量的所有内存的地方。 (当您退出该函数时,它会从堆栈中弹出。)每个操作系统对您可以放入堆栈的数量都有一些限制(当然,这可能是“所有可用内存”)。尤其是在一个看起来打算永远运行的系统上,不断添加功能最终会让你溢出这个限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
相关资源
最近更新 更多