Підручник з мови програмування D. Частина 5

П'ята частина перекладу D Programming Language Tutorial Ali Çehreli. У цій частині переведена глава Logical Expressions. Матеріал глави розрахований на новачків.
  1. Частина 1
  2. Частина 2
  3. Частина 3
  4. Частина 4


Логічні вирази
Фактична робота, яку виконує програма полягає у виразах. Будь-яка частина програми, яка створює значення або побічний ефект, називається виразом. Воно визначається широким поняттям, тому що навіть константне значення, скажімо 42, і рядковий, наприклад «hello», це вираження, оскільки вони створюють ці відповідні константи 42 і «hello».

Важливо: Не плутайте створення значення з декларацією змінної. Значенням не потрібно прив'язуватися до змінних.

Виклики функції, наприклад writeln — це вирази, до речі, тому що у них є побічні ефекти. У випадку з writeln, цей ефект накладається на стандартний потік виводу друкуванням символів на ньому. Іншим прикладом з програм, що ми написали раніше, може бути операція присвоєння, яка змінює змінну, яка стоїть ліворуч.

З-за створення значень, вирази можуть брати участь в інших виразах. Це дозволяє нам формувати більш складні висловлення з простіших. Наприклад, припустимо, що є функція названа currentTemperature, яка повертає значення поточної температури повітря, це значення, що вона виробляє, може бути безпосередньо використовуватись у вираженні writeln:

writeln("it's ", currentTemperature()," degrees at the moment.");

Цей рядок містить наступне:
  1. «it's»
  2. currentTemperature()
  3. " degrees at the moment.
  4. writeln() вираз, який використовує попередні три.
У цій главі ми обговоримо конкретні типи виразів, які використовуються в умовних висловлюваннях.

Перш, ніж йти далі я б хотів повторити оператор присвоювання ще раз, зараз підкреслюючи ці два вирази, що знаходяться ліворуч і праворуч від нього. Оператор присвоювання (=) присвоює значення вказаного виразу праворуч виразу зліва (наприклад змінної).
temperature = 23 // temperature's value becomes 23


Логічні вирази
Логічні вирази — вирази, які використовуються в Булевої алгебри. Логічні вирази те, що роблять комп'ютерні програми, приймаючи рішення, на кшталт «якщо відповідь Так, я збережу файл».

Логічні вирази можуть мати одне з двох значень: false, що означає брехня, і true, що означає істину.

Я буду використовувати writeln вираження в наступних прикладах. Якщо рядок надрукувала trueв кінці, це буде означати, що те, що надруковано в цьому рядку — це правда. Аналогічно,false буде позначати, що те, що надруковано — брехня. Наприклад, якщо цей висновок программытакой:
There is coffee: true
це означатиме, що «там є кава». Аналогічно:
There is coffee: false
передбачатиме «там кави немає». Зверніть увагу, що насправді «is», находящийсяслева не означає, що кава є. Я використовую конструкцію "… is ...: false" щоб позначити «це нетак» або «це брехня». Логічні вирази використовуються в предикатах, циклах, аргументахфункций і т. д. Важливо зрозуміти, як вони працюють. На щастя, логічні вирази дуже прості дляобъяснения і прості у використанні.

Нижче представлені логічні оператори, які використовуються в логічних виразах:
  • Оператор рівності (==) відповідає на питання «це одно цього?». Він порівнює два вираження ліворуч від нього праворуч і повертає true, якщо вони рівні і false якщо немає. По суті, значення, що повертається оператором рівності (==) — це логічний вираз
    Як приклад, припустимо, що у нас є зазначені дві змінні:
    int daysInWeek = 7;
    int monthsInYear = 12;
    Далі, це два вирази, які використовують ці значення:
    daysInWeek == 7 // true
    monthsInYear == 11 // false
  • Оператор нерівності (!=) відповідає на питання «це не одно цього». Він порівнює ці два вирази з обох його сторін і повертає результати, протилежні тим, що повертає оператор (==)
    daysInWeek != 7 // false
    monthsInYear != 11 // true
  • Оператор диз'юнкції (||) позначає «або», і повертає true якщо будь-який з логічних виразів дорівнює true

    Якщо значення виразу зліва це true, то оператор поверне true і навіть не подивиться на вираз праворуч. Якщо вираз зліва поверне false, то оператор поверне значення виразу праворуч. Цей оператор схожий на сполучник «або» в російській мові.

    Вираз зліва Оператор Вираз праворуч Результат
    false || false false
    false || true true
    true || false (не має значення) true
    true || true (не має значення) true
    import std.stdio;
    
    void main()
    {
    // false означає "ні", true означає "так"
    
    bool existsCoffee = false;
    bool existsTea = true;
    
    writeln("There is warm drink: ",
    existsCoffee || existsTea);
    }
    
    Тому що принаймні одне з двох виразів істинно логічне вираз вище видає true.
  • Оператор кон'юнкції (&&) позначає «і» і повертає true, якщо обидва вирази ліворуч і праворуч, повертають true.

    Якщо значення виразу зліва це false, то оператор поверне false і навіть не подивиться на вираз праворуч. Якщо вираз зліва поверне true, то оператор поверне значення виразу праворуч. Цей оператор схожий на союз «і» в українській мові.
    Вираз зліва Оператор Вираз праворуч Результат
    false && false (не має значення) false
    false && true (не має значення) false
    true && false false
    true && true true
  • Оператор строгої диз'юнкції (^) відповідає на питання «один або інший, але не обидва?». Цей оператор повертає true, якщо тільки один вираз повертає true, але не обидва.
    Вираз зліва Оператор Вираз праворуч Результат
    false ^ false false
    false ^ true true
    true ^ false true
    true ^ true false
    Наприклад, ця логіка, що представляє: «Я пограю в шахи, якщо тільки один з двох друзів прийде». Це можна запрограмувати так:
    writeln("I will play chess: ", jimShowedUp ^ bobShowedUp);
  • Оператор строго менше (<) відповідає на питання «Це менше цього?» (або «При сортуванні це буде вище?»)
    writeln("We beat: ", theirScore < ourScore);
  • Оператор строго більше (>) відповідає на питання «Це більше цього?» (або «При сортуванні це буде нижче?».)
    writeln("They beat: ", theirScore > ourScore);
  • Оператор нестрого менше (<=) відповідає на питання «Це менше або одно цього?» (або «При сортуванні це буде вище або на тій же поцизии?».)
    writeln("We were not beaten: ", theirScore <= ourScore);
  • Оператор нестрого менше (>=) відповідає на питання «Це більше або одно цього?» (або «При сортуванні це буде нижче або на тій же поцизии?».)
    writeln("We did not beat: ", theirScore >= ourScore);
  • Оператор інверсії (!) подразумеват «Це противоложность чогось». Він відрізняється від попередніх тим операторів, що працює тільки з одним виразом і повертає true, якщо вираз повертає false і повертає false, якщо вираз повертає true.
    writeln("I will walk: ", !existsBicycle);


Групування виразів
Цей порядок, в якому вирази обчислюються може бути укладений в дужки для того, щоб изсгруппировать. Коли вирази в дужках потрапляють в більш складні вирази, значення цих выраженийрасчитвается до того, як вони будуть використані у виразах, в які вони потрапили. Наприклад, этовыражение «якщо там є кава або чай, а також печиво або булочка, то я щасливий» може бытьзапрограммировано приблизно так, як зазначено нижче:
writeln("I am happy: ", (existsCoffee || existsTea) && (existsCookie || existsScone));
Якщо ці вкладені вираження не були укладені в дужки, то вони будуть виконані з урахуванням приоритетовоператоров за правилами D (які були успадковані з мови C). Оскільки в цих операторконъюнкции && пріоритет вище, ніж оператор диз'юнкції ||, написання вираження безскобок не буде розраховано, як передбачається.
writeln("I am happy: ", existsCoffee || existsTea && existsCookie || existsScone);
Оператор кон'юнкції && виконається в першу чергу, і весь вираз буде семантическиэквивалентно наступного виразу:
writeln("I am happy: ", existsCoffee || (existsTea && existsCookie) || existsScone);
Це в корені має інше значення: «Якщо там є кава або чай з печивом або булочка, то ясчастлив».

Читання вхідних даних типу bool
Всі значення типу bool, представлені вище, надруковані як «хибність» або «істина». Але це неработает у зворотному напрямку: ці рядки «хибність» і «істина» не автоматично читаються як этизначения false та true. З цієї причини, ці вхідні дані повинні зчитуватися какстроки а потім конвертуватися в значення типу bool.

Оскільки в одному з вправ нижче потрібно, щоб Ви ввели «хибність» і «істина», я вынуждениспользовать можливості D, що я не пояснив Вам. Я описав нижче метод, який конвертируетуказанные рядкові вхідні дані в дані типу bool. Цей метод буде вирішувати цю задачувыполнением to, який продекларований в модулі std.conv. (Ви можете побачитиConvException помилки, якщо введете що-небудь, крім «хибність» або «істина».)

Я сподіваюся, що всі частини коду, які у main() в наступних програмах і зрозумілі на даному етапі. read_bool() це той метод, в якому є нові, для Вас, можливості мови. Хоча явставил коментарі для того, щоб пояснити, що він робить, Ви можете не звертати уваги наэтот метод. Все-таки, він повинен бути в коді програми для компіляції і коректної роботи.

Вправи
  • Ми бачили вище, що ці оператори < та > використані щоб визначити, коли значення більше і менше іншого значення, але там не було оператора, який відповідає на питання «це між?», щоб визначити коли значення знаходиться між двома іншими значеннями.

    Давайте припустимо, що програміст написав наступний код для визначення, коли value між 10 і 20. Зверніть увагу, що програма не відбудеться створення як описано.
    import std.stdio;
    
    void main()
    {
    int value = 15;
    
    writeln("Is between: ",
    10 < value < 20); // ← помилка компіляції
    }
    Спробуйте взяти в дужки все це вираз:
    writeln("Is between: ",
    (10 < value < 20)); // ← помилка компіляції
    Зауважте, що ця програма все одно не відбудеться створення.
  • Поки йде пошук вирішення цієї проблеми, той же програміст виявляє, що наступні використання дужок дозволяє скомпілювати код:
    writeln("Is between: ",
    (10 < value) < 20); // ← це пройде компіляцію, але рабоет неправильно
    Зауважте, що програма працює як передбачалося і виводить «true». На жаль, цей висновок збиває з пантелику, тому що в цій програмі є баг. Подивитися наслідки цього бага можна, замінивши 15 значенням більше 20:
    int value = 21;
    Зауважте, що програма все одно виводить «true», незважаючи на те, що 21 не менше 20. Підказка: Пам'ятайте, що тип логічного виразу це bool. У цього не повинно бути сенсу, коли bool менше 20.
  • Логічні вирази, які відповідають на питання «Це між?» повинні, замість цього, відповідати на запитання: «Це більше, ніж мінімальне значення і менше, ніж максимальна?».

    Змініть вираз у цій програмі з урахуванням цієї логіки і помітите, що вона зараз виводить «true», як і очікувалося. Також можна перевірити, що це логічний вираз працює правильно з іншими значеннями. Наприклад, коли value це 50 або 1, ця програма повинна вивести «false» і коли value дорівнює 12, ця програма виведе «true».
  • Припустимо, що ми можемо піти на пляж, коли одне з наступних умов істинно:
    • Якщо відстань до пляжу менше 10 км і є велосипеди для кожного.
    • Якщо нас менше 6, і у нас є машина, і в одного з нас є водійські права.

    Як написано, наступна програма завжди виводить «true». Сконструюйте логіку так, що програма буде виводити «true», коли одна з умов вище виконається. (Коли програма запитає, введіть «true» або «false» на питання, що починаються зі слів «Is there a».). На забудьте підключити метод read_bool() при тестуванні програми:
    import std.stdio;
    import std.conv;
    import std.string;
    
    void main()
    {
    write("How many are we? ");
    int personCount;
    readf(" %s", &personCount);
    
    write("How many bicycles are there? ");
    int bicycleCount;
    readf(" %s", &bicycleCount);
    
    write("What is the distance to the beach? ");
    int distance;
    readf(" %s", &distance);
    
    bool existsCar = read_bool("Is there a car? ");
    bool existsLicense =
    read_bool("Is there a driver license? ");
    
    /*
    Замініть це 'true' нижче логічним вираженням, яке поверне
    'true', коли буде виконувати одна з умов:
    */
    writeln("We are going to the beach: ", true);
    }
    
    /*
    Будь ласка зверніть увагу на те, що цей метод включає в себе можливості,
    які будуть описані в книзі пізніше.
    */
    bool read_bool(string message)
    {
    // Виводить повідомлення
    write(message, "(false true or) ");
    
    // Читає лінію як рядок.
    input string;
    while (input.length == 0) {
    input = chomp(readln());
    }
    
    // Повертає булеве значення з рядка
    bool result = to!bool(input);
    
    // Повертає результат
    return result;
    }
    Введіть різні значення і протестуйте це логічний вираз, який Ви написали, працює правильно.
… рішення
  1. Оскільки компілятор сприймає 10 < value вже як вираз, він чекає, що після нього буде кома, щоб прийняти його як аргумент для writeln. Використання дужок навколо всього виразу не спрацює, тому що в цей час закриває дужка буде очікуватися в тому ж вираженні.
  2. Угруповання цього виразу (10 < value) < 20 видалить помилку при компіляції, тому що в цьому випадку перша частина буде розрахована і далі його результат буде порівнюватися з < 20

    Ми знаємо, що значення логічного вираження, такого як 10 < value, false або true. false та true приймають значення 0 і 1, відповідно, в цілочисельних виразах. Ми розглянемо автоматичне перетворення типів в наступних главах. В результаті, все це вираз буде еквівалентно або 0 < 20 або 1 < 20, які обидва повернуть true.
  3. Вираз «більше ніж мінімальне значення і менше, ніж максимальне», може бути запрограмовано таким чином:
    writeln("Is between: ", (value > 10) && (value < 20));
  4. «Є велосипеди для кожного» може бути запрограмовано як personCount <= bicycleCount так bicycleCount >= personCount. Інше в цьому логічному вираженні може бути відразу переведено в програмний код з вправи:
    writeln("We are going to the beach: ",
    ((distance < 10) && (bicycleCount >= personCount))
    ||
    ((personCount <= 5) && existsCar && existsLicense)
    );
    Зверніть увагу на розташування даного оператора диз'юнкції (||) робить читання зручніше, розділяючи ці два основних предиката.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.