getting out of a loop in C - c

I am trying to get out of a while loop using C, but using breaks, returns or changing the while condition are not working.
Basically, I want to know why in the last else if, when I state back = true my code keeps entering the for.
I would expect an output like: enter1, enter1, enter1, enter1, enter2.
Instead, the output is something like enter1, enter1, enter1, enter2, enter2, enter2, enter1, enter1, enter1....
This is my code work:
void SolveMap8(Core* core_building, Building* new, Stack* solve, bool goingBack){
Core* coreBuilding = core_building;
Building* first = new -> linked[0];
Building* next = NULL;
bool back = goingBack;
while (back == false) {
for (int i = 0; i < (first -> zone -> building_count); i++) {
if (first -> zone -> buildings[i] != NULL) {
if (first != first -> zone -> buildings[i]) {
next = first -> zone -> buildings[i];
if(next -> color == coreBuilding -> buildings[0] -> color && !city_client_is_taken(next)) {
puts("enter0");
Building_Pair* newPair = Building_Tuple_Create(first, next);
stack_push(solve, newPair);
city_client_link(first, next);
break;
}
else if(!city_client_is_taken(next)) {
if (city_client_is_blank(next)) {
if (!(next -> cored)) {
puts("enter1");
Building_Pair* newPair = Building_Tuple_Create(first, next);
stack_push(solve, newPair);
city_client_link(first, next);
SolveMap8(coreBuilding, next, solve, false);
}
}
}
else if (city_client_is_taken(next)) {
if (i == first -> zone -> building_count - 1) {
puts("enter2");
back = true;
}
}
}
}
}
}
}

Update Sorry, missed the recursion. In that case your problem has nothing to do with a missing break statement, but that you are trying to escape from a for loop at a different scope than you are currently in. You will need special logic to handle a global "done" condition. Perhaps something like this:
void process(Core* core, bool& done) {
for (int i = 0; i < core->size() && !done; ++i) {
if (!core[i]->is_taken()) {
process(core[i], done);
} else if (core[i]->is_taken() {
// done procesing
done = true;
}
}
}
// use via
bool done = false;
process(myCore, done);
In the version you have, the goingBack flag is passed by value, so every function gets its own copy and there is no way to pass the value of back to the parent in the recursive call chain. In my code above, done is passed as a reference, so changing the value at some point in the recursion chain will make it visible at parent scope (because the scope of the variable is outside the function itself). Hope this is more helpful.

Related

C: Bus Error between function returns and execution goes back to parent function

To simplify the problem as much as possible, I have two functions, a parent that calls the child. Everything executes okay till it gets to the return of the child function. After that I get a Bus Error.
int main () {
game();
// this doesn't get executed and program fails with bus error
printf("Execute 2");
return 1;
}
int game () {
game_t GameInfo = {.level = 1, .score = 0, .playerCh = 0, .playerX = 1, .playerY = 1};
gameLevel(&GameInfo);
mvprintw(1,1, "Executed");
// code works up to here and get's executed properly
return 1;
};
void gameLevel (game_t *GameInfo) {
// determine the size of the game field
int cellCols = COLS / 3;
int cellRows = (LINES / 3) - 2;
GameInfo -> playerX = 1;
GameInfo -> playerY = 1;
generateMaze(0);
int solved = 0;
int level = GameInfo -> level;
// default player position
getPlayerDefault(GameInfo);
pthread_t enemies_th;
pthread_create(&enemies_th, NULL, enemies, (void *)GameInfo);
// enemies(&level);
while (solved == 0 && GameInfo -> collision != 1) {
printGameInfo(GameInfo);
noecho();
char move = getch();
echo();
if (GameInfo -> collision != 1) {
if (checkMoveValidity(move, GameInfo) == 1) {
solved = movePlayer(move, GameInfo);
if (solved == 1) {
break;
}
}
} else {
break;
}
}
if (solved == 1) {
pthread_cancel(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
return;
}
}
Now, the code is much more complicated than here, but I think that shouldn't have any influence on this (?) as it executes properly, until the return statement. There is also ncurses and multithreading, quite complex custom structures, but it all works, up until that point. Any ideas ?
Tried putting print statements after each segment of code, everything worked up until this.
pthread_cancel() doesn't terminate the requested thread immediately. The only way to know that a cancelled thread has terminated is to call pthread_join(). If the thread is left running, it will interfere with use of the GameInfo variable in the next level of the game if the current level is solved, or may use the GameInfo variable beyond its lifetime if the current level was not solved and the main thread returns back to the main() function.
To make sure the old enemies thread has terminated, add calls to pthread_join() to the gameLevel() function as shown below:
if (solved == 1) {
pthread_cancel(enemies_th);
pthread_join(enemies_th);
GameInfo->level++;
gameLevel(GameInfo);
} else {
// game over
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return;
}
The use of tail recursion in gameLevel() seems unnecessary. I recommend returning the solved value and letting the game() function start the next level:
In game():
while (gameLevel(&GameInfo)) {
GameInfo.level++;
}
In gameLevel():
int gameLevel(game_t *GameInfo) {
/* ... */
pthread_cancel(enemies_th);
pthread_join(enemies_th);
return solved;
}

Passing a void (*fn) from a class

I'm writing an auto display turn-off function with ESP32 on Arduino framework with PIO.
I have a Screen class for handling all of the screen functions.
void Screen::turn_off_screen(){
digitalWrite(SCREEN_ENABLE, LOW);
}
void turn_off_screen_wrapper()
{
Serial.println("turn_off_screen_wrapper called");
if (c_screen_Instance != nullptr)
{
c_screen_Instance->turn_off_screen();
}
}
void Screen::auto_display_power_off(int timeout){
Serial.println("auto_display_power_off called");
c_screen_Instance = this;
auto_off_timer = timerBegin(0, 80, true);
Serial.println("auto_off_timer ran");
timerAttachInterrupt(auto_off_timer, &turn_off_screen_wrapper, true);
Serial.println("timerAttachInterrupt ran");
//Converts given seconds from us to seconds
timerAlarmWrite(auto_off_timer,timeout*1000000,false);
timerAlarmEnable(auto_off_timer);
}
The code compiles however I get this when I run it on the board.
auto_display_power_off called
[E][esp32-hal-cpu.c:93] addApbChangeCallback(): duplicate func=400811F8 arg=3FFBDC54
auto_off_timer ran
The screen never gets turned off of course since the callback never runs. Any ideas why this is happening?
is c_screen_Instance global?
is auto_off_timer global?
Consider providing a bit more of your code.
But anyway.
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
initApbChangeCallback();
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
if(!c){
log_e("Callback Object Malloc Failed");
return false;
}
c->next = NULL;
c->prev = NULL;
c->arg = arg;
c->cb = cb;
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
if(apb_change_callbacks == NULL){
apb_change_callbacks = c;
} else {
apb_change_t * r = apb_change_callbacks;
// look for duplicate callbacks
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
if (r) {
log_e("duplicate func=%8p arg=%8p",c->cb,c->arg);
free(c);
xSemaphoreGive(apb_change_lock);
return false;
}
else {
c->next = apb_change_callbacks;
apb_change_callbacks-> prev = c;
apb_change_callbacks = c;
}
}
xSemaphoreGive(apb_change_lock);
return true;
}
This is addApbChangeCallback's declaration.
Your error comes from this line :
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
Where r it's a struct to hold all the callbacks.
This error indeed indicates this callback function was already assigned somewhere in your code. r is global, so your code is re-assigning the same callback twice.
Try to either only assign it once, or to unassign the function before assigning it again with removeApbChangeCallback(void * arg, apb_change_cb_t cb) or timerDetachInterrupt
I've also found a reported issue related to timerAttach on the current version here: https://github.com/espressif/arduino-esp32/issues/6730
Try to roll back the Platform PIO's version to a more stable one:
# instead of espressif32
platform = https://github.com/platformio/platform-espressif32.git#<tag-version>
Check on the git link for the available tags you can use.
Problem was that I was attaching the interrupt in the void loop(). Which would run way faster than the actual timer. After moving it to setup (Setup being a placeholder) I plan on having it on a Hardware interrupt it worked as expected.

Checking a Point Value exists in Array before calling to it

I'm trying to compare the X value of two points in two different arrays. Problem is sometimes the value I'm comparing may not exist yet and I'm not entirely sure how to go about making this check before I call upon this variable.
My code looks like this
if (blueShipPositions[0].x == redShipPositions[0].x) {
trace("Match in" + blueShipPositions[0]);
}
The x value for any given point in this array tops out at 4 so the error I'm running into looks like this
if (blueShipPositions[0].x == redShipPositions[4].x) {
trace("true");
}
If redShipPositions[4].x does not exist yet I get an error.
I am aware of the IndexOf function, I just don't know how to apply it here.
Wrap it inside an IF statement that determines the size of an array:
if (redShipPositions.length >= 5) {
if (blueShipPositions[0].x == redShipPositions[4].x) {
trace("true");
}
}
Another way is to have an int local variable to indicate the size of the array:
myArraySize = redShipPositions.length;
then you can use it as an indicator/(stop point) to safely execute your code w/o the concern of IndexOutOfBound exception.
As answer to your question, take this example : (comments inside)
var array:Array = new Array(1, 5, 6, 55)
var index:Number = 3
// type of the elements of array, in this case is Number
var element_type:* = Number
// so to verify if the array[index] exists, we can use
if(array[index]) {
trace(array[index])
}
// or
if(array[index] != undefined) {
trace(array[index])
}
// or
if(array[index] != null) {
trace(array[index])
}
// or
if(typeof array[index] != 'undefined') {
trace(array[index])
}
// or
if(array[index] is element_type) {
trace(array[index])
}
// or
if(array[index] as element_type != null) {
trace(array[index])
}
// or
// here you have to put in the mind that arrays in ActionScript starts always from the index 0, thats why we use < and not <=
if(index < array.length) {
trace(array[index])
}
// we use array.indexOf to search an element and not an index
if(array.indexOf(55)){
trace('we have "55" in this array')
} else {
trace('we don\'t have "55" in this array')
}
For more details about AS3 Array object, take a look here : Adobe.com : AS3 Array.
Hope that helps you.

How can we ensure that a while loop would not be an infinite loop?

This is a method where I am using the while loop. I strongly suspect that an infinite loop is possible. How to check and eliminate that?
I am using two while loops here. Sould I totally dismantle the while loop?
public class ReferenceListSaveHandler
{
public PublishReferenceListUpdates populateResponse(SearchQueryResponse pSearchQueryResponse,SearchQueryResponse pListResponse, ObjectFactory objFactory) throws IOException, ParserConfigurationException, SAXException,SipException, Exception
{
ReferenceDataProcessor lRefPro = new ReferenceDataProcessor();
PublishReferenceListUpdates lResponse = null;
Record listRecord = null;
ReferenceDataListItemListType lReferenceDataListItemListType = objFactory
.createReferenceDataListItemListType();
ReferenceDataListType lReferenceDataListType = null;
ReferenceDataListItemType lReferenceDataListItemType = null;
boolean ifSynonym = false;
String lRowIdObject = null;
final int lRowIdLength = 14;
if (refListItemItr.hasNext())
{
Record record = (Record)refListItemItr.next();
boolean continueProcessing = true;
boolean lastRecord = false;
while (continueProcessing)
{ // first use of while loop
if (refListItemItr.hasNext() || lastRecord)
{
continueProcessing = true;
lastRecord = false;
}
else
{
continueProcessing = false;
}
if (continueProcessing)
{
lSynonymListType = objFactory
.createSynonymListType();
Field itemLSIDField = record
.getField(ReferenceDataConstants.FIELD_COMPOUND_ASSET_ID);
if (itemLSIDField == null)
{
continue;
}
else
{
currentItemLSID = itemLSIDField
.getStringValue().trim();
}
lReferenceDataListItemType = objFactory
.createReferenceDataListItemType();
lReferenceDataListItemType = setListDetails(record,
lReferenceDataListItemType,
lId, lName, objFactory);
while (refListItemItr.hasNext()
&& continueProcessing)
{ // second use of while loop
SynonymType lSynonymType = null;
if (continueProcessing)
{
if (lSynonymType != null)
lSynonymListType.getSynonym().add(lSynonymType);
}
}
continueProcessing = true;
}
}//while loop
}
}
}
Please help.
Problem number one: refListItemItr, whatever that is (its definition is not shown), has a .next() method but it's never called inside the loop.
Problem number two: The second while loop is always infinite if you enter it:
while (refListItemItr.hasNext()
&& continueProcessing)
{
SynonymType lSynonymType = null;
if (continueProcessing)
{
if (lSynonymType != null)
lSynonymListType.getSynonym().add(lSynonymType);
}
}
Neither refListItemItr.hasNext(), nor continueProcessing can change inside this loop. That's why it's an infinite loop.
EDIT:
I can't tell you how to change the code because there are many possible ways to change it, depending on what's supposed to happen. You can try this but it may or may not work:
Remove the second loop entirely (it does nothing right now).
Add this line just before the end of the first loop:
record = (Record)refListItemItr.next(); // ADD THIS LINE
} //while loop BEFORE THIS LINE
This is an infinit loop , the outer loop depends on lastrecord which is not beeing set to true anywhere in the program
I throw in a loop counter whenever I write the word while, like this:
int loopCounter = 0, maxLoops = 1000; //just an example
while((loopCounter++) < maxLoops && (myConditions))
{
// loop away, this can't ever be infinite
}
or this
int loopCounter = 0, maxLoops = 1000; //just an example
do
{
// loop away, this can't ever be infinite
}
while((loopCounter++) < maxLoops && (myConditions))
Of course, maxLoops is always sized to be orders of magnitude greater than any reasonable number of iterations... Then I add a check:
if (loopCounter == maxLoops) { throw new InvalidOperationException("Infinite loop detected!"); }

Loop flow control

I have an array of objects, each object has a function that returns a Boolean value. What I need to do, is have a loop continuously running until each object returns a true value when the function is called on each object.
EDIT: Sorry I wasn't clear enough, I meant that I want the loop to break, when ALL of the objects functions return true.
Any ideas?
Java style syntax:
boolean good;
while (true) {
good = true;
foreach (MyObject o : myArray) {
if (!o.someFunction()) {
good = false;
break;
}
}
if (good) break;
}
I interpreted it as meaning that every object needed to have its function evaluated to true each time, and once they all evaluate to true break out of the loop.
If I got your question, you can do like this...
do
{
test = 0;
for(all functions)
{
char test_array[] = function_call();
}
int i = 0;
for(test_array.length)
{
if(test_array[i] == true)
{
count_no_true = i++;
}
}
if(count_no_true == no of function)
{test == 1;}
else
{test == 0;}
}while(test == 1)

Resources