Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование с нуля - это совсем просто! 100) Юбилей!


Школа программирования

100) Юбилей!

Сегодня юбилейный, сотый выпуск. С чем мы друг друга и поздравляем.

В этом выпуске вашему вниманию предлагаются два задания. Они выполнены в неформальном виде. Каждый из них - небольшой рассказик и часть исходного текста программы, в котором содержится ошибка. Ваша задача - отыскать эту ошибку и сообщить мне.

Но сначала маленькая новость. Я перевез Школу программирования на другой сайт. Теперь она находится по адресу http://www.infiltration.ru/p/ (infiltration.ru - это мой личный сайт). Ну и старая копия пока доступна, по старому адресу.


Задача 1.

Тяжелый крейсер с рычанием рвал темные штормовые волны. Сновавшие рядом корабли прикрытия тщательно прощупывали лучами активных радаров окружающее морское пространство. "Тикондерог" считался сердцем мощной боевой эскадры, приближавшейся к Архангельску.

- Кэп, до русского берега - двадцать пять миль! - пискнула цифровая рация локальной связи. Согласно официальным нормам, российская граница заканчивается на двадцати четырех милях от береговой линии. Поэтому "Тикондерог", возглавлявший ударную группировку в рамках учений "Фри Си", пока оставался под незримой охраной международного права.

- Строй пеленг-уступа! Цель - космодром "Плесецк"!

В бронированных недрах корабля взревели сервомоторы, переводя на боевой взвод восемнадцать "Томагавков". Разноцветные лампочки на командно-информационном пульте перемигнули и замерли в новой конфигурации. В головки наведения смертоносных ракет поступила информация о новой цели.

Томас МакКиббен, капитан "Тикондерога", щурился, смахивая с лица соленые брызги. Конечно, это учения. Всего лишь учения. Однако ребята из военной разведки Пентагона недвусмысленно дали капитану понять, что проведение маневров в условиях, максимально приближенных к реальным, сразу по возвращении крейсера в порт обеспечит МакКиббену весьма и весьма щедрую пенсию и небольшую четырехэтажную виллу с видом на Атлантику. Ради этого стоило рискнуть. В последний раз в жизни.

- Двадцать две мили!

В голосе штурмана капитану почудились напряженные нотки. Да так оно и было. Без сомнения, русские корабли непрерывно шлют предупреждения, требуя освободить территориальные воды. Однако согласно негласным рекомендациям аналитиков разведки "Тикондерогу" требовалось приблизиться к берегу как минимум на девятнадцать миль, чтобы обеспечить гарантированное - хотя и имитационное, поражение космодрома.

Спустя несколько минут МакКиббен убедился, что российские моряки не настроены шутить.

- Кэп, предупредительный огонь!

Теперь штурман явно нервничал. Радары фиксировали в небе пять МиГов-29, вооруженных убийственными "Москитами". Но наибольшую опасность, без сомнения, представлял эсминец "Гончий". Он уже обстрелял один из легких кораблей, и его следующий ракетный залп наверняка будет проведен на поражение.

До российского берега оставалось девятнадцать с половиной миль, когда опасения капитана полностью подтвердились.

- Фиксирую четыре воздушные цели! Предварительно опознаны как "Кингфиши". Ставлю пассивные помехи!

Капитан нахмурился. От русских ракет X-22, разгонявшихся до скорости три с половиной тысячи километров в час, "Тикондерога" отделяло всего восемь секунд. Быстрый взгляд направо - так и есть, разворачиваются скорострельные "Голкиперы", позиционируя спаренные четырехствольные установки. Готовятся ежесекундно выпускать по приближающимся X-22 сотни снарядов.

По радиолокационным и оптическим каналам в бортовой вычислительный комплекс крейсера поступили данные о массовой атаке - приближении множества низколетящих целей. Компьютеру трехкоординатой станции обнаружения осталось выполнить последнюю задачу корреляционно-контрастной обработки сигналов, чтобы обеспечить надежное сопровождение каждого ракетного объекта...

Встроенный Си-интерпретатор антенного поста, функционирующий на специализированном процессоре MILSTD-1891 с быстродействием полтора миллиона Си-операторов в секунду, добрался до модуля target_recognize, выполняющего корректировку типа распознанной цели в зависимости от структурированных данных характера рассеивания миллиметровых радарных волн...

* * *

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

Ли быстро набрал дополнительный код, скомпилировал - ошибок не было. За спиной ощущалось тяжелое дыхание старшего менеджера Майкла, здоровенного белобрысого бугая, ни капли не смыслящего в программировании. Но у него существовало одно несомненное преимущество - Майкл был женат на дочери президента компании, бывшего министра сельского хозяйства. Ли, не выдержав прессинга, вздохнул. "Мне что, больше других надо?".

- Готово! - отрапортовал он, отправляя файл на сборку с пометкой "Тестирование завершено". Менеджер снисходительно похлопал Ли по плечу.

- Окей, приятель, отлично! Ну вот и все, расслабься! Завтра тебя ждет неплохая премия - пятизначная сумма!..

"Интересно, сколько же получишь ты?", - с легкой завистью подумал Джон.

* * *

МакКиббен с изумлением следил за сообщениями миниатюрного вспомогательного монитора на огромном пульте управления. По зеленому экрану безостановочным потоком бежали скупые строки сообщений, а гигантский боевой комплекс "Голкипера" как назло застопорился - в самый неподходящий момент! Обе башни с противным неестественным скрежетом совершали однообразные дергающиеся движения, словно в их механизмах что-то поломалось или испортилось. Мельтешение на мониторе наконец прекратилось, сменившись предупредительными подсказками, но драгоценное время было безвозвратно потеряно.

Уже через долю секунды четыре X-22 почти синхронно пробили борт "Тикондерога", беспощадно выжигая его внутренности раскаленной кумулятивной струей...

* * *

Проблема возникла в электронном мозгу "Голкипера". Интерпретатор не смог быстро найти выход из функции target_recognize. Сможете ли вы определить, почему?

Ошибку ищем в следующем коде (сначала прочитайте Примечание после второго задания!).

  #include "us_army.h"
  #include "secret_rockets.h"

  static int target_recognize(y, x)
  int y, x;
  {
    int i, ty, tx, num, sum, dam;
    register rocket_type *c_ptr;
    register struct misc *p_ptr;
    register drive_type *t_ptr;
    bigdrivetype tmp;

    change_drive(y, x);
    c_ptr = &positions[y][x];
    p_ptr = &py.misc;
    dam = proll(t_ptr->damage);
    sum = 0;

    // операции формирования указателя t_ptr всегда корректны
    // и выдают нормальное новое значение!
    for( t_ptr = &t_list[c_ptr->tptr]; ; t_ptr = &t_list[t_ptr->tptr])
     switch(t_ptr->mainval)
      {
      case 1:
        monitor_info("модель KingFish");
        if (py.flags.fail)
          monitor_info("модификация 22M");
        else
        {
       obj_descr(tmp, t_ptr, TRUE);
      set_hittype(dam, tmp);
        }
        continue;

      case 2:
        if (test_rocket(225,8, p_ptr->pac+p_ptr->ptoac, INF_MISC_ROCKET))
        {
  obj_descr(tmp, t_ptr, TRUE);
       set_hittype(dam, tmp);
      monitor_info("модель X-29");
        }
        else monitor_info("модель X-31A");
        continue;

      case 4:
        monitor_info("модель 5B55");
        new_rocket_flag = TRUE;
        sum++;
        if (py.flags.fail)
          monitor_info("модификация R");
        else
          {
  obj_descr(tmp, t_ptr, TRUE);
  set_hittype(dam, tmp);
  }
        continue;

      case 8:
        drive_flag = TRUE;
        monitor_info("модель 48H6E");
        sum += move_target(y, x, -y, -x);
        break;

      case 11:
        (void) delete_target(y, x);
        num = 12 + random(360);
        sum += num;
        for (i = 0; i < num; i++)
        {
      ty = y;
  tx = x;
  (void) summon_rocket(&ty, &tx, FALSE);
  }
        break;

      case 15:
        monitor_info("модель 3M-80E");
        py.flags.blind += randint(500) + 1;
        continue;

      case 17:
        if (test_rocket(128,0, p_ptr->pac+p_ptr->ptoac, INF_MISC_HIT))
  {
       obj_descr(tmp, t_ptr, TRUE);
      set_hittype(dam, tmp);
      monitor_info("модель Udav");
  if (py.flags.free_act)
  monitor_info("модификация X");
       else
       py.flags.slow += randint(200) + 1;
        }
        else
        monitor_info("модификация Z");
        break;

      default:
        monitor_info("Непонятное значение. Перехожу к анализу
  следующего узла...");
        continue;
      }

    return sum;
  }


Задание 2.

- Василь Василич, звонил Министр, - осторожно сообщила секретарь.

- Напомнил, что перенос испытаний невозможен ни при каких условиях. На открытие скоростной трассы ожидаютсся очень высокие персоны... Возможно, - секретарь понизила голос, - будет даже Президент!

Василь Василич раздраженно вздохнул. Подчиненный ему Вычислительнй Центр Министерства Путей Сообщения уже четвертый месяц рабоал в авральном режиме. Под новый проект автоматизации управления движением на скоростной магистрали "Сити - Аэропорт" мощное депутатское лобби выбило пятьдесят два миллиона долларов бюджетных денег. В подобной ситауции вопросам грамотной оргнизации проекта по созданию данной системы наверху уделялось минимальное внимание. Правда, Центр получил солидные суммы на подбор сотрдников, и Василь Василичу удалось набрать достаточно большой штат программистов, преимущественно через популярные сервера по подбору сотрудников и подходящие издания, где публиковались объявления о приеме на работу. Директору ВЦ повезло еще и в плане сроков - разгар проекта пришелся на конец весны, и он принял несколько десятков талантливых выпускников ведущих вузов.

Ребята буквально горели на работе. Продолжительность рабочей недели в последний перед сдачей месяц достигала ста часов. Удачное завершение подобного проекта послужило бы серьезным стартом их карьеры с прерасными перспективами. Однако такой фанатичный труд на износ в сочетании с достаточно сложными в освоениями передовыми информационными технологиями определения местоположения поезда по сигналам спутниковой группировки ГЛОНАСС вызвал в последние дни пока еще не очень серьезный, но уже заметный и очевидный рост числа выявляемых ошибок. Подобный рост в услвоиях плановой работы означал бы хорошую деятельность тестовой группы, однако падение качества на заключительном этапе являлось, без сомнения, следствием аврального режима. Но в сложившейся ситуации Василь Василич не видел ни одного приемлемого выхода.

- А, будь что будет!.. - устало махнул он рукой. В принципе Центру оставалось закончить последний блок корректировки скорости в зависимости от профиля местности, один из саых крупных в проекте. Хотя за последние четыре дня выполнить его детальное тестирование не предсталялось возможным, Директор не сомневался, что разработчики приложат все мыслимые и немыслимые усилия.

* * *

Шел второй час ночи. Степанов прикрыл воспаленные глаза. За последние три часа он переписывал эту функцию не один десяток раз. Требования-дополнения сыпались в его почтовый ящик непрерывно. Последние изменния пришлись на блок корректировки скорости, завязанный на недавно обновленные антенные фазированные решетки пятого поколения для приемников ГЛОНАСС. Степанов добавил необходимые проверки, которые гарантироали бы остановку поезда при возникновении любых внештатных состояний, затем внимательно - любимым и наиболее эффективным способом "пристального взгляда" - проанализироал код, прогнал через транслятор и наконец переключился на новое задание. Теперь предстояло запрограммировать модуль голосового синтеза текстовых сообщений, поступаемых из центра управления в формате XML, с возможностью автоматического определения каждой из трех российских кодировок.

* * *

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

- Сто девяносто девять километров, - мелодично пропел синтезированный женский голос. Машинист бросил внимательный взгляд на виртуальную панель. Странно - хотя указатель корректровки профиля местности плавал в районе красноватой отметки "Уклон", свидетельствуя о начале этапа подтормаживания, скорость плавно росла. Машинист коснулся пальцем электронного образа кнопки "Сброс ускорения", и сразу же поползла вверх полоска режима торможения. Однако скорость не уменьшалась, хотя на тестовой трассе он многократно убеждался в полной корректности работы автоводителя.

- Двести двенадцать километров, - раздалось беспристрасное сообщение равнодушного железного устройства. Машинист почувстовал, как внезапно задрожали пальцы и поймал на себе взгляд внезапно замолчавшего журналиста. Он оглянулся, и увидел, как по виску бородатого мужчины ползет капля пота...

* * *

Сможете ли вы по нижеследующему участку кода определить, почему автоводитель так и не смог понизить скорость поезда? Также обязательно прочтите Примечание в конце.

  #include "Rails.H"
  #include "AutoDriver.H"
  #include <assert.h>
  #include <stdlib.h> //нужен rand()
  #include <time.h> //для time в rand seed
  #include <stdio.h>
  #include <iostream.h> //консольный трафик

  AutoDriver::AutoDriver( unsigned int Xspeed, unsigned int Yspeed,
                          bool myW, int& maxDrivers,
                          unsigned int MFW, int SRC,
                          int* SRS, int* VelL, int* VelD )
  {

    PLokoArray = new Loko[MAX_LOKO + 1] /* массив поездов на
  участке */ ;
    PDriverArray = new Driver[MAXDRIVES + 1] /* массив автоводителей */
  ;
    if( 0 == PDriverArray)
      {
        cout << "Не хватает памяти для PDriverArray" /* надо снизить
  MAXDRIVERS! */ ;
        delete PLokoArray /* удаляем массив поездов */ ;
        std::exit(1) /* аварийный останов - тормоз */ ;
      }

      ...

      /* сканируем данные от системы ГЛОНАСС */
      for( unsigned int x = 0; x < MAX_X_GLONASS_SIZE; ++x)
     for( unsigned int y = 0; y < MAX_Y_GLONASS_SIZE; ++y)
  {
  if( (0 == x) || (0 == y) ||
             ((MAX_X_GLONASS_SIZE - 1) == x ) ||
             ((MAX_Y_GLONASS_SIZE - 1) == y ))
      /* ... контроль на краях фазированной приемной решетки ... */

  {
  if( 0 == x) /* линейное ускорение */
  {
     if( 0 == (y%10)%10 )
       SetSpeed( x , y , *VelL + (y/10)%10 ) /* снизить скорость на краях
  трассы */ ;
     else
       SetSpeed( x , y , (*Vel)*2 ) /* повысить скорость в центре */ ;
  }
  else if (0 == y) /* боковое смещение */
         *VelL = *SRS/x /* учесть профиль местности */ ;
  else if( *VelD ) /* чтобы не делить на ноль */
  *VelL = *SRS/*VelD /* уменьшить скорость под
  профиль */ ;
  }
       else SetSpeed( x , y , 0 ) /* непонятно что - лучше затормозить */ ;
  }
  }

Примечание

Все события, сюжеты, наименования и технико-технические характеристики полностью вымышлены. Любые совпадения названий, имен и ситуаций случайны.

Примеры составлены синтаксически правильно и всегда компилируются и собираются успешно. Мы исходим из того, что все поступающие на вход программы данные корректны, и как минимум не вызывают тех проблем, которые описаны в условиях задачи. То есть считается, что все строки обязательно заканчиваются нулем; как и массивы, имеют ограниченную длину; массивы указателей содержат верные значения, не вызывая неверных обращений к памяти и т. д.

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

Сомнительные ситуации, правильность которых из контекста непонятна, оговорены явно в комментариях.

Хороший компилятор или верификатор lint может сформировать предупреждение в месте потенциальной ошибки программного кода примеров.


Разное.

Специальное предложение для тех, кто хочет научиться набору текстов слепым десятипальцевым методом.
Клавиатурный тренажер "Эдди".
Программу делал я :)
Отличие этого тренажера от всех других существующих клавиатурных тренажеров, что в нем минимизирован объем сознательной работы. Он функционирует в фоновом режиме, обучая бессознательную составляющую психики, в то время как на сознательном уровне человек продолжает обычную работу - например, работает в Ворде или пишет письма.
В данной работе задействованы серьезные разработки известных психологов.

У меня вы можете приобрести эту программу со скидкой. Хотя она и так совсем дешевая - 100 рублей.


(c) 2004-2006 Сергей Бобровский bobrovsky@russianenterprisesolutions.com

Школа программирования с нуля
Все предыдущие выпуски базового курса всегда тут:
http://www.infiltration.ru/p/

Дизайн рассылки: Алексей Голубев - Web-дизайн и web-программирование


В избранное