Бьерн Страуструп - Язык программирования С++. Главы 2-4 - Драйвер

ОГЛАВЛЕНИЕ

 

3.1.5  Драйвер

Когда все части программы определены, нужен только драйвер, чтобы инициализировать и запустить процесс. В нашем примере с этим справится функция main():

       int main()
       {
         // вставить предопределенные имена:
         insert("pi")->value = 3.1415926535897932385;
         insert("e")->value = 2.7182818284590452354;

         while (cin) {
             get_token();
             if (curr_tok == END) break;
             if (curr_tok == PRINT) continue;
             cout << expr() << '\n';
         }
         return no_of_errors;
       }

Принято, что функция main() возвращает нуль, если программа завершается нормально, и  ненулевое  значение,  если происходит иначе.  Ненулевое значение возвращается как число ошибок. Оказывается, вся инициализация сводится к занесению предопределенных имен в таблицу.

В цикле main читаются выражения и выдаются результаты. Это делает одна строка:

        cout << expr() << '\n';

Проверка cin при каждом проходе цикла гарантирует завершение программы, даже если что-то случится с входным потоком, а проверка на лексему END нужна для нормального завершения цикла, когда функция get_token() обнаружит конец файла. Оператор break служит для выхода из ближайшего объемлющего оператора switch или цикла (т.е. оператора for, while или do). Проверка на лексему PRINT (т.е. на '\n' и ';') снимает с функции expr() обязанность обрабатывать пустые выражения. Оператор continue эквивалентен переходу на конец цикла, поэтому в нашем случае фрагмент:

         while (cin) {
         // ...
         if (curr_tok == PRINT) continue;
         cout << expr() << "\n";
       }

эквивалентен фрагменту:

        while (cin) {
        // ...
        if (curr_tok == PRINT) goto end_of_loop;
        cout << expr() << "\n";
        end_of_loop: ;
      }

Более подробно циклы описываются в $$R.6