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

Инвестирование с нуля

  Все выпуски  

Программирование на Си и С++ с нуля 136) Условный оператор


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

136) Программирование на Си и С++: Условный оператор

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

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

На форме размещается поле-метка Label1, поле ввода Edit1 и кнопка Button1 с названием "Бросить кубик".

Ввести в поле ввода число.
Нажать на кнопку "Бросить кубик".
Сгенерировать случайное число в диапазоне от 1 до 6.
Сравнить это число со значением, введенным в поле ввода.
Если они равны, вывести в поле-метку строку "Вы угадали!".
В противном случае вывести в поле-метку строку "Вы не угадали...".

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

Условный оператор в С++ записывается так:

  if ( условие ) действие ;

if - это зарезервированное слово (переводится как ЕСЛИ). Условие - это выражение, возвращающее логическое значение типа bool. Действие - это оператор С++, который выполняется только если условие истинно (равно true). В противном случае никаких действий не происходит и управление передается следующему оператору.

Прежде чем запрограммировать условие, надо разобраться с генератором случайных чисел. Это очень полезная стандартная функция, которая востребована во множестве приложений. Она называется Random() и при каждом обращении выдает случайное число в диапазоне от 0 до заданного аргумента - 1. То есть Random(6) будет выдавать числа в диапазоне от 0 до 5.

Сначала создадим программу, которая по нажатию на кнопку будет выводить в поле-метку очередное выпавшее значение виртуального кубика. Для этого достаточно подготовить такой обработчик нажатия на кнопку:

  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
   int k;
   k = Random(6) + 1; // расчет случайного значения
   Label1->Caption = IntToStr(k); // вывод случ.зн. в поле
  }

В работе этой программы есть одна особенность. Если ее закрыть, а потом запустить снова, то вся выдаваемая случайная последовательность будет снова повторена - вновь на виртуальном кубике выпадут значения 1,1,6,2,2,5... (в зависимости от версии библиотеки C++ она может отличаться, но всегда будет повторяться). Это удобно для отладки - тестирования программы на повторяющейся последовательности, но на практике надо, чтобы каждый раз выдавались непредсказуемые числа. Поэтому необходимо однократно вызвать функцию Randomize(), которая случайно инициализирует генератор случайности - вызовем ее, например, в обработчике FormCreate события создания формы OnCreate:

  void __fastcall TForm1::FormCreate(TObject *Sender)
  {
   Randomize();
  }

Теперь виртуальный кубик будет всегда генерировать неповторимые последовательности. Запустите программу и проверьте.

Дополним код обработчика нажатия на кнопку проверкой, совпадает ли сгенерированное число с числом, введенным в поле Edit1. В качестве проверки надо записать выражение, возвращающее логическое значение (да, нет). Такое значение можно получить с помощью операций сравнения (равно, не равно, больше, меньше). Вот как эти операции записываются в С++:

   == равно
   != не равно
   > больше
   >= больше или равно
   < меньше
   <= меньше или равно

Не перепутайте знак оператора присваивания = с операцией сравнения == ! Это частая ошибка начинающих, и компилятор ее подчас игнорирует.

   2 == 2 // true
   2 > 3 // false
   2 != 3 // true
   3.999 >= 4 // false

Сравнение числа с введенным значением делает следующий код:

  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
   int k;
   k = Random(6) + 1; // расчет случайного значения
   Label1->Caption = IntToStr(k); // вывод случ.зн. в поле

   int n; // переменная, в которой будем
  // хранить введенное пользователем значение

   n = StrToInt(Edit1->Text);

   // сравниваем :
   if( k == n ) Label1->Caption = "Вы угадали!";
  }

Запустите программу и проверьте, как она работает.

Команда Label1->Caption = "Вы угадали!" выполняется только в том случае, если значение переменной k равно значению переменной n. В противном случае ничего не происходит.

Команды С++ всегда отделяются друг от друга точкой с запятой. Условный оператор можно переписать так:

   if( k == n )
     Label1->Caption = "Вы угадали!";

Хотя команда вывода текстовой константы в поле-метку расположена на следующей строке, она не отделена от условного оператора точкой с запятой, поэтому считается его частью, которая выполняется в зависимости от условия. А вот в случае

   if( k == n ) ;
     Label1->Caption = "Вы угадали!";

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

Пока мы реализовали лишь одну условную ветку - вывод строки при совпадении. А что делать в противном случае, если условие не выполнено? Существует расширенная форма условного оператора. Вышеописанная форма работает по схеме ЕСЛИ, ТО. Расширенная форма работает по схеме ЕСЛИ ТО, ИНАЧЕ:

   if( условие ) команда-1;
   else команда-2;

Ключевое слово else переводится как ИНАЧЕ. Команда-1 выполняется, если условие истинно, а команда-2 выполняется , если условие ложно. Таким образом, в расширенном условном операторе обязательно произойдет хоть какое-то действие.

Вот как полностью запишется наш алгоритм на языке С++:

  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
   int k;
   k = Random(6) + 1; // расчет случайного значения
   Label1->Caption = IntToStr(k); // вывод случ.зн. в поле

   int n; // переменная, в которой будем
  // хранить введенное пользователем значение

   n = StrToInt(Edit1->Text);

   // сравниваем :
   if( k == n ) Label1->Caption = "Вы угадали!"; // в случае равенства
   else Label1->Caption = "Вы не угадали..."; // в противном случае
  }

В С++ существует понятие составного оператора - группы команд, которая выполняется как один оператор. Такая группа просто заключается в знакомые фигурные скобки. Тогда, если в условном операторе в зависимости от условвия нужно выполнить не один оператор, а группу, то вся эта группа заключается в фигурные скобки как одно целое (за закрывающей фигурной скобкой точка с запятой не ставится).

В следующем примере по нажатию на кнопку Button1 вводится из поля Edit1 число и проверяется, больше ли оно 10. Если да, то в поле-метку Label1 выводится удвоенное значение этого числа, а если нет - то в поле Label1 выводится удесятеренное значение:

   void __fastcall TForm1::Button1Click(TObject *Sender)
  {
   int n;
   n = StrToInt(Edit1->Text);

   if( n > 10 )
    { // эта часть кода выполняется,
  // если n больше 10:
  n = n * 2;
  Label1->Caption = IntToStr(n);
    }
   else
    { // эта часть кода выполняется,
  // если n меньше или равно 10:
  n = n * 10;
  Label1->Caption = IntToStr(n);
    }
  }

Данный код можно оптимизировать (вынести повторяющуюся команду):

  ...
   if( n > 10 ) n = n * 2;
   else n = n * 10;

   Label1->Caption = IntToStr(n);

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

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

   if( n > 0 )
     {
     x = 2;
     if( n > 5 ) x = x + 1;
     if( n > 15 ) x = x - 4;
     }

Таким образом можно конструировать весьма сложные алгоритмические последовательности.

Иногда бывает нужным проверить в условии сразу несколько значений. Например, надо, чтобы значение N было больше 0, а значение X не равно 5. Такие выражения можно объединять условными операциями. Если надо, чтобы обязательно выполнялись все промежуточные условия, они объединяются так называемым логическим И :

   (n > 0) И (x != 5)

В качестве логического И в языке С++ используются символы &&:

   if( (n > 0) && (x != 5) ) ...

Если достаточно, чтобы было истинно хотя бы одно из условий (или одно, или другое), используют логическое ИЛИ - оно обозначается символами ||:

   if( (n > 0) || (x != 5) ) ...

В следующий раз изучаем отладку программы по шагам - в C++Builder есть замечательная возможность выполнения программы по одному оператору, с остановкой и анализом промежуточных результатов.

Кроме того, рассмотрим, как сделать программу-бот, способную имитировать процесс общения с человеком :) Если вы смотрели "Хоттабыч" :) , то там как раз такая программа была, в которую Хоттабыч влюбился :)
Вот мы ее и сделаем - а нужен для этого условный оператор, и все :)

Задание на условный оператор.
1. Ввести два числа a и b и напечатать максимальное из них.
2. Ввести три числа x, y, z. Напечатать минимальное из них.
3. Ввести три числа x, y, z. Найти, что больше - их сумма или их произведение.
4. Ввести три числа x, y, z. Если x > y > z, то напечатать разность x-z, в противном случае - максимальное из трех.
5. Ввести два числа a и b. Если a > b, то изменить значение a на произведение a и b, в противном случае изменить значение b на сумму a и b.
Напечатать результирующие значения a и b.

Задачки Откуда-то из Сети:

Юзер Вася Чайников познакомился в чате с 16-ти летней девушкой Машей и попросил прислать ее фотку. Так как Маша не знает других форматов, кроме bmp, ее фотка занимает 15 Мб. У Васи коннект с провайдером на 2400 бит/сек. При этом связь рвется каждые 20 минут, а дозвон после этого занимает 30 минут. Льготный тариф действует с 3:00 до 5:00. Сколько лет будет девушке Маше, когда Вася докачает ее фотку?

Юзер Вася Чайников узнал, что у хакера Вовы Крутого появился новый CD-ROM с пиратской игрой. Поскольку у Васи нет дисковода CD-ROM, он решил скопировать себе игру с помощью дискет. Объем игры - 750 Мб, объем дискеты - 1,44 Мб, всего у Васи 10 дискет. Путь от дома Чайникова до дома Крутого занимает полчаса. Сколько времени потратит Вася, прежде чем обнаружит, что игра запускается только при наличии CD-ROM?

Программист Сидор Пентюхов пишет девушке, с которой познакомился в чате, 2 письма в день объемом 4 килобайта каждое, а юзер Вася Чайников - 5 писем по 2 килобайта. Каков будет их суммарный траффик к тому моменту, как они обнаружат, что переписываются друг с другом?

Хакер Вова Крутой написал троян, рассылающий себя по адресам из адресной книги. У среднего пользователя в адресной книге - 30 адресов. Из-за ошибки в программе троян вместо того, чтобы отсылать пароль с зараженной машины Вове, отсылает пароль Вовы на зараженную машину. Сколько человек узнает пароль хакера Вовы Крутого прежде, чем появится антивирус?


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

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


Вышел мой учебный курс "Технологии Delphi. Разработка приложений для бизнеса".
http://shop.piter.com/book/978591180282/

В книге описаны десятки технологий, каждой из которых посвящены отдельные книги. Таким образом, купив одну мою книгу, вы существенно сэкономите :) В книге полностью описан язык Delphi (версия 2006, полностью совместимая с Turbo Delphi) для обеих платформ - Win32 и .NET. Охвачены также темы работы с файлами на этих платформах, создания файл-серверных, клиент-серверных, распределенных приложений, веб-программ (Indy, ASP.NET, веб-сервисы). Описаны языки SQL и OCL. Немало глав посвящены истории программирования и различных технологий. Особое внимание уделено созданию программ с помощью технологии ECO и языка моделирования UML - программы фактически рисуются, и теперь даже для создания корпоративных приложений и их переноса в Интернет не обязательно знать программирование!
Отдельная часть отведена технологиям организации групповой работы, управления требованиями, контроля версий, локализации и тестирования.
Тут подробнее про книгу.

Другие мои книги, которые пока доступны в продаже:


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


В избранное