PvdB PvdB - 27 days ago 8
C Question

Filling an array row by row (one dimensional array)

For school I have to build a "car navigation" using an array which is split in different rows, like so:

S#####
.....#
#.####
#.####
...#.D
##...#


The idea is to find a clear path (the '.' characters) to the destination and replace these with a '+' character.
I'm having issues with filling the array. The exercise is:

Write a function
void inputMaze(char maze[], int maxX, int maxY)
that asks the user to
input
maxY
strings of
maxX
characters each. These strings should be stored in the array
maze
and the strings
should be composed of the following characters:

• ’S’ - starting position.

• ’D’ - destination.

• ’.’ - location where car is allowed to drive.

• ’#’ - location where car is not allowed to drive (obstacle).

The output of your program should look as follows:

Number of rows? 6
Number of columns? 6
Input row 0: S#####
Input row 1: .....#
Input row 2: #.####
Input row 3: #.####
Input row 4: ...#.D
Input row 5: ##...#


I tried writing the function like this:

void inputMaze(char maze[], int maxX, int maxY)
{
int i, j;

for (j = 0; j <= (maxX-1); j++)
{
printf("Input row %d: ",j);
for (i = 0; i <= (maxY-1); i++)
{
maze[(j * maxY) + i] = getchar();
}
}
}


However when I execute the function and it arrives at
j == (maxX-1)
, the print line is shown but it skips the input of row
maxX - 1
(completely ignoring the for loop) and continues to the next step.

Where's the fault in my code?

Edit: The answer was the newline character. This code does seem to work:

void inputMaze(char maze[], int maxX, int maxY)
{
int i, j;
char c;

for (j = 0; j < maxX; j++)
{
printf("Input row %d: ",j);
for (i = 0; i < maxY; i++)
{
scanf(" %c", c);
if (c == '\n')
continue;
else
maze[(j * maxY) + i] = getchar();
}
}
}

Answer Source

When the user inputs data, he types a number, a string, whatever and then he hits Enter.

Now your program uses getchar(), which reads one character at a time, or to put it as written in the ref:

Returns the next character from the standard input (stdin).

So, when the user types "S#####", he hits Enter. Now getchar() will go and consume everything that lives in the standard input buffer (which stores the input of the user).

It will consume 'S', then all '#', since you have called getchar() this many times.

Now the user inputs the next input row ".....#". You want getchar() to consume that input. The function is called, and at its first call, instead of consuming'.' (which is the desired behavior in your case), it will consume the newline character (from the Enter the user hit before, when inputting the previous row).

As a result, it will skip some characters that are intended to be read. This is exactly what happened in your case, since your program was consuming all the newlines from every input row, and when the last line was about to be read, it was done (since you planned to call getchar() maxX x maxY times. However, you didn't took into account the newline characters.

So simply use an extra getchar(), before receiving the next Input row, in order to consume that trailing newline character. Alternatively, you could check if the character currently read is a newline character, and continue to the next iteration (consume and ignore), like this:

void inputMaze(char maze[], int maxX, int maxY) {
    int i, j; char c;
    for (j = 0; j < maxX; j++) {
        printf("Input row %d: ",j);
        for (i = 0; i < maxY; i++) {
            scanf(" %c", c);
            if (c == '\n') continue;
            else maze[(j * maxY) + i] = getchar();
        }
     } 
 }

Tip: Unrelated to your problem, let me note that in a double for loop, we usually name the counter of the outer loop i and the counter of the inner loop j.