Директивы препроцессора

0

Добро пожаловать на блог ojgen-it. Для первого поста я выбрал совершенно случайную тему. Это Директивы препроцессора.

Сегодня я создам маленькую программу, которая демонстрирует  работу с  #define. Думаю, нет особого смысла здесь, что-либо рассказывать о препроцессоре. На википедии и так хорошее описание.

Наша программка будет фильтровать символы, введенные с клавиатуры, меняя их на звездочки. Чтобы было интереснее - добавлю меню, в котором можно будет выбрать, что именно фильтровать, текст или цифры, например. Итак, приступим.

Для начала напишем код, который позволит вводить символы с клавиатуры:


#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;

int main() {
 int i=0;
 char ch=0;
 char str[256];

 while (true) {  
  system("cls");
  for(int j=0; j < i; j++) {
   cout << str[j];
  }   
  str[i++] = _getch(); 
 }
 return 0;
}
  • system("cls"); - с помощью этой функции можно очистить консоль;
  • _getch(); - эта функция ожидает нажатия клавиши, и возвращает ее код в int. Для использования функции нужно подключить библиотеку conio.h.

Теперь добавим больше функциональности примеру, и заодно используем  #define для определения констант:


#include <iostream>

…     
 
#define ENDLINE '\n' // «;» после директив ставить не нужно

int main() {
 int i=0;
 char ch=0;
 char str[256];

 while (true) {  
  system("cls");
  for(int j=0; j < i; j++)
   cout << str[j];
      
  ch = _getch(); 
         switch (ch) { 
   case 83: // клавиша del
    for (int j=0; j < i; str[j++] = ' ');
    i=0;
break;  
   case 8: // клавиша backspace
    if (i > 0)
     str[--i] = ' ';
    break; 
              case 13: // клавиша enter
    str[i++] = ENDLINE;
    break; 
   default :  
    str[i++] = ch;   
    break;
         }
     }
return 0;
}

При нажатии на любую клавишу ми получаем ее код, и можем делать то или иное действие. Вы можете сами посмотреть нужный вам код клавиши, просто посмотрев результат _getch(), или найти уже составленные таблицы, например, здесь

Я объявил текстовую константу  ENDLINE – теперь, при нажатии на Enter, в массив str будет дописан символ нового рядка. Ми сможем перейти на новую строчку и набирать текст дальше. Также при нажатии Backspace, можно «стирать» последний символ, или все символы, нажав на Del. Все другое будет, записывается в массив str.

Создадим еще одну константу и макросы:


#include <iostream>

…

#define FILTER '*'

// таблицу ASCII кодов можно найти по силке выше 
#define UP_LATIN(ch) ( ch > 65 && ch < 90 )
#define LO_LATIN(ch) ( ch > 97 && ch < 122 )

#define FILTER_LATIN(ch)    ( (UP_LATIN(ch) || LO_LATIN(ch)) ? FILTER : ch )
#define FILTER_CYRILLIC(ch) ( (ch > 191 && ch < 256) ? FILTER : ch )
#define FILTER_NUMBER(ch)   ( ch > 47 && ch < 58 ? FILTER : ch )
int main() { … }

Используем эти макросы и добавим меню:


int main() {
 int i=0;
 int choice = 0, size=3;
 char ch=0;
 char str[256];
 char * menu[] = { "No filtering", "Latin characters filter", "Number filter"};

 while (true) {  
  system("cls"); 
  for (int j = 0; j < size; j++) {
              cout << ( choice==j ? " >> " : "    ") << menu[j] << ( j==0 ? ENDLINE : ' ' ) << endl;
  }
  cout << endl << endl;
      
  for (int j=0; j < i; j++) {
   switch(choice) {
   case 0:
    cout << str[j];
    break;
   case 1:
    cout << FILTER_LATIN(str[j]);
    break;
   case 2:
    cout << FILTER_NUMBER(str[j]);
    break;
   }
  }
     
 ch = _getch(); 
       switch (ch) { 
  case -32: 
   break; 
        case 72: // стрелка вверх
         if (choice != 0)
          choice--;
         break; 
        case 80: // стрелка вниз
         if (choice != size - 1)
          choice++;
         break;

  . . .
       }
    }
return 0;
}

Теперь, ми можем вводить и удалять текст, а параллельно, стрелками вверх/вниз менять способ фильтрации текста.

Может быть вы обратили внимание на код

 case -32: break;

, в самом начале switch. Если вы его закомментируйте и посмотрите результат, то обнаружите, что при нажатии стрелки вверх/вниз, помимо смены режима фильтрации, в текст добавится символ «p».
Почему так происходит?
Все дело в том, что при нажатии на определенные клавиши (стрелки входят в их число), код возвращается два раза. Таким способом первый код отлавливается. 

Prev