HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Looping input function

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
inputloopingfunction

Problem

Currently, I have a function that loops to gather input for program execution, but I feel that it is a bit lacking, overthought and unoptimized. I would love any input on the process, coding style, or usability of the function.

I feel like the use of while (true) is not really optimized here.

My code uses curses and unistd.h.

// Heart of the display of the program
void startEvolutionLoop (Grid* grid, size_t speed) {
    clear();

    // Infinitely loops until 'q' is pressed
    while (true) {
        // First of all displays the grid with supporting information
        displayGrid(grid);
        printw("[Space] Evolve once        [Enter] Run evolutions        [q] Exit\n");

        // Gets the most recently touched character
        int c = getch();

        //  - if space (' ') evolves and loops again
        //  - if ('q') ends the loops
        //  - if enter ('\n') starts a sub-loop similar to the main one, but waits for any character to stop
        if (c == ' ') {
            grid->evolve();
        } else if (c == 'q') {
            return;
        } else if (c == '\n') {
            nodelay(stdscr, TRUE); // Getting of the input is asyncronous
            // Infinitely loops until any key is pressed
            while (true) {
                grid->evolve();
                displayGrid(grid);

                printw("Press any key to end execution...                       \n"); // Extra whitespace to override previously written stuff in this area

                // If there has been something inputted, then break out of this sub-loop
                if (getch() != ERR) {
                    break;
                }

                usleep((__useconds_t)speed * 1000); // Sleep the desired amount of time (in micro seconds converted to milliseconds)
            }
        }
    }
}


For context (which is not necessary), you can check out my GitHub Repo.

Solution

Consider following the Single Responsibility Principal and break the function up into smaller functions that do less.

Note: This answer makes use of the loopEvos() that is provided in the updated version of the source files on GitHub.

void loopEvos (Grid* grid, size_t speed) {
    nodelay(stdscr, TRUE); // Getting of the input is asyncronous
    // Infinitely loops until any key is pressed
    while (true) {
        grid->evolve();
        displayGrid(grid);

        printw("Press any key to end execution...\n");

        // If there has been something inputted, then break out of this sub-loop
        if (getch() != ERR) {
            break;
        }

        usleep((__useconds_t)speed * 1000); // Sleep the desired amount of time (in micro seconds converted to milliseconds)
    }
}


Whenever code is written future expansion of the program/function must be considered. In the function above there is the code :

if (c == ' ') {
            grid->evolve();
        } else if (c == 'q') {
            return;
        } else if (c == '\n') {
            loopEvos(grid, speed);
            nodelay(stdscr, FALSE);
        }


It would be is easier to expand the code if another type of control statement was used instead. If the code was

switch (c) {
            case ' ':
                grid->evolve();
                continue;
            case 'q':
                return;
            case '\n':
                loopEvos(grid, speed);
                nodelay(stdscr, FALSE);
                continue:
            default :
                printw("Invalid character input\n");
                return;
        }


It would be easier to handle any additional input characters such as
KEY_UP, KEY_LEFT, KEY_DOWN and KEY_UP.

switch (c) {
            case ' ':
                grid->evolve();
                continue;
            case 'q':
                return;
            case '\n':
                loopEvos(grid, speed);
                nodelay(stdscr, FALSE);
                continue;
        // The following code is modified from procs/procs.hpp in the GitHub account.
            case 's':
                askFileSave(grid);
                continue;
            case 'c':
                changeSettings(&speed);
                continue;
            case KEY_UP:
                if (cursorPosY >= 1) {
                    cursorPosY -= 1;
                }
                continue;
            case KEY_LEFT:
                if (cursorPosX >= 2) {
                    cursorPosX -= 2;
                }
                continue;
            case KEY_DOWN:
                if (cursorPosY y - 1)) {
                    cursorPosY += 1;
                }
                continue;
            case KEY_RIGHT:
                if ((cursorPosX / 2) x - 1) {
                    cursorPosX += 2;
                }
                continue;
            default :
                printw("Invalid character input\n");
                return;
        }


It might be easier to read, understand and modify the outer loop if it was a do
while loop rather than a while true loop

void startEvolutionLoop (Grid* grid, size_t speed) {
    clear();

     int userInput;
     do {
         // First of all displays the grid with supporting information
         displayGrid(grid);
         printw("[Space] Evolve once        [Enter] Run evolutions        [q] Exit\n");

         // Gets the most recently touched character
         userInput = getch();

         if (userInput == ' ') {
             grid->evolve();
         } else if (userInput == 'q') {
             continue;
         } else if (userInput == '\n') {
             loopEvos(grid, speed);  // from procs/procs.hpp in the GitHub account.
             nodelay(stdscr, FALSE);
         }
     } while (userInput != `q`);
}

Code Snippets

void loopEvos (Grid* grid, size_t speed) {
    nodelay(stdscr, TRUE); // Getting of the input is asyncronous
    // Infinitely loops until any key is pressed
    while (true) {
        grid->evolve();
        displayGrid(grid);

        printw("Press any key to end execution...\n");

        // If there has been something inputted, then break out of this sub-loop
        if (getch() != ERR) {
            break;
        }

        usleep((__useconds_t)speed * 1000); // Sleep the desired amount of time (in micro seconds converted to milliseconds)
    }
}
if (c == ' ') {
            grid->evolve();
        } else if (c == 'q') {
            return;
        } else if (c == '\n') {
            loopEvos(grid, speed);
            nodelay(stdscr, FALSE);
        }
switch (c) {
            case ' ':
                grid->evolve();
                continue;
            case 'q':
                return;
            case '\n':
                loopEvos(grid, speed);
                nodelay(stdscr, FALSE);
                continue:
            default :
                printw("Invalid character input\n");
                return;
        }
switch (c) {
            case ' ':
                grid->evolve();
                continue;
            case 'q':
                return;
            case '\n':
                loopEvos(grid, speed);
                nodelay(stdscr, FALSE);
                continue;
        // The following code is modified from procs/procs.hpp in the GitHub account.
            case 's':
                askFileSave(grid);
                continue;
            case 'c':
                changeSettings(&speed);
                continue;
            case KEY_UP:
                if (cursorPosY >= 1) {
                    cursorPosY -= 1;
                }
                continue;
            case KEY_LEFT:
                if (cursorPosX >= 2) {
                    cursorPosX -= 2;
                }
                continue;
            case KEY_DOWN:
                if (cursorPosY < (grid->y - 1)) {
                    cursorPosY += 1;
                }
                continue;
            case KEY_RIGHT:
                if ((cursorPosX / 2) < grid->x - 1) {
                    cursorPosX += 2;
                }
                continue;
            default :
                printw("Invalid character input\n");
                return;
        }
void startEvolutionLoop (Grid* grid, size_t speed) {
    clear();

     int userInput;
     do {
         // First of all displays the grid with supporting information
         displayGrid(grid);
         printw("[Space] Evolve once        [Enter] Run evolutions        [q] Exit\n");

         // Gets the most recently touched character
         userInput = getch();

         if (userInput == ' ') {
             grid->evolve();
         } else if (userInput == 'q') {
             continue;
         } else if (userInput == '\n') {
             loopEvos(grid, speed);  // from procs/procs.hpp in the GitHub account.
             nodelay(stdscr, FALSE);
         }
     } while (userInput != `q`);
}

Context

StackExchange Code Review Q#146968, answer score: 5

Revisions (0)

No revisions yet.