The Yorn Function – Solution

The most difficult thing about this month’s Exercise is to deal with stream input: When the user overstuffs the input buffer, those extra characters continue to flow into the program, interpreted as additional input and they make the output look ugly.

If you truly want a clean-looking program that’s interactive, you must use input other than standard I/O. For example, use Ncurses to interactively read the keyboard. But this month’s Exercise required that you handle stream input, which is dicey.

I decided that if the buffer overflows, it overflows. As long as the program continues to prompt for Yes/No input, I’m good. Otherwise, I tackled my solution for the yorn() function in these steps:

  1. Display the input prompt
  2. Read input
  3. Check for null/invalid input
  4. Convert input to uppercase
  5. Evaluate input

For Step 2, I use the worthy fgets() function. Immediately after retrieving input, I move to Step 3, which is to check for null or invalid input — to see whether I/O is being redirected as empty input or the user is just being silly:

    /* read stream input */
    fgets(buffer,SIZE,stdin);

    /* check for null input */
    ch = (int)buffer[0];
    if( ch=='\0' || ch==EOF )
        return(0);

If the input buffer is empty, buffer[0]=='\0' or a null file was redirected as input, buffer[0]==EOF, the program returns zero, meaning invalid input.

For Step 4, I combine two tasks: remove the newline from input and convert characters to uppercase.

    /* replace the newline with null char
       and convert input to uppercase */
    for( x=0; x<SIZE; x++ )
    {
        if( buffer[x]=='\0' )
            break;
        if( buffer[x]=='\n' )
        {
            buffer[x]='\0';
            break;
        }
        buffer[x] = toupper(buffer[x]);
    }

When the null character is encountered, buffer[x]=='\0', the loop breaks. Otherwise, when the newline is encountered, buffer[x]=='\n', it’s replaced with the null character and the for loop breaks. Beyond those two conditions, the toupper() function converts the character to uppercase.

Finally, Step 5 evaluates the results. To meet this end, I use the strcmp() function to compare the four desired results: YES, Y, NO, and N. Anything else is considered invalid:

    /* evaluate results */
        /* return 1 for Yes */
    if( strcmp(buffer,"YES")==0 )
        return(1);
    if( strcmp(buffer,"Y")==0 )
        return(1);
        /* return 2 for No */
    if( strcmp(buffer,"NO")==0 )
        return(2);
    if( strcmp(buffer,"N")==0 )
        return(2);
    /* neither */
    return(0);

Longer strings, such as yessiree and nope are rejected. After all, the prompt does indicate “Yes or No.”

Here’s a sample run:

Would you like to destroy the Earth? (Yes or No)? No
The Earth will be saved.

Buffer overflow is handled in the code, though the output looks sloppy:

Would you like to destroy the Earth? (Yes or No)? Most definitely not.
Invalid response
Would you like to destroy the Earth? (Yes or No)? Invalid response
Would you like to destroy the Earth? (Yes or No)?

Because the input string is longer than SIZE (12) characters, two responses are interpreted. Both are invalid. Still, the code saves itself, continuing to prompt for valid input.

Click here to view the entire code on Github. I hope your solution dealt with the many puzzles and issues presented with stream input. The process can be challenging.

Leave a Reply