Unreadable input on Turtle Graphics program ( C )

Solution for Unreadable input on Turtle Graphics program ( C )
is Given Below:

I was asked to do a simple 20×20 turtle graphics program but for some reason I’m having an issue that’s probably related from line 42 to 150 (Only they were originally on the post but I edited it since someone asked me to on the comments):

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <locale.h>
#include <string.h>
int floor[20][20], step, p1 = 0, p2 = 0;
char compass[6] = "westm", com[1], pen[3] = "up";
int main()
{
    com[0] = 'x';
    for (int i = 0; i < 20; i++)
    {
        for (int j = 0; j < 20; j++)
        {
            floor[i][j] = 0;
        }

    }
    while (com[0] != 'e' && com[0] != 'E')
    {
        com[0] = 'x';
        printf("Enter a command n");
        scanf("%c", &com[0]);
        getchar();
        if (com[0] == 'e' || com[0] == 'E')
        {
            printf("End n");
        }
        else
        {
            if (com[0] == 'u' || com[0] == 'U')
            {
                strncpy(pen, "up", 3);
                printf("The pen was turned up n");
            }
            if (com[0] == 'd' || com[0] == 'D')
            {
                strncpy(pen, "do", 3);
                floor[p1][p2] = 1;
                printf("The pen was turned down n");
            }
            if (com[0] == 'r' || com[0] == 'R')
            {
                if (!strcmp(compass, "westm"))
                {
                    strncpy(compass, "south", 6);
                }
                if (!strcmp(compass, "south"))
                {
                    strncpy(compass, "eastm", 6);
                }
                if (!strcmp(compass, "eastm"))
                {
                    strncpy(compass, "north", 6);
                }
                if (!strcmp(compass, "north"))
                {
                    strncpy(compass, "westm", 6);
                }
                printf("The turtle turned right n");
            }
            if (com[0] == 'l' || com[0] == 'L')
            {
                if (!strcmp(compass, "westm"))
                {
                    strncpy(compass, "north", 6);
                }
                if (!strcmp(compass, "south"))
                {
                    strncpy(compass, "westm", 6);
                }
                if (!strcmp(compass, "eastm"))
                {
                    strncpy(compass, "south", 6);
                }
                if (!strcmp(compass, "north"))
                {
                    strncpy(compass, "eastm", 6);
                }
                printf("The turtle turned left n");
            }
            if (com[0] == 'w' || com[0] == 'W')
            {
                step = 2147483647;
                if (!strcmp(compass, "westm"))
                {
                    while (step + p2 > 19)
                    {
                        printf("Type a valid number of steps n");
                        scanf("%d", &step);
                        getchar();
                    }
                    if (!strcmp(pen, "do"))
                    {
                        for (int i = 0; i <= p2 + step; i++)
                        {
                            floor[p1][p2 + i] = 1;
                        }
                    }
                    p2 = floor + p2;
                }
                if (!strcmp(compass, "north"))
                {
                    while (p1 - step < 0)
                    {
                        scanf("%d", &step);
                        getchar();
                    }
                    if (!strcmp(pen, "do"))
                    {
                        for (int i = 0; i <= p1 - step; i++)
                        {
                            floor[p1 - i][p2] = 1;
                        }
                    }
                    p1 = p1 - step;
                }
                if (!strcmp(compass, "eastm"))
                {
                    while (p2 - step < 0)
                    {
                        scanf("%d", &step);
                        getchar();
                    }
                    if (!strcmp(pen, "do"))
                    {
                        for (int i = 0; i <= p2 - step; i++)
                        {
                            floor[p1][p2 - i] = 1;
                        }
                    }
                    p2 = p2 - step;
                }
                if (!strcmp(compass, "south"))
                {
                    while (step + p2 > 19)
                    {
                        scanf("%d", &step);
                        getchar();
                    }
                    if (!strcmp(pen, "do"))
                    {
                        for (int i = 0; i <= p1 + step; i++)
                        {
                            floor[p1 + i][p2] = 1;
                        }
                    }
                    p1 = p1 + step;
                }
            }
            if (com[0] == 'p' || com[0] == 'P')
            {
                for (int i = 0; i < 20; i++)
                {
                    for (int j = 0; j < 20; j++)
                    {
                        if (floor[i][j] == 0)
                        {
                            printf(". ");
                        }
                        else
                        {
                            printf("* ");
                        }
                    }
                    printf("n");
                }
            }
        }
    }
}

Basically, on the beginning of the code there is an “while” waiting for user inputs until the’re different from both ‘e’ and ‘E’, and it seems to be working fine on most cases

The problem is that when I walk AFTER turning right or left (by inputting ‘w’ after either the characters ‘r’ or ‘l’) or try to use the ‘w’ input for multiple times the program keeps asking for inputs (for the variable com, not step) without reading ‘w’ for some reason

Any other inputs like ‘p’, ‘e’ or even ‘l’ and ‘r’ again are working fine, but ‘w’ specifically doesn’t work, and if I use ‘p’ (‘e’ doesn’t count because it’ll stop the repetition) and then ‘w’ the input will be recognized too

The algorythm with all those ifs kinda sucks but it’s the most simple and easy to explain I could think of by myself

When I run your program and enter l as the first command and w as the second command, then it will execute the following loop:

while (p2 - step < 0)
{
    scanf("%d", &step);
    getchar();
}

Because p2 == 0 at this point, this loop will run forever until the user enters either zero or a negative number. This does not seem intended. Also, it does not seem intended that the program reads input from the user without telling the user beforehand what input to enter.

The best way to diagnose such issues is to run your program line by line in a debugger while monitoring the values of all variables. That way, it is easy to see at which point your program stops behaving as intended.

Also, your program also has the following issues:


It seems that the statement getchar(); is supposed to discard the newline character. However, this will only work if the user’s input is in the expected format, i.e. if the newline character is in the expected position. If the user enters no characters or too many characters, then this won’t always work.

For line-based input, I recommend that you use the function fgets instead of scanf/getchar, because the function fgets always reads exactly one line at a time (assuming that the buffer is large enough to store the entire line). You may want to read this: A beginners’ guide away from scanf()


Generally, it does not make sense to declare an array with only a single member. Therefore, it would probably make more sense to declare com as a simple char instead of an array of char.


The following code is a bit cumbersome:

if (com[0] == 'e' || com[0] == 'E')
{
    [...]
}
else
{
    if (com[0] == 'u' || com[0] == 'U')
    {
        [...]
    }
    if (com[0] == 'd' || com[0] == 'D')
    {
        [...]
    }
    if (com[0] == 'r' || com[0] == 'R')
    {
        [...]
    }
    if (com[0] == 'l' || com[0] == 'L')
    {
        [...]
    }
    if (com[0] == 'w' || com[0] == 'W')
    {
        [...]
    }
    if (com[0] == 'p' || com[0] == 'P')
    {
        [...]
    }
}

It can be simpified to the following:

switch ( toupper( (unsigned char)com[0] ) )
{
    case 'E':
        [...]
        break;
    case 'U':
        [...]
        break;
    case 'D':
        [...]
        break;
    case 'R':
        [...]
        break;
    case 'L':
        [...]
        break;
    case 'W':
        [...]
        break;
    case 'P':
        [...]
        break;
    default:
        fprintf( stderr, "unexpected error!n" );
        exit( EXIT_FAILURE );
}

The following code is wrong:

if (!strcmp(compass, "westm"))
{
    strncpy(compass, "south", 6);
}
if (!strcmp(compass, "south"))
{
    strncpy(compass, "eastm", 6);
}
if (!strcmp(compass, "eastm"))
{
    strncpy(compass, "north", 6);
}
if (!strcmp(compass, "north"))
{
    strncpy(compass, "westm", 6);
}

For example, if compass holds the string "westm", then the first if block will change the string to "south". But now the condition of the second if block is true, so the second if block will change it to "eastm". Now the condition of the third if block is true, so the third if block will change it to "north". Now the condition of the fourth if block is true, so the fourth if block will change it back to "westm". That way, you will have done a full rotation. This is probably not what you want.

In order to break this chain, you should add an else before every if statement, except for the first if statement:

if (!strcmp(compass, "westm"))
{
    strncpy(compass, "south", 6);
}
else if (!strcmp(compass, "south"))
{
    strncpy(compass, "eastm", 6);
}
else if (!strcmp(compass, "eastm"))
{
    strncpy(compass, "north", 6);
}
else if (!strcmp(compass, "north"))
{
    strncpy(compass, "westm", 6);
}

However, instead of storing the direction (compass) as a string, it would be more efficient to store it as an enum, like this:

enum direction
{
    DIRECTION_NORTH,
    DIRECTION_SOUTH,
    DIRECTION_WEST,
    DIRECTION_EAST
};

That way, instead of writing a chain of if/else if statements, you could simply write the following (assuming compass is an int instead of a string):

switch ( compass )
{
    case DIRECTION_WEST:
        compass = DIRECTION_SOUTH;
        break;
    case DIRECTION_SOUTH:
        compass = DIRECTION_EAST;
        break;
    case DIRECTION_EAST:
        compass = DIRECTION_NORTH;
        break;
    case DIRECTION_NORTH:
        compass = DIRECTION_WEST;
        break;
    default:
        fprintf( stderr, "unexpected error!n" );
        exit( EXIT_FAILURE );
}

The reason that this is more efficient is that computers are better at handling numbers than strings.

#include "turtle.h"

int main()
{
    turtle_init(300, 300);          // initialize the image to be 600x600

    turtle_forward(50);
    turtle_turn_left(90);
    turtle_forward(50);
    turtle_draw_turtle();

    turtle_save_bmp("output.bmp");  // save the turtle drawing

    return EXIT_SUCCESS;
}