Pure C function pointer on printing vowels twice

Have difficulty to understand this pure C code to only print vowels twice from input string. Questions are commented at the end of each place.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
/*
 *Demonstrate the use of dispatch tables
 */

/*Print a char twice like putchar, return char if successful, or EOF on error.*/

int putcharTwice(int c)
{
    if (putchar(c) == EOF || putchar(c) == EOF)  {//Q1
    return EOF;
    } else {
    return c;
    }
}

#define NUM_CHARS (UCHAR_MAX + 1)    //UCHAR_MAX is in limits.h

int main(int argc, char **argv)
{
/*This declares table as array of function pointers */
    int (*table[NUM_CHARS]) (int);   //Q2
    int i;
    int c;

    for (i = 0; i < UCHAR_MAX; i++) {
    /* default is to call putchar */
    table = putchar;
    }

    /*but lower-case vowels show up twice */
    table['a'] = putcharTwice; //Q3, and following 4 lines
    table['e'] = putcharTwice; //Q3
    table['i'] = putcharTwice; //Q3
    table['o'] = putcharTwice; //Q3
    table['u'] = putcharTwice; //Q3

    while ((c = getchar()) != EOF) {
    table[c] (c); //Q4,
    }
    return 0;
}

The code was compiled without any problem,

$ echo "The quick brown fox jumps over the lazy dog!" | ./a.out
$ Thee quuiick broown foox juumps ooveer thee laazy doog!

Q1: How does the logic work by repeating the same condition on both sides of "||" ? I tried using only one side of the OR condition, the code compiled without error but did not work as expected.

Q2:Even not quite sure how to ask this question. Is this a prototype of a function? But the calling is without any parameter see Q3.

Q3: Calling of the function does not have a parameter at all. How does it work?

Q4: I thought I understand this line, but I must have wrong catch because of Q2.

Thanks a lot!

putchar(c) returns 0 on success or EOF on error. So, if the first putchar(c) succeeds, the second putchar(c) will also be executed. If both of them succeed, the expression tested will be 0 || 0 and the else side of the if statement will have putcharTwice() return c . If either putchar(c) failed, putcharTwice() will return EOF .

int (*table[NUM_CHARS]) (int); is a declaration stating that table is an array of 256 pointers to functions and those functions take one argument of type int and return an int .

    for (i = 0; i < UCHAR_MAX; i++) {
    /* default is to call putchar */
    table = putchar;
    }

sets the 1st 255 of the 256 elements of the table[] array to be a pointer to the putchar() function. It does not call putchar() .

    /*but lower-case vowels show up twice */
    table['a'] = putcharTwice;

resets the elements of the table[] array corresponding the the character a to point to the function putcharTwice() . And the following statements do the same thing for the other lowercase vowels in the English alphabet. These assignments do not call putchar() or putcharTwice() either.

    while ((c = getchar()) != EOF) {
    table[c] (c); //Q4,
    }

is a loop that reads one character at a time from standard input until it detects an error or end-of-file condition. For each character read, it calls the function specified by the element of table[] corresponding to the character read with an argument that is the character read.

Hope this helps.

2 Likes

Thanks Don! I seem to get closer to understand it. With a simpler test, here is my dissection of the execution:

 $ echo Test | ./a.out 
table['T'] ~~> putchar('T');  
table['e'] ~~> putcharTwice('e');  
table['s'] ~~> putchar('s');
table['t'] ~~> putchar('t');

but I still did not get how putcharTwice( int c) print the chars (now vowels only) twice.
For putcharTwice('e'): (putchar('e') == EOF || putchar('e') == EOF) becomes (0 || 0) so that the else block is executed to return 'e'; but how is 'e' printed twice to have ee with this function?

Thanks again!

Because putchar isn't returning EOF.
From man putchar:

RETURN VALUE
       fputc(),  putc()  and  putchar()  return  the  character  written as an
       unsigned char cast to an int, or EOF on error.

So if you're printing C, it ends up testing 'C' == EOF, which evaluates to 0, allowing it to reach the second part, testing 'C' == EOF again, which is false again.

The return value is EOF or a single vowel, which is the first part bugging me.

Does that mean in if (putchar(c) == EOF || putchar(c) == EOF) , function putchar(c) gets actually executed twice?

I thought this line is just a condition, and before the end only the else block is executed so that the value is 'e', without printing.
Let me put my question in another way:
Is there another layer for printing hidden behind, such as when 'e' is encountered in 'Test'?

putchar(c);    //Is this the place 'e' get printed the first time?
left ~> (putchar(e) == EOF) is false, 0
putchar(c);    //Is this the place 'e' get printed the second time?
right ~> (putchar(e) == EOF is false, 0
so that, the if (0 || 0) condition still false; 
else block executed

Is this correct?
Thanks!

Yes. To evaluate the expression, it has to call the function.

Slapping an if() around it doesn't change it. Would you expect this to print the values?

#include <stdio.h>

int main(void) {
    printf("a") && printf("b");
}

Treat anything inside an if() the exact same way.

No.

For C, the answer to this question is always "no".

With very specific exceptions - like atexit() - C will never call a function without being asked.

What I meant is: Does putchar(c) == EOF have two layers?
First, putchar(c) , which will print 'c' out;
Second, evaluate putchar(c) == EOF , which is false because first step is successful.
How does 'e' get printed twice in 'Test'? I need each step through the code.
i.e. how the function putcharTwice(int c) print each 'c' twice?

Thanks!

To get the return value of a function, the function must first be executed, yes.

if(putchar(c) == EOF || putchar(c) == EOF)
if('C' == EOF || putchar(c) == EOF)
if(false || putchar(c) == EOF)
if(putchar(c) == EOF)
if('C' == EOF)
if(false)

Now, if putchar actually DID return eof, it'd ignore the other half. It doesn't need to bother, since true || anything means true. That's why they call || short-circuit evaluation, it can quit early.

if(putchar(c) == EOF || putchar(c) == EOF)
if(EOF == EOF || putchar(c) == EOF)
if(true || putchar(c) == EOF)
if(true)

I think I can get the logic part, but not the 'ee' from Test to Teest'.
I re-wrote the code to avoid any possible confusion just simply printing each char twice:

#include <stdio.h>
#include <stdlib.h>

/*Print a char twice like putchar, return char if successful, or EOF on error.*/

int putcharTwice(int c)
{
    if (putchar(c) == EOF || putchar(c) == EOF)  {
    return EOF;
    } else {
    putchar(c);  //explicit printing
    putchar(c);  //explicit printing
    return 0;
    }
}

int main(int argc, char **argv)
{
    int c;

    while ((c = getchar()) != EOF) {
    putcharTwice(c); 
     }
    return 0;
}

but the code actually print each char FOUR times!

$ echo Test | ./a.out
TTTTeeeesssstttt.

Apparently every last two repeats are from the explicit printing. Where are the first two repeats from?
Sorry for my slow catch!

You have a big array of pointers which determines which function gets called. It executes different code because a few pointers point to a different location in memory.

The value of table['a'], or any other vowel, is 0x400656. That's a location in memory which gets jumped to, containing the instructions for the putcharTwice function. All other indexes contain 0x400500, which is just putchar.

1 Like

That's because you call putchar() four times. Not sure what you were expecting.

How could an expression possibly work without calling the functions mentioned in it? It couldn't.

Thanks Don and corona688!
I think my problem is my mis-understanding of the function putchar(c) so that I re-wrote it with putc() which helped me understand it.

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>

/*Print a char twice like putchar, return char if successful, or EOF on error.*/

int putcharTwice(int c)
{
    if (putc(c, stdout) == EOF || putc(c, stdout) == EOF)  {//Q1
    return EOF;
    } else {
    return 0;        //NOT return c;
    }
}

#define NUM_CHARS (UCHAR_MAX + 1)    //UCHAR_MAX is in limits.h

  int (*table[NUM_CHARS]) (int);   //Q2, So moved outside main() to see this function pointer

int main(int argc, char **argv)
{
/*This declares table as array of function pointers */
    int i;
    int c;

    for (i = 0; i < UCHAR_MAX; i++) {
    // default is to call putchar 
    table = putchar;
    }

    // but lower-case vowels show up twice 
    table['a'] = putcharTwice; //Q3, and following 4 lines
    table['e'] = putcharTwice; //Q3
    table['i'] = putcharTwice; //Q3
    table['o'] = putcharTwice; //Q3
    table['u'] = putcharTwice; //Q3

    while ((c = getchar()) != EOF) {
    table[c] (c); //Q4,
    }
    return 0;
}

Thanks a lot again!