我认为你会从对程序如何流动的大量思考中受益匪浅。现在,我可以推断出您的程序流程是:
- 您有一个外部循环来检查至少一个通道 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 区域,不如每次返回,并检查您的值以查看您是否还在那里。这是关键点 - 你的功能应该是快速的,而不是垄断你的处理器。让每个函数只做一种事情,并让所有控制都来自主循环。
我对您的代码进行了很多更改,我不知道您是否可以进行所有更改,但是您需要类似的东西。它更加强大,并为您提供全方位成长的空间。