пустой корпус переключателя в C - PullRequest
4 голосов
/ 31 августа 2011

Я читаю несколько книг о C. Я нашел следующий пример переключения регистра в C , который я пытаюсь понять ...

/* caps.c */

   #include <stdio.h>
   #include <ctype.h>

   #define SEEK 0
   #define REPLACE 1

   int main(void)
   {
     int ch, state = SEEK;
     while(( ch = getchar() ) != EOF )
     {
       switch( state )
       {
       case REPLACE:
         switch( ch )
         {
         case ' ':    //leaving case empty will go to default ???
         case '\t':
         case '\n':   state = SEEK;
                      break;
         default:     ch = tolower( ch );
                      break;
         }
         break;
       case SEEK:
         switch( ch )
         {
         case ' ':
         case '\t':
         case '\n':   break;
         default:     ch = toupper( ch );
                      state = REPLACE;
                      break;
         }
       }
       putchar( ch );
     }
     return 0;
   }

Мне совершенно ясно, что режим SEEK, а затем буквы пишутся с заглавной буквы, а затем режим устанавливается на REPLACE, а затем буквы преобразуются в нижние. Но почему пробелы снова вызывают режим SEEK? Это действительно так в моем комментарии?

Ответы [ 4 ]

12 голосов
/ 31 августа 2011

Это так называемое сквозное поведение оператора C switch.Если у вас нет break в конце области case, управление переходит к следующей метке case.

Например, следующий фрагмент

int x = 5;
switch( x ) {
    case 5:
        printf( "x is five!\n" );
    case 2:
        printf( "x is two!\n" );
        break;
    default:
        printf( "I don't know about x\n" );
}

выходы

x is five!
x is two!

Будьте осторожны.

4 голосов
/ 31 августа 2011

В этом случае произойдет то, что коммутатор войдет в соответствующий статус case, поэтому, если ch=' ' наверху, то работает, пока не достигнет break.

Это означает, что если ch является одним из ' ','\t' или '\n', тогда state будет установлено на SEEK.

3 голосов
/ 31 августа 2011

Оставление пустого дела означает не переход к значению по умолчанию, оно переходит к следующему случаю.

Таким образом, будет установлен фрагмент кода:

case ' ':    // leaving case empty will drop through to `\t` and then `\n`.
case '\t':
case '\n':   state = SEEK;
             break;
default:     ch = tolower( ch );
             break;

состояние SEEK для пробелов, символов табуляции и новой строки, в противном случае он будет символом в нижнем регистре.

У вас есть небольшой конечный автомат с двумя состояниями.

  • В режиме SEEK он пропускает все пробелы (символы табуляции, пробелы и новые строки) и, когда находит другой символ, вводит его в верхнем регистре и переключается в режим REPLACE.

  • В режиме ЗАМЕНА, он будет в нижнем регистре все символы, пока не найдет пробел, а затем переключится в режим SEEK.

Следовательно текст, как:

PaxDiablo is a REALLY cool guy

станет:

Paxdiablo Is A Really Cool Guy

1 голос
/ 31 августа 2011
case ' ':    //leaving case empty will go to default ???

Сначала я хочу пояснить, что если вы напишите case '': , вы не оставите дело пустым.На самом деле вы пишете case 32: , поскольку значение ASCII для пробела равно 32.

В общем, всякий раз, когда вы пишете 'a', или 'b' или любую константу характера,быть неявным преобразованием символа, указанного в соответствующее значение ASCII.

Proof: 
 The prototype of isspace() is,
 int isspace ( int c );
 And not as,
 int isspace ( char c );

Закомментируйте регистр '': оператор.Тогда ты сам найдешь ответ.Если я закомментирую регистр '':,

 Then on input,
    hello world
    the output will be,
    Hello world   <not expected>
    instead of 
    Hello World  (needed output).
...