The problem is that the lines
scanf("%d", &side);
scanf("%d %d", &base, &height);
scanf("%d %d %d", &up, &down, &height);
will not extract the newline character at the end of the line.
Therefore, in the next loop iteration, the call to getchar
will extract that newline character and the call to scanf
will fail, because the next character is a letter and not a number. This means that only the call to getchar
one loop iteration later will actually extract the first character of the new line.
This bug should be clearly visible by running your program line by line in a debugger, as the debugger will show you that the value of type
will be \n
(ASCII Code 10
) in the second loop iteration.
To fix this bug, the simplest solution would be to add a call to getchar
after every call to scanf
, which will discard the newline character from the input stream.
A more robust solution would not use scanf
, but would use the function fgets
to always read exactly one line of input and sscanf
to parse the input:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
int output[1000];
char line[200];
int i;
//attempt to read one line of input per loop iteration
for ( i = 0; ; i++ ) //infinite loop
{
char *p;
//protect against buffer overflow
if ( i == sizeof output / sizeof *output )
{
fprintf( stderr, "Too many lines!\n" );
exit( EXIT_FAILURE );
}
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
fprintf( stderr, "Error reading input!\n" );
exit( EXIT_FAILURE );
}
//attempt to find newline character in the line
p = strchr( line, '\n' );
//verify that entire line was read and remove the
//newline character, if it exists
if ( p == NULL )
{
//a missing newline character is probably acceptable
//when end-of-file has been reached, for example when
//standard input is being piped from a file.
if ( !feof( stdin ) )
{
fprintf( stderr, "Line too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove the newline character by overwriting it with
//a terminating null character
*p = '\0';
}
if( line[0] == 'P' )
{
int side;
if ( sscanf( line+1, "%d", &side ) != 1 )
{
fprintf( stderr, "Error parsing input!\n" );
exit( EXIT_FAILURE );
}
output[i] = side * side;
}
else if ( line[0] == 'S' )
{
int base, height;
if ( sscanf( line+1, "%d %d", &base, &height ) != 2 )
{
fprintf( stderr, "Error parsing input!\n" );
exit( EXIT_FAILURE );
}
output[i] = 0.5 * base * height;
}
else if ( line[0] == 'T' )
{
int up, down, height;
if ( sscanf( line+1, "%d %d %d", &up, &down, &height ) != 3 )
{
fprintf( stderr, "Error parsing input!\n" );
exit( EXIT_FAILURE );
}
output[i] = height * (up + down) / 2;
}
else if ( line[0] == '0' )
{
//break out of infinite loop
break;
}
}
for ( int j = 0; j < i; j++ )
{
printf( "%d\n", output[j] );
}
return 0;
}
For the input specified in the question, this program has the desired output:
25
50
100