Учебник по языку программирования D. Часть 4

Четвертая часть перевода D Programming Language Tutorial от Ali Çehreli.Другие части: Конкретные понятия, которые представлены в программе, называются переменными. Значение вроде температура воздуха или более сложный объект, как двигатель машины, могут быть переменными в программе.Каждая переменная имеет определенный тип и определенное значение. Большинство переменных также имеют имена, но некоторые являются анонимными.

В качестве примера переменной мы можем рассматривать концепцию числа учеников в школе. Так как число студентов является целым числом, int — подходящий тип, и studentCount будет достаточно описывающим именем.

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

import std.stdio;  void main (){    // Определение переменной;  это определение    // указывает,  что типом studentCount является int:     int studentCount;      // Название переменной становится ее значением:     writeln («Присутствует »,  studentCount,  » учеников.»);}

Вывод этой программы:

Присутствует 0 учеников Как видно из этой строки, значение studentCount равно 0. Согласно таблице фундаментальных типов из прошлой главы: начальное значение int равно 0.

Заметьте, что строка studentCount не появляется в выводе. Другими словами, программа не выводит «Присутствует studentCount учеников».

Значения переменных изменяются с помощью оператора =. Оператор = присваивает новые значения переменным, и по этой причине и называется оператором присвоения:

import std.stdio;  void main (){    int studentCount;     writeln («Присутствует »,  studentCount,  » учеников.»);      // Присваивание значения 200 переменной studentCount:     studentCount = 200;     writeln («Теперь присутствует »,  studentCount,  » учеников.»);}

Присутствует 0 учеников. Теперь присутствует 200 учеников. Когда значение переменной известно в момент определения, значение переменной может быть присвоено одновременно с ее определением. Это важный принцип; это делает невозможным использование переменной до момента присвоения предназначенного ей значения:

import std.stdio;  void main (){    // Одноврменное определение и присвоение значения:     int studentCount = 100;      writeln («Присутствует »,  studentCount,  » учеников.»);}

Присутствует 100 учеников. Упражнения Определите две переменные для вывода «Я обменял 20 евро по курсу 2.11». Для значения с плавающей точкой используйте double… решение import std.stdio; void main (){int amount = 20; double rate = 2.11;

writeln («Я обменял », amount,» евро по курсу », rate);}-->

import std.stdio;  void main (){    int amount = 20;     double rate = 2.11;      writeln («Я обменял  »,  amount,             » евро по курсу »,  rate);}

До этого момента весь напечатанный вывод наших программ появлялся в окне консоли. Хотя это на самом деле часто используется многими программами, на самом деле символы выводятся в стандартные потоки вывода.Стандартный вывод основан на символах; все, что печатается, сначала конвертируется в символьное представление и потом последовательно отправляется на вывод как символы. Например, целочисленное значение 100, которое мы выводили в прошлой главе не посылается на вывод как значение 100, а как три символа 1, 0 и 0.

Аналогично то, что мы обычно воспринимаем как клавиатура, на самом деле является стандартным потоком ввода программы, и он также основан на символах. Информация всегда поступает как символы для конвертацию в данные. Для примера целочисленное значение 42 на самом деле приходит через стандартный ввод как символы 4 и 2.

Эти преобразования производятся автоматически.

Это понятие последовательных символов называется символьным потоком. Так как стандартный поток ввода и стандартный поток вывода подходят под это описание, они являются символьными потоками.

Названия стандартных потоков ввода и вывода в D — stdin и stdout соответственно.

Операции над этими потоками обычно требуют имя потока, точку и название операции; например stream.operation (). Так как stdin и stdout используются очень часто, по соглашению, стандартные операции над ними могут быть вызываны без необходимости указывания имени и точки, например operation ().

writeln, которую мы использовали в предыдущих главах на самом деле является сокращением от stdout.writeln. Также write — сокращение от stdout.write. Соответственно программа «привет мир» может быть написана так:

import std.stdio;  void main (){    stdout.writeln («Hello world!»);}

Упражнения Убедитесь, что stdout.write работает также, как write… решение import std.stdio;  void main (){    stdout.writeln (1,  »,»,  2);}

Любые данные, которые были прочитаны программой, должны быть сперва сохранены в переменную. Например, программа, которая читает количество студентов из стандартного потока ввода, должна сохранить эту информацию в переменную. Типом этой конкретной переменной может быть int.Как мы убедились в предыдущей главе, нет необходимости указывать stdout, когда выводим информацию, так как он предполагается. Далее, то, что выводится, указывается как аргумент. Поэтому write (studentCount) достаточно, чтобы вывести значение studentCount. Подведем итог:

поток: stdout операция: write данные: значение переменной studentCount цель: обычно, окно терминала Обратная операции write — readf; она читает из стандартного потока ввода. Буква «f» в имени взята от «formatted», так как то, что читает эта функция, должно быть всегда представлено в определенном формате.

Также в прошлой главе мы узнали, что стандартный поток ввода называется stdin.

В случае чтения один кусочек головоломки все еще отсутствует: куда сохранить данные. Подведем итоги:

поток: stdin операция: readf данные: некоторая информация цель: ? Расположение места, куда необходимо сохранить данные, указывается с помощью адреса переменной. Адресом переменной является точное положение в памяти компьютера, где хранится ее значение.

В D символ '&', напечатанный перед именем, является указанием адреса того, что представляет эта переменная. Например, адресом studentCount является &studentCount. Здесь, &studentCount может быть прочитано как «адрес studentCount», и это недостающий кусок, который заменяет знак вопроса выше:

поток: stdin операция: readf данные: некоторая информация цель: расположение переменной studentCount Набор символа & перед именем означает взятие адреса того, что представляет это имя. Это понятие является основой ссылок и указателей, которые мы увидим в следующих главах.

Я отложу объяснение одной особенности использования readf; сейчас, примем правило о том, что первым аргументом readf должна быть строка »%s»:

readf (»%s», &studentCount); Заметка: Как я объясняю ниже, в большинстве случаев в строке также должен присутствовать пробел:» %s».

»%s» указывает, что данные должны быть автоматически преобразованы таким способом, который подходит под тип переменной. Например, когда символы '4' и '2' читаются в переменную типа int, они должны быть преобразованы в целочисленное значение 42.

Программа ниже просит пользователя ввести число учеников. Необходимо нажать клавишу Enter после окончания ввода:

import std.stdio;  void main (){    write («Сколько присутствует учеников?  »);      /*     * Объявление переменной,  которая будет использована для * хранения информации,  которая читается из потока ввода     */    int studentCount;      // Запись входных данных в эту переменную    readf (»%s»,  &studentCount);      writeln («Понял:  Присутствует »,  studentCount,  » учеников.»);}

Пропуск пробельных символов Даже клавиша Enter, которую мы нажимаем после ввода данных, сохраняется как специальный код и помещается в поток stdin. Это помогает программам обнаруживать, была ли информация введена в одной или нескольких строчках.Хотя это иногда полезно, такие специфические коды в большинстве случаев не важны для программы и должны быть удалены из ввода. Иначе они блокируют ввод и не дают читать другие данные.

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

import std.stdio;  void main (){    write («Сколько присутствует учеников?  »);     int studentCount;     readf (»%s»,  &studentCount);      write («Сколько присутствует преподавателей?  »);     int teacherCount;     readf (»%s»,  &teacherCount);      writeln («Понял:  Присутствует »,  studentCount,  » учеников»,             » и»,  teacherCount,  » преподавателей.»);}

К сожалению, теперь программа застряла при чтении второго int:

Сколько присутствует учеников? 100 Сколько присутствует преподавателей? 20 <- Программа зависает здесь Хотя пользователь ввел число преподавателей равным 20, специальные коды, которые представляют клавишу Enter при чтении предыдущего значения 100, все еще находятся в потоке ввода и блокируют его. Символы, которые хранятся в потоке ввода аналогичны следующим:

100[EnterCode]20[EnterCode] Первый символ [EnterCode] блокирует ввод.

Решением этой проблемы является добавление пробела перед %s для обозначения того, что код клавиши Enter, который может быть встречен перед чтением числа преподавателей, не важен:» %s». Пробелы в строке форматирования используются для чтения и игнорирования нуля или более невидимых символов, которые могут предшествовать вводу. Такие символы включают в себя: сам символ пробела, коды, которые представляют клавишу Enter, символ клавиши Tab и другие, называемые пробельными символами.

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

// …    readf (» %s»,  &studentCount);// …    readf (» %s»,  &teacherCount);// …

Вывод:

Сколько присутствует учеников? 100 Сколько присутствует преподавателей? 20 Понял: Присутствует 100 учеников и 20 преподавателей. Дополнительная информация Упражнения Введите не числовые символы, когда программа ожидает целочисленное значение и пронаблюдайте, как программа работает некорректно… решение Когда символы не могут быть преобразованы в желаемый тип, stdin переводится в состояние непригодное к использованию. Например, ввод «abc», когда ожидается int, сделает stdin непригодным к использованию.

© Habrahabr.ru