0

I'm trying to understand following code:

#include <stdio.h>

int main(void)
{
    int counter[5] = {0};
    int *i, c;
    printf("Please enter a string terminated by ENTER key:\n");
    while(i = counter, (c = getchar()) != '\n')
    {
        switch(c)
        {
          default: continue;
          case 'U'+' ': case 'U': ++ i;
          case 'O'+' ': case 'O': ++ i;
          case 'I'+' ': case 'I': ++ i;
          case 'E'+' ': case 'E': ++ i;
          case 'A'+' ': case 'A': ++*i;
        }
    }
    for(c = 0; c < 5; c++)
       printf("counter[%d] = %d\n", c, counter[c]);

    return 0;
}

This code caught my attention for the following reasons

  • First do not understand it because the array counter appears to be the amount of vowels, without having any allocation made for it.

  • Second because the last case the pointer i has an asterisk.

  • Third because in each case there is a 'A'+' '. Why does it add
    a space to each vowel

James Z
  • 12,209
  • 10
  • 24
  • 44
Kevin
  • 1,151
  • 1
  • 10
  • 18

3 Answers3

2

1) At the start of your loop, 'i' is being set to point to the first element in the array 'counter' because:

i = counter;

is the same as:

i = &counter[0];

2) Since you don't have any 'break' statements, when you enter a vowel, 'i' will be incremented to point to one of the elements of the array. For example, if you enter 'O', the pointer 'i' will be incremented 3 times. Then, since the last set of case statements increments what 'i' points to and not 'i' itself, the value of one of the array elements will be incremented.

3) 'A' is the ASCII character 0x41, ' ' is 0x20. 'A' + ' ' is the same as 0x41 + 0x20 which is 0x61 which is the same as 'a'.

Jim Rhodes
  • 5,021
  • 4
  • 25
  • 38
1

The code is intentionally obfuscated.

  • Lowercase letters are written as <Space> + <upper case equivalent>.

  • The pointer i is advanced to the correct vowel by walking through a switch without break statements.

The first part works because of the way the ASCII character table is organized: Upper and lower case letters have a fixed difference of 32, which happens to also be the ASCII value of the space.

The second part just relies on the rules of the C language:

  1. When the loop sees a vowel, it starts at the appropriate switch label and "falls through", executing all the subsequent executable statements.

  2. Unless the vowel is an A or a, the pointer i was incremented one or more times, so that it points to counter[1], counter[2], etc.

  3. The final statement, ++*i, increments the value that the pointer i now points to. That's where vowels are counted. For example, if i has been incremented twice it points to counter[2], so that's what the ++ increments.

alexis
  • 48,685
  • 16
  • 101
  • 161
0

Read about definition and declaration. The array is well defined. Althought the initializer is an extension for an automatic variable which e.g. gcc supports.

For the cases, I unwrapped that a bit:

   switch ( c ) {
      default: continue;
      case 'U'+' ':  // 'u' 
      case 'U': ++ i;
      case 'O'+' ':  // 'o'
      case 'O': ++ i;
      ...
   }

This is just a broken variant to check for 'u' and 'U'. Broken as it relies on ASCII encoding where ' ' has the decimal index of 32 and lower-case letters have an index 32 higher than uppercase letters. Looks somewhat obfuscated to me and I would not recommend it (for both reasons given).

If there is a problem for the switch as such: remember that the "case labels " are called that intentionally: the code is executed from each label until the end of the statement. So, for 'U', i (bad name for a pointer; i is associated with integger types/index by most) is incremented 4 times - which would point past the array!. The last label just increments the corresponding counter (note the additional *.

I think that code is hard to read for the occasional reader. I would not write such without absolute need for performance (whereas It might not even perform that well due to the multiple increments). From a student I would not accept that.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52