Последние записи
- Windows 10 сменить администратора
- Рандомное слайдшоу
- Событие для произвольной области внутри TImage
- Удаление папки с файлами
- Распечатка файла
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
20th
Авг
Маленькие помощники программиста
Ежедневно мы сталкиваемся с рутинной работой, которая отнимает львиную долю нашего времени. В этой статье я попробую «приучить» читателя к созданию маленьких помощников, оптимизирующих работу или сокращающих время рутинных операций…
Маленькие помощники программиста
Алексей Шишкин
by Alex Cones www.programmersforum.ru
http://www.programmersforum.ru/member.php?u=40711
В фантастических фильмах мы часто видим, что человека окружают маленькие роботы, которые помогают ему, выполняют его рутинную работу. Рыботы пылесосы убирают пыль и мусор, маленькие роботы кофеварки подадут Вам свежий кофе, а маленький робосекретарь напомнит Вам о важной встрече. В жизни все не так просто.
Но, не смотря на такую жестокую реальность, программисты главным образом живут в мире виртуальном. Поэтому ничто не мешает им улучшать свою жизнь, создавая «роботов»-помощников. «Но какие-же помощники могут быть у программиста?» – скажете Вы. Я постараюсь ответить на Ваш вопрос, опираясь на собственный опыт.
История появления…
Итак, первая вещь, которая была создана мной для облегчения собственной жизни – это «Заполнялкин» (см. рисунок 1):
Эта программа предназначалась для того, чтобы оптимизировать написание больших блоков кода, отличающихся только ссылками. Так, например, введя шаблон:
Label@@.Caption := IntToStr(@@);
Можно было получить практически неограниченное количество следующих строк:
Label1 := IntToStr(1);
Label2 := IntToStr(2);
Label3 := IntToStr(3);
Label4 := IntToStr(4);
Label5 := IntToStr(5);
Кстати говоря, данные строки были получены с помощью вышеописанной программы. Итак, вопрос создания многократной записи большого количества похожего кода уже не стоял, и я занялся другими проблемами.
Второй программой стал Resource Builder (см. рисунок 2):
Да, возможно некоторые станут упрекать меня за то, что такое название уже существует, но я ведь не собираюсь продавать это творение, поэтому не обеспокоен нарушением авторских прав на название программы. Моя версия создателя ресурсов к программам отличалась тем, что в ней можно было добавить любой файл в ресурсы к программе.
Итак, вопрос удобства создания программ уже не стоял, я приступил к улучшению окружающей меня обстановки: я создал G.A.P. Создать эту программу меня вдохновили действия Educated Fool – он создал excel-ский макрос, который упаковывал проект в архив, создавал к нему превью и отправлял на FTP сервер. По аналогии моя программа делает снимок экрана (или части его ? по выбору пользователя), дает возможность создать превью к снимку, отметить на нем что-то и отправить на сервис хранения картинок, оставив ссылку на картинку в буфере обмена (см. рисунок 3):
* Комментарий автора
На этом месте я хочу предупредить читателя о том, что данная статья задумывалась вовсе не как реклама этих программ, а как пособие начинающему «импруверу» (от англ. improve – улучшать). Не бойтесь экспериментировать, и запомните одну вещь – ЛЮБАЯ работа может быть оптимизирована. Даже если кажется, что это не так.
Однажды мне потребовалось залить на файлообменный сервис достаточно большой файл. С моей полу-диалапной скоростью эта задача имеет решение только посредством FTP доступа. К счастью сервис предоставляет такую услугу. Радости моей не было предела и на первую же ночь я поставил на загрузку злополучный файл. Проснувшись утром и просмотев логии, я ужаснулся – сервер отключает меня каждые 15 минут бездействия. Даже если в этот момент загружается файл. Выход был лишь один – отправлять команду просмотра каталогов каждые 10 минут (благо для этого была выделена отдельная кнопка). Но не кликать-же по ней каждые десять минут, пока файл не загрузится? Хотя-я… Собственно, почему нет? За 15 минут был создан Click Shot (программа, которая будет кликать за меня в нужную точку экрана через заданный промежуток времени)
Думаю, лишним будет говорить то, что файл был успешно загружен.
Вчера один из моих товарищей вставил в мой ноутбук свою флешку. Несмотря на то, что на ней были только документы, Windows спросила разрешения запускать с неё программы. Снизойдя до отказа, я включил отображения скрытых и системных файлов и обнаружил autorun и exe-шник. Открыв авторан, я понял, почему антивирус продолжал молчать
[AutoRun
;lsbvrkskjvbliurbsv
;srvlbsrvksrjksr
open = klbhk.exe
;kjbsjvbkvksjvn
Одна закрывающаяся скобка… И план вторжения армий провалился… Но что-то я отвлекся. Удаление файлов прокатывать не захотело по причине аттрибута «системный» у обоих файлов. Форматировать флешку мне не позволили, и я накатал программу, изменяющую аттрибуты каталогов и файлов по выбору пользователя. Так появился на свет A.ch (см. рисунок 5):
Заключение
В завершение статьи хочу отметить, что каждая решенная проблема приносит удовольствие, но лично для меня большее удовольствие приносит решение проблемы. Дерзайте, и да прибудут с вами маленнькие помощники программиста!
Ссылки
. Заполнялкин. Версия 1.0 http://www.programmersforum.ru/showpost.php?p=367784&postcount=26
. Resource Builder http://www.programmersforum.ru/showthread.php?t=69505
. GAP http://www.programmersforum.ru/showthread.php?t=69505
. Click Shot http://www.programmersforum.ru/showthread.php?t=92768
. A.ch – Attribute Changer http://www.programmersforum.ru/showthread.php?t=104574
Скачать этот номер можно по ссылке.
Ознакомиться со всеми номерами журнала.
20th
Рассылка. Выпуск 72.
От ведущего.
Здравствуйте. Сегодня у нас очередной выпус рассылки от клуба программистов. Этот 72 выпуск посвящен пятому номеру журнала ПРОграммист. Мы его долго ждали и не зря. Некоторые заметки и статьи мы просмотрим в этой рассылке.
19th
Авг
УРОК 11. ПРЕИМУЩЕСТВА ИСПОЛЬЗОВАНИЯ БИБЛИОТЕКИ ЭТАПА ВЫПОЛНЕНИЯ
Из урока 9 вы узнали, как разделить ваши программы на небольшие легко управляемые части, называемые функциями и выполняющие определенную задачу. Одно из преимуществ использования функций заключается в том, что вы можете часто применяемую функцию, созданную для одной программы, использовать в другой программе. Как вы узнаете из этого урока, большинство компиляторов C++ обеспечивают широкий набор функций, использующихся в программах и называющихсябиблиотекой этапа выполнения. Применение этих функций сокращает объем программирования, который вы должны выполнить самостоятельно. Вместо этого ваша программа просто вызывает функции библиотеки этапа выполнения. В зависимости от компилятора библиотека этапа выполнения может состоять из тысяч функций. В данном уроке описывается использование таких функций в ваших программах. К тому времени, когда вы закончите этот урок, вы освоите следующие основные концепции:
• Библиотека этапа выполнения представляет собой набор функций, обеспечиваемых вашим компилятором, которые вы можете легко использовать в программах.
• Для использования функций библиотеки этапа выполнения вы должны включить соответствующие заголовочные файлы, содержащие прототипы функций.
• Некоторые компиляторы обращаются к библиотеке этапа выполнения как к интерфейсу прикладных программ или API.
Большинство библиотек этапа выполнения содержат сотни прикладных функций, которые помогут вам сохранить огромное количество времени и быстро разработать сложные программы. Вы узнаете, что очень легко использовать функции библиотеки этапа выполнения!
19th
УРОК 9 ЗНАКОМСТВО С ФУНКЦИЯМИ
По мере увеличения размера и сложности ваших программ вам следует разделить их на небольшие легко управляемые части, называемыефункциями. Каждая функция в вашей программе должна выполнять определенную задачу. Например, если вы пишете программу платежей, можете создать одну функцию, определяющую количество часов, отработанных служащим, вторую функцию, определяющую сверхурочную оплату, третью функцию, выводящую на печать и т. д. Если программе необходимо выполнить определенную задачу, то она вызываетсоответствующую функцию, обеспечивая эту функцию информацией, которая ей понадобится в процессе обработки. Из этого урока вы узнаете, как создавать и использовать функции в ваших программах на C++. К концу данного урока вы освоите следующие основные концепции:
• Функции группируют связанные операторы для выполнения определенной задачи.
• Ваша программа вызывает функцию, обращаясь к ее имени, за которым следуют круглые скобки, например bеер ().
• После завершения обработки большинство функций возвращают значение определенного типа, например int или float, которое программа может проверить или присвоить переменной.
• Ваши программы передают параметры (информацию) функциям, например имя, возраст или оклад служащего, заключая параметры в круглые скобки, которые следуют за именем функции.
• C++ использует прототипы функций для определения типа возвращаемого функцией значения, а также количества и типов параметров, передаваемых функции.
По мере увеличения ваших программ использование функций становится их неотъемлемой необходимостью. Однако, как вы увидите, создавать и использовать функции в C++ очень легко.
19th
УРОК 8. ПОВТОРЕНИЕ ОДНОГО ИЛИ НЕСКОЛЬКИХ ОПЕРАТОРОВ
Из урока 7 вы узнали, как использовать в ваших программах оператор C++if для принятия решений. С подобным принятием решений тесно связана способность повторять одну или несколько инструкций определенное число раз или до достижения некоторого условия. В этом уроке вы будете использовать итеративные конструкции C++ для повторения одного или нескольких операторов. К концу данного урока вы освоите следующие основные концепции:
- Для повторения операторов определенное число раз ваши программы используют оператор C++ for.
- С помощью оператора C++ while программы повторяют операторы до тех пор, пока указанное условие истинно.
- Оператор C++ do while позволяет программам выполнять операторы по крайней мере один раз, а затем, возможно, повторять операторы, основываясь на определенном условии.
Возможность повторять операторы очень важна в программировании. Экспериментируйте с программами, представленными в этом уроке. К концу урока вы сможете значительно усовершенствовать свои возможности программирования на C++.
ПОВТОРЕНИЕ ОПЕРАТОРОВ УКАЗАННОЕ ЧИСЛО РАЗ
Одной из наиболее широко используемых операций в ваших программах является повторение одного или нескольких операторов определенное число раз. Например, одна программа могла бы повторять один и тот же оператор, чтобы напечатать пять копий файла, а другая могла бы повторять некоторый Набор операторов 30 раз, чтобы определить, поднялась или упала цена ваших 30 акций. Оператор C++ forпредоставляет чрезвычайно простую возможность вашим программам повторять один или несколько операторов указанное число раз.
Если ваша программа использует оператор for (часто называемый цикломfor), она должна указать переменную, которая называется управляющей переменной, хранящей количество выполнений цикла. Например, следующий цикл for использует переменную count для хранения количества выполнений цикла. В данном случае цикл будет выполнен десять раз.
for (count = 1; count <= 10; count++)
оператор;
Цикл for состоит из четырех частей. Первые три части управляют количеством выполнений цикла. Сначала оператор count = 1, присваивает переменной управления начальное значение. Цикл for выполняет эту инициализацию один раз при запуске цикла. Далее цикл проверяет условие count <= 10. Если условие истинно, цикл for выполняет следующий оператор. Если условие ложно, цикл завершается и программа продолжает свое выполнение с первого оператора, следующего за циклом. Если условие истинно и цикл for выполняет свой оператор, то после этого цикл увеличивает переменную count, используя оператор count++. Далее программа проверяет условие count <= 10. Если это условие все еще истинно, то опять повторяется выполнение оператора внутри цикла, увеличение и проверка переменной count
for (count = 1; count <= 10; count++)
Инициализация Проверка Увеличение
Следующая программа FIRSTFOR.CPP использует цикл for для вывода на экран дисплея значений от 1 до 100:
#include <iostream.h>
void main(void)
{
int count;
for (count = 1; count <=100; count++) cout << count <<‘ ‘;
}
Как видите, оператор for инициализирует переменную count значением 1. Затем цикл проверяет, меньше ли значение переменной count или равно 100. Если это так, цикл for выполняет соответствующий оператор и затем увеличивает count, повторяя проверку. Экспериментируйте с этой программой, изменяя значение 100 на 10, 20 и даже 5000.
Следующая программа ASKCOUNT.CPP выводит сообщение, запрашивающее пользователя ввести число, при котором цикл должен завершиться. Затем программа выводит числа от одного до указанного значения:
#include <iostream.h>
void main(void)
{
int count;
int ending_value;
cout << «Введите конечное значение и нажмите Enter: «;
cin >> ending_value;
for (count = 0; count <= ending_value; count++)
cout << count << ‘ ‘;
}
Экспериментируйте с этой программой, вводя разные числа, например 10, 1 и даже 0. Если вы вводите значение 0 или 1, цикл for никогда не выполняется, потому что условие count <= ending_value сразу же ложно. Помните, если вы введете значение вне диапазона значений, которые может хранить переменная типа int, возникнет ошибка переполнения. Например, запустите программу и введите значение 50000. Поскольку это значение превышает наибольшее возможное для переменной типа int, то переполнение приводит к отрицательному значению, которое предотвращает выполнение цикла.
Циклы for C++ поддерживают составные операторы
Из урока 7 вы узнали, что если программы выполняют несколько операторов внутри if или else, то такие операторы следует сгруппировать внутри левой и правой фигурных скобок. Это же относится и к нескольким операторам в цикле for. Следующая программа ADD1_100.CPP зацикливает числа от 1 до 100, выводя и добавляя каждое число в общий итог:
#include <iostream.h>
void main(void)
{
int count;
int total = 0;
for (count = 1; count <= 100; count++)
{
cout << «Прибавляю » << count << » к » << total;
total = total + count;
cout << » получаю » << total << endl;
}
}
Группируя операторы внутри фигурных скобок, цикл for тем самым может выполнить несколько операторов за один проход (называемый umepa-циейцикла).
Изменение и увеличение цикла for
Все представленные до настоящего момента циклы for увеличивали управляющую переменную цикла на 1 на каждой итерации цикла. Однако цикл for не обязывает ваши программы увеличивать эту переменную на единицу. Следующая программа BY_FIVES.CPP выводит каждое пятое число в диапазоне от 0 до 100:
#include <iostream.h>
void main(void)
{
int count;
for (count = 0; count <= 100; count += 5)
cout << count << ‘ »;
}
Если вы откомпилируете эту программу, на вашем экране будут отображаться числа 0, 5,10 и т. д. до 100. Обратите внимание, что оператор цикла for использует для увеличения переменную count.
count += 5;
Если вы хотите добавить некоторое значение к текущему значению переменной, а затем присвоить результат той же переменной, C++ позволяет вам сделать это двумя способами. Первый: предположим, вашей программе необходимо добавить значение 5 к переменной count, это можно сделать, как показано ниже:
count = count + 5;
Второй: C++ позволяет вам использовать краткую запись, представленную ниже, для добавления значения 5 к переменной count.
count += 5;
Поскольку это легче записать, то данная краткая форма является общепринятой внутри циклов.
При использовании цикла for вы не обязаны продвигать счетчик в сторону увеличения. Следующая программа CNT_DOWN.CPP использует цикл forдля вывода чисел в порядке уменьшения от 100 до 1:
#include <iostream.h>
void main(void)
{
int count ;
for (count = 100; count >= 1; count—)
cout << count << ‘ ‘;
}
Как видите, цикл for инициализирует переменную count значением 100.На каждой итерации цикл уменьшает значение этой переменной на 1. Цикл завершается, когда переменная count содержит значение 0.
Остерегайтесь бесконечных циклов
Как вы уже знаете, цикл for предоставляет вашим программам способ повторять связанные операторы определенное количество раз. Используя переменную управления, цикл for по существу считает количество выполненных итераций. Когда цикл достигает своего конечного условия, ваша программа прекращает повторение операторов и продолжает свое выполнение с первого оператора, следующего за циклом for.
К сожалению, из-за ошибок в программах в некоторых случаях цикл никогда не достигает своего завершающего условия и, таким образом, зацикливается навсегда (или до тех пор, пока вы не прервете программу). Такие не завершающиеся циклы называются бесконечными циклами. Другими словами, это циклы, не имеющие способа для завершения. Например, следующий оператор for создает бесконечный цикл:
for (count = 0; count < 100; wrong_variable++)
// операторыКак видите, цикл for использует переменную count в качестве своей управляющей переменной. Однако в секции цикла увеличения программа увеличивает не ту переменную. В результате цикл никогда не увеличивает переменную count, и она никогда не будет иметь значение больше или равно 100. Таким образом, этот цикл превращается в никогда не завершающийся бесконечный цикл.
Важно обратить внимание, что циклы for не ограничиваются использованием переменных типа int в качестве их управляющих переменных. Например, следующая программа LOOPVAR.CPP использует переменную типа char для вывода букв алфавита внутри одного цикла и переменную типа float для вывода чисел с плавающей точкой внутри другого цикла:
#include <iostream.h>
void main(void)
{
char letter;
float value;
for (letter = ‘A’; letter <= ‘Я’; letter++)
cout << letter;
cout << endl;
for (value = 0.0; value <= 1.0; value += 0.1)
cout << value << ‘ ‘;
cout << endl;
}
Если вы откомпилируете и запустите эту программу, на экране появится следующий вывод:
АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
Повторение цикла определенное число раз
Одна из наиболее общих операций, которую будут выполнять ваши программы, состоит в повторении одного или нескольких операторов определенное количество раз. Оператор C++ for позволяет вашим программам сделать именно это. Такой оператор for использует управляющую переменную, хранящую количество выполнений цикла. Общий формат оператора for выглядит так:
for (инициализация; проверка; увеличение)
оператор;При запуске этот цикл for присваивает начальное значение управляющей переменной цикла. Далее программа проверяет условие цикла. Если условие истинно, она выполняет операторы внутри цикла, затем увеличивает управляющую переменную цикла и повторяет проверку условия. Если условие истинно, процесс повторяется. Если же условие ложно, цикл for завершается и программа продолжает свое выполнение с первого оператора, следующего за циклом for.
ВЗГЛЯД НА ЦИКЛ while
Как вы только что узнали, цикл C++ for позволяет вашим программам повторять один или несколько операторов определенное количество раз. Однако в некоторых случаях программе необходимо повторять операторы, пока удовлетворяется (истинно) некоторое условие. Например, в следующих уроках вы узнаете, как читать содержимое файла. Такие программы могли бы повторять цикл, пока не встретится конец файла. В ситуациях, когда программам необходимо выполнять цикл, пока удовлетворяется некоторое условие (но не обязательно определенное количество раз), ваши программы могут использовать оператор C++ while.Общий формат оператора while выглядит так:
while (условие_верно)
оператор;
Если ваша программа встречает оператор while, она проверяет заданное условие. Если условие истинно, программа выполняет операторы циклаwhile. После выполнения последнего оператора в цикле, цикл while опять проверяет условие. Если условие все еще истинно, повторяются операторы цикла и повторяется данный процесс. Когда условие, наконец, становится ложным, цикл завершается и программа продолжает свое выполнение с первого оператора, следующего за циклом. Следующая программа GET_YN.CPP просит вас ввести Д для да или Н для нет. Затем программа использует цикл while для чтения символов с клавиатуры, пока пользователь не введет Д или Н. Если пользователь вводит значение, отличное от Д или Н, программа сигналит встроенным динамиком, записывая символ сигнала ‘\а’ в выходной поток cout :
#include <iostream.h>
void main(void)
{
int done = 0; // Устанавливается в состояние „истина», если введены Д или Н char letter;
while (! done){
cout << «\nВведите Д или Н» << » и нажмите Enter для продолжения: «;
cin >> letter;
if ((letter == ‘Д’) II (letter == ‘д’))
done = 1;
else if ((letter == ‘Н’ ) II (letter == ‘н’))
done = 1;
else cout << ‘\а’; // Играть сигнал динамика для неверного символа
}
cout << «Вы ввели букву » << letter << endl;
}
Как видите, цикл while тоже поддерживает несколько операторов, сгруппированных внутри левой и правой фигурных скобок. В данном случае программа использует переменную done для управления циклом. Пока программа не завершится (т. е. пока пользователь не введет Д илиН), цикл продолжает выполняться. Когда пользователь вводит Д или Я, программа устанавливает переменную done в значение истина и цикл завершается. Как только ваши программы начнут работать с файлами, вы регулярно будете использовать цикл while.
Повторение цикла до выполнения заданного условия
По мере усложнения ваших программ им, возможно, понадобится выполнять группы связанных операторов, пока не реализуется заданное условие. Например, программа может вычислять суммы платежей для служащих компании. В этом случае цикл будет выполняться до тех пор, пока не обработаны данные для последнего служащего. Для повторения операторов до выполнения заданного условия программы как правило, будут использовать оператор while:
while (условие)
оператор;Сталкиваясь с оператором while, программа будет оценивать условие цикла. Если условие истинно, ваша программа выполняет операторы цикла while. После выполнения последнего оператора цикла программа снова проводит проверку условия. Если условие истинно, программа повторит этот процесс, выполнит операторы, а затем повторит проверку условия. Если условие оценивается как ложь, программа продолжит свое выполнение с первого оператора, который следует за оператором while.
ВЫПОЛНЕНИЕ ОПЕРАТОРОВ ПО КРАЙНЕЙ МЕРЕ ОДИН РАЗ
Как вы уже знаете, цикл C++ while позволяет вашим программам повторять набор операторов, пока данное условие удовлетворяется. Когда программа встречает оператор while, она сначала оценивает заданное условие. Если условие истинно, программа входит в цикл. Если условие ложно, операторы цикла while никогда не выполняются. В зависимости от назначения ваших программ, возможны ситуации, когда некоторый набор операторов должен выполняться по крайней мере один раз, а затем выполнение, основываясь на некотором условии, может повторяться. В подобном случае ваши программы могут использовать цикл do while:
do
{
операторы;
}while (условие_истинно);
Если программа встречает цикл do while, она входит в цикл и запускает выполнение операторов, содержащихся в цикле. Затем программа оценивает заданное условие. Если условие истинно, программа возвращается к началу цикла:
do <—————————————-
{ |
операторы; |
} |while (условие_истинно); ———-
Если условие ложно, программа не повторяет инструкции цикла, продолжая вместо этого выполнение с первого оператора, следующего за циклом. Обычно цикл do while используется для отображения пунктов меню и затем обработки выбора пользователя. Вам требуется, чтобы программа отобразила меню по крайней мере один раз. Если пользователь выбирает какой-либо пункт меню, кроме Quit, программа выполнит пункт, а затем отобразит меню снова (повторяя оператор цикла). Если пользователь выбирает Quit, цикл завершится и программа продолжит свое выполнение с первого оператора после цикла.
Повторение операторов, если условие истинно
В зависимости от назначения программы, возможно, потребуется выполнить набор операторов, по крайней мере, один раз, и повторить операторы, если заданное условие истинно. В таких случаях ваши программы используют оператор C++ do while:
do {
оператор;
} while (условие);Когда программа встречает оператор do while, она сразу же выполняет операторы, содержащиеся в цикле. Затем программа исследует условие цикла. Если условие истинно, программа повторяет операторы цикла и процесс продолжается. Если условие цикла становится ложным, программа продолжает свое выполнение с первого оператора, следующего за оператором do while.
ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ
Итеративная обработка представляет собой способность программы повторять один или несколько операторов. В этом уроке были описаны итеративные (или циклические) операторы C++. Как вы уже знаете, оператор for позволяет вашим программам повторять один или несколько операторов заданное число раз. Используя оператор while, программы повторяют операторы до тех пор, пока указанное условие истинно. Наконец, с помощью оператора do while программы выполняют операторы, по крайней мере один раз, повторяя их, если заданное условие истинно. Из урока 9 вы узнаете, как разделить программы на небольшие легко управляемые части, называемые функциями. Однако до изучения урока 9 убедитесь, что освоили следующее:
- Оператор C++ for позволяет вашим программам повторять один или более операторов заданное число раз.
- Оператор for состоит из четырех частей: инициализации, проверяемого условия, операторов, которые повторяются, и приращения.
- Оператор for не обязывает вас увеличивать управляющую переменную цикла именно на 1 или использовать именно приращение.
- Цикл C++ while позволяет вашим программам повторять операторы, пока указанное условие истинно.
- Программы часто используют цикл while для чтения содержимого файла, пока не встретится конец файла.
- Оператор C++ do while позволяет вашим программам выполнять один или несколько операторов, по крайней мере один раз, и воз можно, повторять их на основании заданного условия.
- Программы часто используют операторы do while для работы с меню
- Если проверяемые условия в циклах, while или do whileстановятся ложью, программа продолжает свое выполнение с первого оператора, следующего за циклом.
Programming articles
Создание сайтов на шаблонах
Множество вариантов работы с графикой на канве
Шифруем файл с помощью другого файла
Перехват API функций — Основы
Как сделать действительно хороший сайт
Создание почтового клиента в Delphi 7
Применение паскаля для
решения геометрических задач
Управление windows с помощью Delphi
Создание wap сайта
Операционная система unix, термины и понятия
SQL враг или друг
Возникновение и первая редакция ОС UNIX
Оптимизация проекта в Delphi
Ресурсы, зачем нужны ресурсы
Термины программистов 20 века
Советы по созданию собственного сайта с нуля
Шифруем файл с помощью пароля
Фракталы — геометрия природы
Crypt — Delphi программа для шифрования
Рассылка, зачем она нужна и как ее организовать?
Учебник по C++ для начинающих программистов
Уроки для изучения ассемблера
Загадочный тип PCHAR
Средства по созданию сайтов
Операторы преобразования
классов is и as
Borland Developer studio 2006. Всё в одном
Создание базы данных в Delphi, без сторонних БД
Software engineering articles
19th
УРОК 7. ПРОГРАММА ПРИНИМАЕТ РЕШЕНИЕ
Как вы уже знаете, программа представляет собой последовательность инструкций, выполняемых компьютером для реализации определенных задач. Все созданные вами до сих пор простые программы на C++ выполняли операторы по порядку, начиная с первого до конца программы. По мере усложнения программ вам потребуется, чтобы выполнялся один набор операторов, если определенное условие соблюдается, и другой набор, если условие не соблюдается. Другими словами, вам потребуется, чтобы ваши программы приняли решение и соответственно отреагировали. В этом уроке описывается оператор C++ if, который будет использоваться вашей программой для принятия подобных решений. К концу данного урока вы освоите следующие основные концепции:
- Программы на C++ используют операции сравнения, чтобы определить, равны ли два значения или одно значение больше или меньше другого.
- Для принятия решений используется оператор C++ if.
- Операторы C++ могут быть простыми (одна операция) илисоставными (несколько операций, сгруппированных внутри правой и левой фигурных скобок {}).
- Ваши программы используют оператор C++ if-else для выполнения одного набора операторов, если определенное условие соблюдается, и другого набора операторов, если условие не соблюдается.
- Комбинируя несколько операторов if-else, программы могут проверять несколько условий.
- Используя логические операторы C++ И и ИЛИ, ваши программы могут проверить несколько условий, например: Есть ли у пользователя собака И долматин ли это ?
Программы, которые принимают решения, выполняют условную обработку. Другими словами, на основании результата одного или нескольких Условий программа будет выполнять определенные операторы. Экспериментируйте с программами данного урока; ваш набор инструментальных средств C++ уже достаточно обширен для создания полезных программ.
19th
УРОК 1. СОЗДАНИЕ ВАШЕЙ ПЕРВОЙ ПРОГРАММЫ
Все вы использовали компьютерные программы, такие как текстовый процессор, электронные таблицы и даже Microsoft Windows 95. Компьютерные программы, или программное обеспечение, представляют собой файлы, содержащие инструкции, которые указывают компьютеру, что следует делать. Если вы работаете в среде MS-DOS или Windows, то, например, файлы с расширениями ЕХЕ и СОМ содержат команды, которые компьютер может выполнять. Другими словами, файлы содержат специальные инструкции, выполняемые компьютером, обычно одну за другой, для решения определенной задачи. При создании программы вы указываете инструкции, которые компьютер должен выполнить. Из этого урока вы узнаете, как указать такие инструкции с помощью операторов C++. К концу данного урока вы освоите следующие основные концепции:
• При создании программы используйте текстовый редактор, чтобы ввести операторы C++ в исходный файл программы.
• Для преобразования операторов программы C++ в выполнимую программу, в единицы и нули, которые понимает компьютер, используйте специальную программу — компилятор C++.
• Для изменения или исправления программы используйте текстовый редактор.
• При нарушении одного (или более) правил программирования на C++ компилятор выдаст на экран сообщения о синтаксических ошибках. Вам следует отредактировать программу, чтобы исправить ошибки, а затем запустить компилятор снова.
Программирование представляет собой процесс определения последовательности инструкций, которые должен выполнить компьютер для решения определенной задачи. Для указания этих инструкций вы используете язык программирования, например C++. С помощью текстового редактора вы вносите программные операторы в исходный файл. Далее вы используете специальную программу — компилятор —для преобразования операторов из формата, который вы можете читать и понимать, в единицы и нули, которые понимает компьютер.
Лучший способ понять процесс создания и компиляции программы — построить простую программу на C++. Давайте этим займемся!
19th
УРОК 2. БОЛЕЕ ВНИМАТЕЛЬНЫЙ ВЗГЛЯД НА C++
В уроке 1 вы создали несколько программ на C++. В то время ваша цель заключалась в том, чтобы понять процесс создания и компиляции программ на C++, а не в том, чтобы понять операторы C++. В данном уроке вы впервые более внимательно рассмотрите операторы, из которых состоит программа на C++. Вы увидите, что большинство программ на C++ придерживаются одного и того же формата: начинаются с одного или нескольких операторов # include, содержат строку void main(void), а затем набор операторов, сгруппированных между левой и правой фигурными скобками. Из этого урока вы поймете, что эти несколько запугивающие операторы реально очень просто освоить. К концу данного урока вы изучите следующие основные концепции:
- Оператор # include обеспечивает преимущества использования заголовочных файлов, которые содержат операторы C++ или программные определения.
- Основная часть программы на C++ начинается с оператора void main(void).
- Программы состоят из одной или нескольких функций, которые, в свою очередь, состоят из операторов, предназначенных для решения определенной задачи.
- При выводе на экран ваши программы будут широко использовать выходной поток cout.
Когда вы создаете программы на C++, вы реально работаете в терминахоператоров, но не инструкций. Позже вы изучите оператор присваивания,который присваивает значения переменным, оператор if , который позволяет программе принимать решения и т. д. А пока мы просто будем ссылаться на содержимое вашей программы, как на операторы программы.
19th
Разработчики – интерфейс – пользователи
В статье написано то, что автор смог прочесть, понять и пересказать своими словами и немного того, до чего додумался сам; все то, что касается процесса взаимодействия двух человек – разработчика и пользователя. Кратко это выражается одним словом – интерфейс…
«Встречают по одежке, а провожают по уму»
Демьяненко Александр by Grenles http://www.programmersforum.ru/member.php?u=17572
Часть первая. Философия
Надо же! Почти вступление! Не скажу, что я большой профессионал, особенно по теме данной статьи, но и не скажу, что я совсем уж любитель. Я учусь писать, читать, видеть, думать, и снова начинаю этот процесс сначала*.
* Комментарий автора.
Кто-то сказал: «хочешь что-то понять, – объясни это что-то другому, – он может и не понять
сказанного тобою, но уж ты сам точно это поймешь».
Очень сложно учить чему-то профессионалов, особенно в той области, которую они знают лучше тебя, гораздо проще – стать их учеником. Однако, как ни странно, порой именно любители пишут книги для профессионалов и учат их ремеслу и только лишь потому, что не всегда профессионалы умеют выразить доходчиво свои знаний для других. Поэтому не все так плохо, но и не так просто, как кажется на первый взгляд. В мире всегда полно тех, кто задает вопрос: «А с чего мне лучше начать?». Мало того, есть еще такие профессионалы, которые проснувшись утром, понимают, что они ничего не знают из того, что должны знать. Именно поэтому каждый день они начинают с поиска и изучения новых горизонтов знания. Каждый раз, узнав больше, они понимают, что все равно ничего не знают и снова начинают бесконечный процесс приобретения знаний. Вот для этих людей и не только для них я и начал разговор на заданную тему.
Тема, которую хочу затронуть, выражается одним словом – интерфейс. Тема с одной стороны кажется простой и легкой, а с другой – это весьма сложная и обширная область знаний, которую трудно уместить в рамки одной статьи. Анализируя современный рынок программного обеспечения, множество интернет сайтов, различных печатно-книжных изделий я пришел к выводу, что знания о правилах создания интерфейса должны быть у всех, так или иначе связанных с созданием продуктов, предназначенных для пользователей, потребителей. На сегодняшний день эта область знания вполне достойна того, чтобы идти отдельным курсом в высших учебных заведениях.
От того, насколько удачно продуман и реализован интерфейс продукта, зависит 75% успеха разработчика и 100% эффективности использования потребителем конечного продукта. Случается, что и начинающие разработчики, и гранды компьютерной индустрии, как студенты на экзаменах, «засыпаются» на плохо сделанном интерфейсе для своих великих проектов. К сожалению, не всегда с первого раза удается найти удобный способ взаимодействия пользователя и продукта. То, что ясно разработчику, не всегда очевидно пользователю и наоборот. Почти как мужчина и женщина всегда говорят на разных языках, так разработчик и пользователь живут и мыслят на основе разных категорий.
Садясь за статью и желая раскрыть тему полнее и правильнее, я решил обратиться в Интернет, чтобы узнать: «А как на мой вопрос отвечали другие?». Не скажу, что эта фраза мне попалась первой, но зацепился я за нее сразу: «Для ReGet дизайн придумывала студия Артемия Лебедева. В результате пользоваться ReGet, в отличие от FlashGet очень удобно. Можете в этом сами убедиться» [1]. При этом, я не думаю, что функционально обе программы сильно разнятся, выполняемые ими задачи практически одни и те же, но разница в том, что одну программу мы используем, а другую просто имеем ввиду, зная что она есть.
Самый веский аргумент, окончательно подтолкнувший меня на создании серии статей по заданной теме, я нашел в источнике [1]: «в России слишком много программистов-самоучек, которые все этапы создания программы от идеи программы до ее реализации выполняют сами». К сожалению, не у всех есть возможность нанять профессиональных дизайнеров или найти специалиста в этой области, поэтому приходится «изобретать велосипед» самому.
Начнем. С чего? Элементарно! What song? Книги!
Я нашел очень много информации по теме и около нее: статьи, примеры, книги, журналы. Среди множества источников выделил три книги. Не буду утверждать, что они являют собой ту самую истину, которая незыблема и нет других источников информации, но прочесть бы их я посоветовал:
ее стоит прочесть хотя бы для того, чтобы понять основные принципы «юзабилити» и того, как не стоит делать интерфейс. Кто-то скажет, – но она же только для тех, кто создает веб-сайты, Отвечу, – а кто сказал, что создание интерфейса программы сильно отличается от создания интерфейса веб-сайтов? Я бы сказал иначе, создание веб-сайтов выросло из принципов создания программ, именно поэтому внешний вид может быть разным, но подходы, принципы, правила одни и те же. Но, как ни странно, думать надо в любом случае и при создании сайта, и при создании программы. Хорошо думать, когда есть знания. Замечательно думать, когда знания перешли в умения. Надеюсь, уважаемый читатель, ты меня понял.
2. Джеф Раскин. Интерфейс: новые направления в проектировании компьютерных систем
считаю весьма полезными для разработчиков, желающих стать профессионалами. Я бы не сказал, что по году создания и издания книга нова. В найденной мною версии она датируется 1996 годом, но только что это меняет? В книге весьма интересно разложены по полочкам элементы интерфейса их плюсы и минусы, и порой высказывается совершенно иной взгляд на привычные, казалось бы, вещи: отказ от GUI, отказ от использования мыши, отказ от разбиения задач по приложениям. В определенном смысле программы интернет-браузеры реализуют эту идею, когда в одном окне выполняется все – звук, графика, редактирование, просмотр видео и прочие действия.
3. Иоханнес Иттен. Искусство цвета
книга тоже не новая, но привожу я ее из тех соображений, что дизайнеру, просто глупо ничего не знать о свете и цвете и не уметь применять эти знания на практике. Да и просто это повод открыть интернет и поискать любую литературу на тему рисования, цвета, способов изображать предметы. Скажу вам – очень интересная тема. Исследуйте на досуге, а я как-нибудь позднее чего-нибудь вам об этом расскажу. Искусство художника оказывается полезным для дизайнера – это основа его творчества.
4. В.В. Головач. Дизайн пользовательского интерфейса
Скажу сразу, она попалась мне на глаза гораздо позже других книг и понравилась намного больше тем, что в ней нет строгой теории, а сразу идет разбор конкретных ситуаций – ошибок и решений. Как ни странно, на фоне прочтения первых трех книг, эта – четвертая книга как будто подвела итоги решений, описанных теоретически в «умных» книгах.
Мало того, изложение материала таково, что я бросил чтение других книг и продолжил чтение только этой книги. При этом, на основании изложенных примеров, я реализовал несколько удобных «фишек» для своих программ на будущее, и они мне понравились. Советую прочесть эту книгу, просто потому, что это полезно и интересно.
Есть более новая версия этой книги – «Дизайн пользовательского интерфейса 2. Искусство мыть слона».
Начав читать, и, почти дочитав эти книги, я понял, что дизайн это бесконечный процесс слияния знаний, фантазии и ресурсов, которыми обладает дизайнер, в котором многое зависит от личности и ее таланта. Задумавшись, решил, что точнее назвать этого человека дизайнера – создатель: во-первых – это по-русски, а во-вторых – более отражает процесс дизайна (создавать нечто удобное, новое и оригинальное).
Что наша жизнь? И…
Классический ответ на заданный вопрос – «игра». В каком-то смысле, если задуматься, так и есть – вся наша жизнь есть одна сплошная игра. И в любой игре есть маски, костюмы, актеры, зрители. Я нашел этой игре новое обличие:
. зрители – это пользователи, потребители созданного вами продукта – программы, фильма, музыки, книги и тому подобного
. маски и костюмы – это тот самый интерфейс, в который мы облекаем наш продукт и то, что видит в первую очередь зритель. Это только потом он начинает разбираться в сюжете (логике), в таланте актера (профессионализме разработчика), имя которого завтра будет трудно вспомнить, если он оказался плох и т.д.
. актеры – это разработчики, по сути – мы с вами, те, кто хоть однажды пытался что-то проектировать, создавать, строить и прочее. От того, насколько мы талантливые актеры будет зависеть успех всего спектакля, аншлаг, признание публики, слава, деньги и прочее.
Разрабатывая программу, мы играем роль самого Создателя. Может быть, именно поэтому большинству так нравится играть, многим – нравится программировать, а некоторым из числа избранных – создавать и творить. Все это теоретически хорошо, но возникает вопрос, а какой ты создатель? И для кого ты создаешь? Мучаешься, не спишь ночами, читаешь гору разной литературы, бьешься над парой строк кода и все ради чего? Чтобы однажды узнать – твой труд никому не нужен, потому что ты не смог найти удачный способ взаимодействия пользователя с твоим творением. Не смог донести до него свою мысль и идею – ответ на главный вопрос: «…зачем ему нужно то, что ты создал?». Тебе-бы встретиться с ним, поговорить по душам за рюмкой чаю, но уже поздно – время упущено и пользователь ушел к другому, так и не поняв, что же ты хотел для него сделать. К сожалению, в жизни часто так бывает, что разработчик и пользователь встречаются друг с другом тет-а-тет весьма и весьма не часто. Особенно последняя фраза касается начинающих разработчиков – опытные-то знают, что пользователя надо завлечь пряничком, блестящей оберткой, усадить на мягкий стульчик, подать вкусный чай… Часто начинающие разработчики не то чтобы забывают о пользователе, они порой плохо представляют, а кто это вообще такой.
Пройдемся по науке
Собственно, что я хотел сказать? Для начала надо немного определиться и ответить на вопрос главный вопрос статьи: «Что такое интерфейс***?»
** Интерфейс (от англ. interface — поверхность раздела, перегородка) — совокупность средств
и методов взаимодействия между элементами системы [4].
Ответ обобщенный, подходит для разных сторон и сфер человеческой деятельности, но в своей сути он отражает смысл этого явления. Далее, подумав немного, решил, что мир придуман не вчера и все процессы должны быть так или иначе давно регламентированы и описаны. Я начал искать стандарты, правила, ГОСТ-ы. Приводить здесь подробное описание этих документов абсолютно бессмысленно. Каждый сам может найти их в сети Интернет. Будет гораздо лучше, если выскажу свои соображения, которые сделал, переработав найденную информацию…
Большинство ГОСТ-ов, найденных мною, направлены на разработку технической документации, связанной с процессом разработки программного обеспечения. Создается впечатление, что изначально в 70-х начале 80-х годов прошлого столетия упор делался на техническую сторону этого вопроса – разработку и детализацию алгоритмов, средств сопряжения, подбор технической базы, создание различных инструкций по эксплуатации и прочее. Старый ГОСТ именно это и регламентировал. Впрочем, если подумать, так оно и должно было быть, так как программирование по сути родилось из математики и на первом месте было решение задач, а не внешнее оформление. Лишь в ГОСТ, относящимся к недавним советским временам, а именно, ГОСТ 19.201-78 и ГОСТ 24.207-80 можно неявно увидеть фразы, частично указывающие на средства взаимодействия с пользователем: «требования к программе или программному изделию», «требования к маркировке и упаковке». Правда, прочтя эти фразы, явно и не скажешь, что тут имеется ввиду «интерфейс». Тем не менее, в источнике [2] нашел следующее: «Техническое задание, как правило, разрабатывается на основе ГОСТа 19.201-78 «ЕСПД.
Техническое задание. Требования к содержанию и оформлению». Таким образом, получается, что разработчик должен сам знать и подразумевать, что в задание должны закладываться вопросы, связанные с интерфейсом. Явно это в ГОСТ не звучит. Но это было «тогда». По ГОСТ советских времен подразумевалось, что интерфейс у нас возникает сам собой, – это следует из текстов документов. Получалось, как в известной фразе: «В СССР секса нет, а дети есть». Всем известна фраза о том, что в мире все подвержено изменениям. Тоже самое можно утверждать и про ГОСТ-ы. Не прошло и 20-ти лет, изменились требования времени, реалии, изменилось само время. Согласно документам, датируемым 2000-м годом и выше, разработчики ГОСТ уже узнали про интерфейс и даже явно написали об этом в «Пример шаблона технического задания (ТЗ) на сайт» [3], где есть два раздела: «Требования к графическому дизайну сайта», и «Требования к дизайну сайта». Это уже радует. Конечно же, кажется совершенно очевидным, что сайт без дизайна не сайт. Однако, судя по всему, на осознание этого факта разработчикам ГОСТ потребовалось время. Думаю, что оно им еще будет нужно, чтобы создать отдельный ГОСТ, касающийся только дизайна, как такового.
В итоге, проглядев различные ГОСТ, документы, шаблоны и примеры, сделал основной вывод. Сейчас, как и раньше, основной упор идет на правильное, точное, детальное оформление документации по всем этапам разработки продукта – замысел, поиск информации для начала разработки, процесс разработки, тестирование, внедрение, эксплуатация. С одной стороны – это правильно, сложные продукты делает много людей и для удобства их работы и взаимодействия нужны документы, описывающие детально и правильно различные этапы процесса создания конечного продукта. А с другой стороны – это жуткая бюрократическая формальность, требующая от каждого участника процесса описывать каждое свое действие и решение. Именно поэтому создание документации так не любят разработчики. Порой время, требуемое на ее создание соизмеримо со временем создания самого программного продукта. Но, опять же, мы вернулись к тому, от чего пришли – в настоящее время по ГОСТ дизайн и интерфейс упирается в «бумагу».
Если внимательно подумать, то это правильно, заказчику «нечто» не покажешь, а нарисованное и написанное на бумаге вполне возможно. Поэтому, насколько мне представляется, знание ГОСТ и этапов от создания технического задания до сопровождения готового продукта необходимо не только крупным фирмам, но и одиночным разработчикам, так как это позволяет делать все правильно и приучает к определенному порядку. Конечно же, для написания программы, из разряда «калькулятор» вряд-ли нужно техническое задание, но знание этого необходимо. Прошлись по науке? Хотя ГОСТ и прочие нормативные документы необходимо знать, но, по сути, это скучно, сухо и сложно. Пожалуй, хватит – идем дальше.
Что вы делаете после того, как решили написать собственную программу?
Предполагаю, что 95% респондентов ответят – обдумываю идею программы, способы реализации, типы данных, выбор среды программирования и прочие детали и … будут почти правы. А почему – почти? А потому «почти», что мало-кто сразу из большинства разработчиков начинает думать над тем: а как будет выглядеть ваше будущее творение перед лицом пользователя. Удобно—ли пользователю будет работать с программой***. Согласен, что на первом этапе весьма сложно представить цельный интерфейс программы, так как и программы, собственно говоря, еще и нет, но задуматься над этим стоит уже с самого начала.
*** Комментарий автора.
Скажу, что два года назад, когда я стал активно заниматься программированием, а не просто сопровождением программ и написанием мелких макросов, я больше корпел над алгоритмами и достижением результата, – программа должна делать то, что хочет от нее пользователь. Интерфейс возникал или по ходу написания, или так, как было удобно мне, а не пользователю. После запуска продукта в эксплуатацию как минимум неделя была посвящена только тому, что я отвечал на вопросы что, где, почему и зачем. Теперь же я стараюсь думать не только над «внутренностями», но и над «внешним видом».
А как вы пишете программу?
Думаю, что большинство ответят примерно так: «Сажусь за компьютер, открываю среду программирования и начинаю писать код». Если это визуальная среда программирования, то обычно 100% действий начинается с того, что на пустую форму перетаскивается мышкой какой-либо элемент из палитры компонентов и… вот тут начинается самое интересное, вы ступаете на дорогу «войны». Я не ошибся, именно дорогу войны, даже точнее будет сказать – тропу. Почему? Все очень просто – весь процесс разработки есть борьба с самим собой, с кодом, ошибками и прочими неприятностями. В любой программе во время ее написания никогда с первого раза не бывает правильно размещенного элемента в нужном месте формы, соседние элементы иногда начинают мешать друг другу или просто не помещаются на форме так, как этого хочется. В итоге вы все время воюете – с алгоритмом, со средой разработки с внешним видом. Причем чаще всего страдает от всей этой «битвы» интерфейс. Да и кто серьезно задумывается**** над тем, насколько удобно пользователю будет работать с программой, когда на первое место выходят задачи логики функционирования программного продукта?
**** Комментарий автора.
Пример из моей практики. В связи с производственной необходимостью потребовалось решить проблему автоматизации учета. Проблема была в том, что «низы» уже не могли вести расчеты «вручную» в связи с их сложностью, объемом и цикличностью, а «верхи» не знали быстрого решения проблемы, то есть подходящего программного решения по цене и решаемым задачам не было. В итоге, по стечению различных обстоятельств, наш системный администратор взялся за разработку программы «с нуля». То, что для него это было тяжело, это мягко сказано, это было очень тяжело. Ему приходилось решать проблемы абсолютно разного рода – выполнять свою непосредственную работу, параллельно изучать новые методы и технологии программирования, изучать предметную область задачи, решать дела домашние, между этим делать еще что-то. Мало того, периодически он «воевал» с непосредственным начальством по поводу совмещения прямых рабочих обязанностей и работы по написанию программы (программу он писал добровольно и, в том числе, на своем рабочем месте, а какому начальству понравится такое?). Смысл всей этой предыстории таков, что ему было не до интерфейса и дизайна программы. Для него было важным решить технические проблемы стоявшей перед ним задачи. В итоге задачу он решил для своего уровня и того времени достойно. Однако, в процессе эксплуатации выяснилось, что где-то он не додумал логику, где-то проиграл в удобстве интерфейса. При этом каждый день он решал какие-либо проблемы, связанные с внедренной программой – дописывал, исправлял, модернизировал, консультировал пользователей, писал документацию. Добавление новых решений и отчетов в программу, привело к тому, что с каждым днем она становилась все функциональнее и сложнее. В итоге, несмотря на то, что он видел и знал огрехи интерфейса, переделать или исправить что-то было уже практически невозможно, так как это означало переписывание программного кода практически сначала.
Вывод, напрашивающийся из всей этой ситуации таков – в условиях нехватки времени (а в обычных «рабочих» условиях так и есть) одному человеку практически невозможно создать удобную во всех отношениях программу. Все усилия в этом случае направлены на то, чтобы найти и реализовать логическое решение, внедрить и запустить в работу программу. Понимание того, как все должно быть, как удобнее работать, приходит уже после того, когда программа запущена в работу и эксплуатируется. И, часто получается так, что реализация «удобства интерфейса» уходит на второй план, так как возникают более важные задачи, – исправление допущенных ошибок в логике, модернизация и прочее. Именно поэтому большинство серьезных фирм очень много времени тратят на подготовку процесса, создание «стартовой базы», и лишь потом начинают программировать. В экстремальных условиях интерфейс страдает всегда.
Когда вы задумываетесь о том, кто и как будет работать с вашей программой и какие ситуации могут при этом возникнуть?
А вот на эти вопросы я не могу дать однозначного для всех ответа. У каждого найдется свой ответ, но, в конечном итоге, правильный ответ на эти вопросы всегда звучат из уст пользователя. Почему из уст пользователя? Отвечу цитатой рецензента этой статьи, литературного редактора этого журнала, Utkin: «…даже в идеальной программе пользователи найдут что покритиковать. Просто потому что пользователи всегда придирчивы. Одним подавай одно, другим требуется прямо противоположное». Поспорить с этим сложно. Еще классик И.А. Крылов написал басню про Слона, который рисовал картину в угоду всем и в итоге никому его шедевр не понравился. В данном случае – тот же самый процесс.
Мало того, этот самый «пользователь» всегда найдет ту самую ошибку, которую никто из разработчиков даже в страшном сне не мог увидеть. При этом, сложно сказать, какая ошибка хуже – алгоритмическая или визуальная, обе одинаково неприятны. Разница лишь в том, что логическую ошибку среднестатистический пользователь не всегда можно найти, особенно, если плохо знает логику функционирования программы, – такую ошибку не всегда видно. С точки зрения пользователя, логические ошибки могут быть вообще никогда не обнаружены. По известной статистике большинство пользователей используют лишь 5-10% возможностей программы, про остальные 90-95% возможностей, где и может оказаться логическая ошибка, они могут не знать. Визуальная ошибка всегда хуже – она просто заметнее. Классический пример из недавнего прошлого – это ошибка вывода изображения видеокартой. Чаще всего такие ошибки выявлялись в играх, как более требовательным к ресурсам компьютера, а не «офисных» приложениях, которым хватало «гарантированного минимума». Они проявлялись в том, что могли «ломаться» контуры изображаемых предметов, возникали непредвиденные визуальные эффекты, искажения картинки в целом, в худшем варианте или просто ничего не было видно, или компьютер шел на перезагрузку. При этом, источник ошибки мог быть с любом месте – как в сбое видеокарты, так в используемом программном обеспечении (драйверах видеокарты, драйверах DirectX или OpenGL, несовместимости с операционной системой и прочее).
Для крупных корпораций уровня Microsoft или Adobe, когда есть рынок, бренд, сформированный круг пользователей, которые все равно не уйдут, такие ошибки менее ощутимы. Да, они неприятны, никто не говорит, что ошибки – это хорошо, но все-таки, менее ощутимы. Для таких корпораций они всего-лишь повод создания обновлений и выпуска новых версий программ. При этом, вовсе на факт, что старые версии работали хуже или не удовлетворяли потребностям пользователя. На мой взгляд, рассматривая, как пример, программу Adobe Photoshop, для большинства пользователей (не дизайнеров) вообще достаточно ее варианта в версии 9.0. Новые возможности программы, выпуск линейки продуктов от Adobe в виде нескольких DVD дисков, еще раз повторю, обычным пользователям, вообще не понятны и не нужны, – они просто не пользуются ими в полной мере. Хотя, как бренд и признак «статуса», большинство просто устанавливают эти продукты на свой компьютер, не зная и 5% всех возможностей. Грубо говоря, они микроскопом забивают гвозди, изменяя размеры фотографий или сохраняя их в другой формат.
Возвращаясь к теме разговора, еще раз скажу, что ошибки для крупных корпораций менее болезненны, чем для разработчиков-одиночек. И вот почему. Образно говоря, обслуживание ошибок у них поставлено на конвейер – службы поддержки, бесплатная горячая телефонная линия, консультации он-лайн и через различные сервисы в сети. В данном случае под «ошибками» я подразумеваю не только непосредственно ошибки в программе, найденные пользователями, но и «ошибки в мозгах пользователей», связанные с обычной человеческой ленью и нежеланием разобраться и думать. С одной стороны – такая ситуация везде и всюду и считается обычной, а с другой – это повод, способ, средство знать еще сильнее «привязывать» пользователей к себе. Если бы большинство из нас внимательно читали бы документацию и перед тем, как задать вопрос, подумали над его решением, то половина вопросов исчезла, а службам поддержки нечего было бы делать.
Если вы «один из подающих надежды», тот самый герой, призванный удивить мир, то у вас просто нет права на ошибку. Вы должны выстелить точно в цель, чтобы громко и красиво заявить о себе. В противном случае велика вероятность того, что пользователи вас не поймут и забудут навсегда ваш адрес и ваш продукт и, развернувшись, уйдут к другим. Исключение в этой ситуации, составляет всеми горячо любимый Билл Гейтс, который, несмотря на то, что первые версии его операционный системы Windows содержали много ошибок и пользователями по всему миру изначально вообще не воспринимались, смог продать свою систему этому миру. Возможно, одна из причин его успеха в том, что первыми пользователями его системы были студенты, ставившие над ней эксперименты. А так как чаще всего то, что изучается в университете, дальше используется в повседневной работе, то Windows и получила такое распространение. Впрочем, умалять заслуг Билл Гейтса, как удачного менеджера и торговца не стоит. Думаю что, еще одна хитрость, принесшая успех Windows состоит в том, что долгое время вообще никто даже и не знал, что надо покупать лицензии на эту систему. Она эксплуатировалась везде и всюду просто так, благодаря умным ребятам, называющих себя хакерами. В свое время ходила шутка о том, что самая лицензионная часть операционной системы – драйвер от мыши.
Другая исключительная ситуация, может быть только одна – ваша программа настолько уникальна и нужна пользователю, что он вынужден терпеть и ждать, и прощать вам ваши ошибки. Правда, такие исключения бывают редко и чаще всего встречаются в сфере специфических видов деятельности человека. Например, программа расчета поведения группы микроорганизмов под влиянием факторов внешней среды, или программа учета параметров работы газотурбинного двигателя. Рядовому пользователю такие программы просто не нужны, подозреваю, что он даже не догадывается о существовании таких программ.
Если кратко подводить итог***** всему сказанному в этих абзацах, что я бы сказал так. Если вы, как разработчик задумались над удобством использования вашего продукта не на стадии разработки, а гораздо позднее, то можно с уверенностью утверждать, что чем дальше вы от точки старта, тем больше затрат и усилий придется приложить, чтобы внести одно «элементарное» исправление. Это касается как общей логики функционирования, так и интерфейса в целом. Копеечная ошибка на старте всегда выливается миллионные затраты на ее исправление на финише.
***** Комментарий автора.
Часто в процессе создания возникает иллюзия «понятности», – это состояние, в котором разработчик настолько проникается идеей продукта и его тонкостями, что ему начинает казаться, что и другим также все очевидно и понятно в функционале создаваемого продукта, как и ему самому. На деле же все выходит наоборот, – даже знающего и опытного пользователя всегда требуется обучать и отвечать на такие вопросы, которые с точки зрения разработчика находятся в ряду «элементарных».
Необходимо как можно раньше начинать глядеть на ваше творение со стороны пользователя и делать это чаще и не просто глядеть (любоваться), а пытаться использовать все то, что вы создали, именно как пользователь. Забыть все, что известно о «внутреннем содержимом» продукта и стать неопытным пользователем, задающим извечные детские вопросы: «Как?» и «Почему?». Поверьте мне, это правило очень и очень часто помогает увидеть такие интересные вещи.
Элементы и проблемы… все мы родом из детства
Насколько я помню, начиная со школьных уроков информатики и продолжая на специализированных курсах университета, везде учат практически одинаково. Ученику рассказывают про алгоритмы, основы написания программ, грамматике языков программирования. Задавая типовые задачи, пытаются выработать логическое мышление, умение применять операторы и структуры изученного языка. Это все полезно и нужно, так как на самом деле заставляет думать и приводит к приобретению навыков логического мышления.
Я могу ошибаться, утверждая следующее, но на мой взгляд, практически нигде нет ни слова о том, как сделать так, чтобы с программой, в общем смысле – продуктом, было удобно работать. Учат только языку, логике и умению применить знания на практике. А о том, чтобы умения, воплощенные в продукте, было еще и удобно использовать на практике, если и говорится, то уж очень мало, настолько мало, что об этом не остается даже воспоминания.
Говорить, что нас ничему не учили, тоже нельзя. Если чуть-чуть подумать, то можно немного провести аналогии, хотя это будет слишком размыто и не очень конкретно. Уроки рисования в школе, когда каждый как умел, так и рисовал, теоретически можно взять в качестве элементарной базы графического дизайна. Тоже можно сказать о черчении и геометрии, из них можно почерпнуть понятия о проекциях, симметрии, способах изображения объектов, пропорциях. Можно еще упомянуть историю, касаемо истории искусств, обычаев, культуры – оттуда можно взять некоторые элементы для декора, дизайна, оформления. Но, мне кажется, это все-таки сложно и «притянуто за уши». Мало того, требует определенных усилий и особого мышления, чтобы все это собрать воедино. Пожалуй, из школьной программы – это и все, что можно взять в багаж, если не учитывать книги и специальные курсы, где непосредственно учат дизайну и оформительскому искусству, я их не рассматриваю, так как они идут факультативно и не входят в основную программу обучения, то есть массово не изучаются.
Если идти обучаться далее в университет (не могу со стопроцентной вероятностью утверждать, что в настоящее время ситуация не изменилась), то до недавнего времени в большинстве высших технических учебных заведений не было специально выделенной дисциплины, так или иначе связанной с интерфейсом. Студентам преподавались эргономика, трехмерная графика, черчение, инженерное моделирование, но увязать их с интерфейсом, опять же, можно лишь косвенно. Выделенной специализированной дисциплины, технических ВУЗах до недавнего времени не было. Я не беру во внимание обучение специальности дизайнер, так как считаю, что её изучает отдельно взятая группа людей и, распространяемые знания, не идут в широкие массы в отличие, например, от математики, физики, химии, изучаемых всеми в обязательном порядке на первых курсах университета.
Таким образом, молодой инженер, выпускник высшего учебного заведения с техническим уклоном, может оказаться хорошим специалистом, весьма подкованным логически и технически, но имеющим слабые знания в части дизайна, интерфейса и способов взаимодействия с пользователями. В результате, придя на рабочее место, молодому специалисту приходится восполнять этот пробел в знаниях самому и, порой, «изобретать велосипед» там, где он давно уже придуман. Иначе говоря, технические ВУЗы выпускают хороших специалистов, обладающих знаниями по своей специальности, но в разной степени хорошо умеющих эти знания красиво и удобно представить в конечном продукте. Именно по этой причине, как одной из основных, имеют такую популярность различные дизайнерские фирмы. Конечно же тому есть и другие причины – не все умеют созидающе мыслить, красиво рисовать, придумывать, но научить делать это можно всех. С одной стороны удобно поручить создание интерфейса и дизайна знающим людям, а с другой стороны подобное происходит потому, что большинство просто не знает и не умеет это делать правильно. Итак, завершаю философствовать и перехожу к описанию отдельных элементов касающихся интерфейса и не только его.
Продолжение следует…
Ресурсы
. Размышления об интерфейсе http://tclstudy.narod.ru/articles/mytk.html
. Культура разработки программного обеспечения http://www.orientir-yug.ru/kult_po.htm
. Техническое задание на разработку интернет-сайта http://www.rugost.com/index.php?option=com_content&task=view&id=182&Itemid=85
. Википедия. Интерфейс http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81
. Джеф Раскин. Интерфейс: новые направления в проектировании компьютерных систем
http://www.kodges.ru/9701-interfejjs-novye-napravlenija-v-proektirovanii.html
. С.Круг. Не заставляйте меня думать http://www.bookshunt.ru/b10909_veb_dizajn_kniga_stiva_kruga_ili_quotne_zastavlyajte_menya_dumatquot/download
. Об оформлении программной документации http://www.raai.org/about/persons/karpov/pages/ofdoc/ofdoc.html
. ГОСТ 19.102-77.Стадии разработки http://www.nist.ru/hr/doc/gost/19102-77.htm
. Студия Артемия Лебедева. Создание интерфейса навигатора «Штурман» http://www.artlebedev.ru/everything/shturmann/process
. Этот мерзкий, неудобный, противоестественный оконный интерфейс
http://epikoiros.narod.ru/public/antiwind.htm
. Обзор эргономических проблем и недостатков пользовательского интерфейса ПО бухгалтерского учёта на примере 1С:Предприятие 7.5 http://www.usability.ru/Articles/1.htm
. Ссылка на отдельное сообщение форума http://forums.drom.ru/1067823597-post12.html
Статья из пятого выпуска журнала ПРОграммист.
Скачать этот номер можно по ссылке.
Ознакомиться со всеми номерами журнала.
Обсудить на форуме — Разработчики – интерфейс – пользователи
19th
Введение в Scheme. Часть 2.
Здравствуйте, дорогие читатели. Как и обещал, сегодня мы продолжим рассмотрение наиболее распространенных команд языка Scheme и механизмов, облегчающих управление процессом выполнения, а также познакомимся ближе со средой разработки PLT Scheme.
Продолжение. Начало цикла смотрите в четвертом выпуске журнала…
Введение в Sсheme. Часть 2
Utkin www.programmersforum.ru
Нужно помнить, что данные предикаты нежелательно использовать на неточных числах – ошибки округления могут приводить к обратным результатам. Кстати, определить является ли число точным или не точным можно определить с помощью предикатов:
(exact? z) Тест на точность
(inexact? z) Тест на неточность
Для одного и того же числа один из этих предикатов всегда результат #t, тогда как второй #f. Для сравнения чисел можно использовать следующие предикаты, думаю назначение их понятно и так:
(= х1 х2 х3 …)
(< x1 x2 x3 …)
(> x1 x2 x3 …)
(<= x1 x2 x3 …)
(>= x1 x2 x3 …)
(= 1 1 1) #t
(= 1 2 1) #f
Аналогично, предикатам типов числа, не стоит применять сравнения на неточных числах, поскольку ошибки округления могут дать противоположный результат для почти равных чисел.
Еще предикаты для работы с числами:
(zero? z) Проверка на нуль
(positive? x) Проверка является ли число положительным
(negative? x) Проверка является ли число отрицательным
(odd? n) Проверка является ли число не четным
(even? n) Проверка является ли число четным
Поиск минимального и максимального чисел:
(max x1 x2 …)
(min x1 x2 …)
Примеры:
(max 3 4) Результат 4
(max 3.9 4 9 48 99 5) Результат 99.0 При этом число будет преобразовано в неточное.
(min 54 565 9L0) Результат 9.0
(min 4 4) Результат 4
Нужно соблюдать осторожность при сравнении почти равных неточных чисел, поскольку правильный результат работы данных предикатов не гарантирован. Теперь напомним стандартные арифметические операции:
(+ z1 …) Сложение
(* z1 …) Умножение
(- z1 z2) Вычитание
(- z) Унарный минус
(- z1 z2 …) Вычитание (с произвольным числом аргументов)
(/ z1 z2) Деление (деление на нуль не допускается)
(/ z) Деление 1 / z, при этом образуется дробь
(/ z1 z2 …) Деление z1 на произвольное число аргументов
Теперь примеры (поскольку некоторые результаты не очевидны):
(+ 3 4) Результат 7
(+ 3) Результат 3
(+) Результат 0
(* 4) Результат 4
(*) Результат 1
(- 3 4) Результат -1
(- 3 4 5) Результат -6
(- 3) Результат -3
(/ 3 4 5) Результат 3/20 (3 разделить на 4*5)
(/ 3) Результат 1/3
Кстати, дроби являются точными числами, поэтому их удобно использовать в предикатах для работы с числами (гарантируются однозначные результаты сравнений, отношений и т.д.). Дополнительные операции над числами:
(abs x) Абсолютное значение числа
Дополнительные операции деления:
(quotient n1 n2)
(remainder n1 n2)
(modulo n1 n2)
При этом n2 не должен быть равен нулю (независимо от точности числа). Если n1 / n2 есть целое:
(quotient n1 n2) Результат n1/n2
(remainder n1 n2) Результат 0
(modulo n1 n2) Результат 0
Если в результате n1 / n2 образуется не целое число:
(quotient n1 n2) Результат nq
(remainder n1 n2) Результат nr
(modulo n1 n2) Результат nm
где число nq – n1/n2, округленное к нулю, 0 <| nr | <| n2 |, 0 <| nm | <| n2 |, nr и nm отличаются от n1 множителем n2, nr получит знак n1, nm получит знак n2.
Особенностью этих функций (по сути, вариации на тему нахождение остатка от деления) является факт, того, что они возвращают точные числа, в случае если их входящие параметры также являются точными.
(modulo 13 4) Результат 1
(remainder 13 4) Результат 1
(modulo -13 4) Результат 3
(remainder -13 4) Результат -1
(modulo 13 -4) Результат -3
(remainder 13 -4) Результат 1
(modulo -13 -4) Результат -1
(remainder -13 -4) Результат -1
(remainder -13 -4.0) Результат -1.0 Обратите внимание, результат не точное число.
Следующие функции возвращают наибольший общий делитель или наименьший общий множитель их параметров. Результат является всегда неотрицательным.
(gcd 32 -36) Результат НОД (наибольший общий делитель) 4
(gcd) Результат 0
(lcm 32 -36) Результат НОМ (наименьший общий множитель) 288
(lcm 32.0 -36) Аналогично Результат 288.0, но теперь результат будет неточным.
(lcm) Результат 1
Следующие ниже функции возвращают числитель, и знаменатель дроби (знаменатель всегда положительное число):
(numerator q)
(denominator q)
Примеры:
(numerator (/ 6 4)) Результат 3
(denominator (/ 6 4)) Результат 2
(denominator
(exact->inexact (/ 6 4))) Результат 2.0, для получения неточного числа используется явное преобразование. Естественно удобно и для дробей:
(numerator 6/4) Результат 3 (рассматривается дробь 3/2, и только потом берется знаменатель)
Следующая группа функций:
(floor x)
(ceiling x)
(truncate x)
(round x)
всегда возвращает целые числа. Floor возвращает наибольшее целое число не большее чем х. Ceiling возвращает наименьшее целое число не меньше чем х. Truncate возвращает целое число, которое наиболее ближе к х, и абсолютная величина которого не больше абсолютной величины х. Round возвращает целое число путем округления х (половина икса округляется в большую сторону).
(floor -4.3) Результат -5.0 (числа целые, но не точные)
(ceiling -4.3) Результат -4.0
(truncate -4.3) Результат -4.0
(round -4.3) Результат -4.0
(floor 3.5) Результат 3.0
(ceiling 3.5) Результат 4.0
(truncate 3.5) Результат 3.0
(round 3.5) Результат 4.0 — не точное число
(round 7/2) Результат 4 — точное число
(round 7) Результат 7
(rationalize x y) – возвращает самое простое рациональное число, отличающееся от x не больше, чем y.
Рациональное число x более простое чем другое рациональное число y если x = p1/q1 и y = p2/q2 и и | p1 | < | p2 | и | q1 | <| q2 |. Таким образом, 3/5 более простое число чем 4/7. Хотя не все рациональные числа сопоставимы в этом упорядочении (например, 2/7 и 3/5), любой числовой интервал содержит рациональное число, которое более просто, чем любое рациональное число в том же интервале. Известно также, что 0 = 0/1 – самые простые рациональные числа из всех.
(rationalize
(inexact->exact .3) 1/10) Результат 1/3, точное число
(rationalize .3 1/10) Результат 0.3333333333333333
Трансцендентальные функции:
(exp z)
(log z)
(sin z)
(cos z)
(tan z)
(asin z)
(acos z)
(atan z)
(atan y x)
Здесь все просто, стоит отметить log – имеется ввиду натуральный (а не десятичный), atan с двумя параметрами использует знаки x, y для определения квадранта, к которому принадлежит результат.
(sqrt z) – вычисляет квадратный корень, включая мнимую часть числа:
(sqrt -1) Результат 0+1i (всегда мечтал в Паскале получить корень из -1)
(expt z1 z2) – возведение в степень, довольно-таки мощная функция, единственное ограничение – в степень запрещено возводить нуль.
(expt 2.1 3.3) Результат 11.569741950241465
(expt 2.1 -3.3) Результат 0.08643235124004903
Следующие функции предназначены для поддержки комплексных чисел:
(make-rectangular x1 x2)
(make-polar x3 x4)
(real-part z)
(imag-part z)
(magnitude z)
(angle z)
Здесь x1-x4 вещественные числа, z комплексное.
(make—rectangular x1 x2) Результат комплексное число
(make—polar x3 x4) Результат комплексное число
(real—part z) Результат реальную часть числа (x1)
(imag—part z) Результат мнимую часть числа (x2)
(magnitude z) Результат |x3|
(angle z) Результат xangle
Точные и неточные числа можно преобразовывать следующим образом:
(exact->inexact z)
(inexact->exact z)
Первая функция переводит точное число в неточное, вторая выполняет обратные действия. Естественно, такое преобразование возможно не всегда (такая ситуация считается ошибочной). Теперь рассмотрим ввод и вывод чисел. Числа можно получать из строки следующим образом:
(string->number string)
(string->number string radix)
Здесь radix есть основание системы счисления (точное целое число 2, 8, 10 или 16). Для первого варианта имеется ввиду основание системы счисления равным 10. Если число z является неточным и может быть выраженым с использованием точки в качестве разделителя целой и дробной частями, то число будет представлено с минимально возможным числом разрядов.
(string->number ”100″) Результат 100
(string->number ”100″ 16) Результат 256
(string->number ”1e2″) Результат 100.0
(string->number ”15##”) Результат 1500.0
В случае, если строку в число преобразовать не удастся, результат функции #f.
Пары и списки
Парой (иногда называется точечной парой) называется структура данных, представляющая собой запись, состоящую из двух полей, первое из которых называется car, а вторая cdr (названия сложились исторически). Пара создается функцией сons. Доступ к полям пары осуществляется одноименными функциями car и cdr. Присваивание значений полям пары осуществляется с помощью процедур set-car! и set-cdr!. Основное назначение пар это образование и представление списков. Список может быть определен рекурсивно, как пустой список (список, не содержащий элементов) или как пара поле cdr которого является списком. Если Х является списком, то:
. в Х содержится пустой список
. если список находится в X, то любая пара, поле cdr которой содержит список, находится также в X.
Объекты в полях car последовательных пар списка считаются элементами списка. Например, двухэлементный список это пара, car которой первый элемент списка и чей cdr пара, car которой второй элемент списка и чей cdr есть пустой список. Длина списка – это число элементов (которые можно выразить как число пар).
Список |
Список состоит из пар |
||||
Пара1 |
Car |
1-й элемент списка |
|||
Cdr |
Пара2 |
Car |
2-й элемент списка |
||
Cdr |
Пустой список |
Список (a b c d e) можно выразить так (a . (b . (c . (d . (e . ()))))). То есть в списке пары расположены не последовательно друг за другом, а являются вложенными объектами. Пустой список – специальный объект своего собственного типа (это не пара); у него нет никаких элементов, и его длина равна нулю. При этом все списки имеют конечную длину (точное число) и заканчиваются пустым списком.
Для представления пар используется точечная нотация, поля разделяются точкой. Например, пара (4 . 5) имеет поле car 4 и поле cdr 5, при этом внутреннее представление пары будет иным. Списки выражаются проще (х1 х2 … хn), где х это элемент списка. Пустой список выражается, как (). Как уже было отмечено ранее, вся программа на языке Scheme является списком (как и любые ее логически законченные фрагменты), поэтому программы, и выражения можно обрабатывать также как и списки.
Существуют структуры, похожие на списки, которые не удовлетворяют данному выше определению, они называются неподходящие списки. Неподходящий список списком не является, вот его пример:
(a b c . d) что эквивалентно (a . (b . (c . d))), то есть неподходящие списки есть пары.
(define x (list ’a ’b ’c))
(define y x)
y Результат (a b c), list создает список
(list? y) Результат #t, предикат проверки списка
(set—cdr! x 4) Результат не определен (побочный эффект cdr х равен 4)
x Результат (a . 4)
(eqv? x y) Результат #t
y Результат (a . 4)
(list? y) Результат #f
(set—cdr! x x) Результат не определен
(list? x) Результат #f
Предикат (pair? obj) проверяет является ли объект парой.
(pair? ‘(a . b)) Результат #t
(pair? ‘(a b c)) Результат #t
(pair? ‘()) Результат #f
(pair? ’#(a b)) Результат #f
Следующая функция возвращает пару:
(cons obj1 obj2)
car пары будет представлять собой obj1, cdr соответственно obj2.
(cons ‘a ‘()) Результат (а)
(cons ‘(a) ‘(b c d)) Результат (c d)
(cons “a“ ‘(b c)) Результат (”a“ b c), обратите внимание на квотирование и кавычки
(cons ’a 3) Результат (a . 3)
(cons ’(a b) ’c) Результат ((a b) . c)
Квотирование в данном случае используется для того, чтобы поля пары не вычислялись в момент внесения в пару. Это позволяет вносить в пару как простые данные, вроде чисел, так и функции и выражения.
(car pair) – возвращает поле car пары (так и хочется сказать первое поле, но внутреннее представление пар может быть иным, поля пары могут находиться даже не в смежных областях памяти). Попытка получения car пустой пары вызовет ошибку.
(car ’(a b c)) Результат a
(car ’((a) b c d)) Результат (a)
(car ’(1 . 2)) Результат 1
(car ‘()) Результат ошибка вычислений
(cdr pair) – возвращает поле cdr пары. Получение cdr пустого списка вызовет ошибку.
(cdr ‘((a) b c d)) Результат (b c d)
(cdr ’(1 . 2)) Результат 2
(cdr ’()) Результат ошибка вычислений
(set—car! pair obj) и (set—cdr! pair obj) помещает соответственно в car и cdr пары pairs объект obj.
Результат их работы не определен, функции имеют побочные эффекты. Очень часто во время манипуляций со списками возникает много car и cdr. Такие выражения допускается сокращать:
(car (cdr (cdr x))) эквивалентно caddr, то есть справедливо следующее утверждение:
(define caddr (lambda (x) (car (cdr (cdr x)))))
Правило формирования функции следующее: все car представляются как а, а все cdr как d в наименовании функции, которая начинается с с и заканчивается r. При этом допускается формирование функций не более чем из четырех car и cdr.
(null? obj) – возвращает #t, если obj есть пустой список
(list? obj) – возвращает #t, если obj есть список.
(list? ‘(a b c)) Результат #t
(list? ’()) Результат #t
(list? ‘(a . b)) Результат #f
(let ((x (list ’a)))
(set-cdr! x x)
(list? x)) Результат #f
(list obj …) – создает список.
(list ’a (+ 3 4) ’c) Результат (a 7 c)
(list) Результат ()
(length list) – передает число элементов в списке
(length ’(a b c)) Результат 3
(length ’(a (b) (c d e))) Результат 3
(length ’()) Результат 0
(append list …) – объединение списков, при этом происходит перераспределение их внутренней структуры (таким образом, чтобы результат удовлетворял определению списка).
(append ‘(x) ‘(y)) Результат (x y)
(append ’(a) ’(b c d)) Результат (a b c d)
(append ’(a (b)) ’((c))) Результат (a (b) (c))
(append ’(a b) ’(c . d)) Результат (a b c . d)
(append ‘() ‘a) Результат a, список был изменен.
(reverse list) – возвращает список, перераспределенный в обратном порядке.
(reverse ’(a b c)) Результат (c b a)
(reverse ’(a (b c) d (e (f)))) Результат ((e (f)) d (b c) a)
(list-tail list k) – возвращает список на основе списка list, но без k первых элементов. Входящий список должен содержать не менее k элементов. Работу list-tail можно выразить функцией-эквивалентом:
(define list-tail
(lambda (x k)
(if (zero? k)
x
(list-tail (cdr x) (- k 1)))))
(list-ref list k) – возвращает k-й элемент списка. В списке должно быть не менее k элементов.
Нумерация элементов списка осуществляется от нуля. Плюсом пар и неподходящих списков является возможность создания древовидных структур данных с неограниченным числом узлов (пока хватит памяти компьютера).
Символы
Это специальные объекты, особенность которых заключается в том, что символы считаются эквивалентными (для предиката eqv?), если получены одинаковым путем. Символы в частности могут представлять идентификаторы программы, и их уникальность дает возможность использовать их во внутреннем представлении программы. Правила образования символов полностью соответствуют правилам образования идентификаторов. Не следует путать данные символы (Symbols) с символами строки (Characters). Это символы программы и не предназначены для представления строк (хотя и могут быть конвертированы в строки). В частности символы можно получить, квотировав идентификаторы.
Следующий предикат подтверждает, все то, что сказано выше:
(symbol? obj) – определяет является ли объект символом.
(symbol? ’foo) Результат #t
(symbol? (car ’(a b))) Результат #t
(symbol? “bar“) Результат #f, строки представляются строковыми символами!
(symbol? ‘nil) Результат #t
(symbol? ‘()) Результат #f
(symbol? #f) Результат #f
(symbol? 5) Результат #f
(symbol? ‘5) Результат #f, это не идентификатор и не выражение
Для преобразования символов в строки используется
(symbol->string symbol)
Примеры:
(symbol->string ’flying-fish) Результат “flying-fish”
(symbol->string ’Martin) Результат “martin”
(symbol->string
(string->symbol ”Malvina”)) Результат “Malvina”
Здесь (string->symbol “Malvina“) выполняет обратную функцию.
(string->symbol “Привет“)
Символы, в частности, предоставляют программисту возможность работать с объектами программы через операции над их идентификаторами.
Строковые символы
Строковой символ – минимальная единица представления текстовой информации. Строковые символы можно образовывать так #\<character> или #\<character name>. Вот примеры образования строковых символов:
#\a; буква в нижнем регистре
#\A; буква в верхнем регистре
#\(; открывающая скобка
#\ ; пробел
#\space; пробел (образование строкового символа по его имени)
#\newline; символ перехода на новую строку
Поскольку Scheme во многом система, не зависящая от конкретной платформы, то получать константы строковых символов по кодам в какой-либо кодировке не допускается. Поэтому нельзя получить строковой символ #\13, в тоже время PLT Scheme позволяет получать символы национальных алфавитов и задать строковый символ #\й вполне допустимо. Для определения факта того, что объект является строковым символом, используется следующая функция:
(char? obj) – возвращает #t, если объект является строковым символом.
(char? ‘try) Результат #f, поскольку язык проводит четкую границу между символами и строковыми символами.
Все строковые символы определяются на основе их порядка следования в алфавите. Поэтому между строковыми символами существуют отношения, связанными с их расположением относительно друг друга. Для оценки строковых символов используется ряд функций:
(char=? char1 char2)
(char<? char1 char2)
(char>? char1 char2)
(char<=? char1 char2)
(char>=? char1 char2)
Сначала следуют цифры, потом прописные буквы, потом строчные (национальные символы «больше» латиницы). Кстати, PLT Scheme версии 350 допускает более двух символов для сравнения (на манер числовых предикатов).
(char-ci=? char1 char2)
(char-ci<? char1 char2)
(char-ci>? char1 char2)
(char-ci<=? char1 char2)
(char-ci>=? char1 char2)
Тоже самое, но без учета регистра.
(char-ci=? #\A #\a)
Результат #t. Аналогично, функции с приставкой –ci в PLT Scheme могут содержать больше чем два аргумента.
(char-alphabetic? char) – возвращает #t, если строковой символ буква.
(char-numeric? char) – возвращает #t, если строковой символ цифра.
(char-whitespace? char) – возвращает #t, если строковой символ пробел.
(char-upper-case? letter) – возвращает #t, если строковой символ буква в верхнем регистре.
(char-lower-case? letter) – возвращает #t, если строковой символ буква в нижнем регистре.
Несмотря на то, что задавать константы строковых символов их кодами нельзя, получать коды из строковых символов разрешено: (char->integer char) – вернет точное целое число, которому сопоставлен данный строковой символ. Обратная ей функция (integer->char n). Изменить регистр символов можно с помощью функций:
(char—upcase char) – изменяет регистр строкового символа на верхний
(char—downcase char) – изменяет регистр строкового символа на нижний.
Строки
Строки это последовательности символов. В Scheme строки выделяются кавычками. В строки допускается включать Escape-последовательности через использование обратного слеша (\). Например, если известны коды символов, то строку можно задать следующим образом: “\u65\u65” (чего нельзя делать для строковых символов). Длина строки есть число содержащихся в ней символов (точное целое неотрицательное число). Индексация символов начинается от нуля. Аналогично операций с символами все функции имеющие приставку –ci есть операции со строками без учета регистра. Начнем с определения строки:
(string? obj) – возвращает #t, в случае, если объект является строкой.
Существует два способа напрямую создать строку с помощью функций:
(make-string k)
(make-string k char)
Здесь, k – есть длина создаваемой строки, char – символ, которым должна быть наполнена строка (в первой функции она будет наполнена символами вида ”\u0000\u0000\u0000”). Также строки можно создавать путем конкатенации (объединении) символов:
(string char …)
Длина строки:
(string-length string)
Можно также получить доступ к каждому элементу строки (строковому символу):
(string-ref string k)
(string-ref “Привет” 1) Результат #\р, так как нумерация в строке идет от нуля
Изменить конкретный символ в строке можно с помощью: (string—set! string k char). При этом следует помнить, что string—set! возвращает неопределенное значение. Строки можно сравнивать (на порядок расположения в них строковых символов):
(string=? string1 string2)
(string-ci=? string1 string2)
(string<? string1 string2)
(string>? string1 string2)
(string<=? string1 string2)
(string>=? string1 string2)
(string-ci<? string1 string2)
(string-ci>? string1 string2)
(string-ci<=? string1 string2)
(string-ci>=? string1 string2)
PLT Scheme разрешает использовать более двух аргументов при сравнении строк.
(string=? “12″ “15″ “gsjfds”) Результат #f
При этом более короткие строки считаются меньше длинных:
(string-ci<? “fff” “ffff”) Результат #t
Выделение подстроки:
(substring string start end)
При этом входящие параметры должны удовлетворять условию:
0 < start < end < (string-length string)
Объединение (конкатенация) строк:
(string—append string …)
(string—append “Привет ” “Мир!”) Результат “Привет Мир!”
Также важны функции преобразования строк:
(string->list string) – преобразование строки в список строковых символов
(list->string list) – преобразование списка в строку (список должен быть списком строковых символов)
(string->list string) и (list->string list) являются противоположными по отношению друг к другу.
(string-copy string) – возвращает копию строки
Векторы
Векторы в Scheme есть неоднородные структуры данных индексированные целыми числами. Одним из плюсов векторов является организация, построенная таким образом, что скорость доступа к ним выше, чем к спискам. Длина вектора есть число элементов, которые он содержит (целое точное неотрицательное число, также как и индекс любого из доступных элементов вектора). Индексация элементов вектора начинается от нуля. В общем, векторы сильно похожи на массивы императивных языков программирования, но имеют одну приятную особенность – вектор может содержать данные различных типов.
Для записи векторов используется следующая нотация: #(obj …).
#(0 (2 2 2 2) ”Anna”) Вектор, состоящий из трех элементов – числа нуль, списка (2 2 2 2) и строковой константы ”Anna”.
(vector? obj) – определяет, является ли объект вектором (#t если объект вектор).
(make—vector k) – создает вектор из k элементов, сами элементы не определены.
(make—vector k fill) – создает вектор из k элементов, элементы которого являются fill.
(vector obj …) – создает вектор из указанных объектов.
(vector ‘a ‘b ‘c) Результат #(a b c), сами элементы при этом не вычисляются (из-за одинарной кавычки).
(vector-length vector) – возвращает длину вектора (точное целое число).
(vector-ref vector k) – возвращает k-тый элемент вектора (k как и все индексы должен быть точным и целым).
(vector-ref ’#(1 1 2 3 5 8 13 21) 5) Результат 8 (нумерация от нуля).
(vector—set! vector k obj) – присваивает k-тому элементу вектора значение obj. Результат не определен, функция обладает побочными эффектами.
(vector->list vector) – создает список из вектора.
(list->vector list) – создает вектор из списка.
(vector->list ’#(dah dah didah)) Результат (dah dah didah)
(list->vector ’(dididit dah)) Результат #(dididit dah)
(vector-fill! vector fill) – заполняет указанный вектор объектами fill. Результат функции не определен, функция имеет побочные эффекты.
Особенности управления
Здесь мы опишем некоторые (не все, например, отложенные вычисления уже рассматривались) механизмы, облегчающие управление процессом выполнения.
(procedure? obj) – возвращает #t, в случае если перед нами процедура. Надо отметить, что в Scheme очень часто идет слияние понятий функция и процедура.
(procedure? car) Результат #t
(procedure? ’car) Результат #f
(procedure? (lambda (x) (* x x))) Результат #t
(procedure? ‘(lambda (x) (* x x))) Результат #f
(apply proc arg1 … args) – вызывает указанную функцию к аргументам заданным списком.
(apply + (list 3 4)) Результат 7, для функции + (плюс) задается параметр (только один), заданный в виде списка.
(map proc list1 list2 …) – применение функции proc к каждому из списков. Списки должны иметь одинаковый размер. Одна из мощнейших функций языка. Работает это следующим образом:
(map car ‘((a b) (d e) (g h))) Результат (a d g)
(map cdr ‘((a b) (d e) (g h))) Результат ((b) (e) (h))
(map cadr ‘((a b) (d e) (g h))) Результат (b e h)
Функция всегда работает со списками и списки же и возвращает. Эти примеры не полностью раскрывают работу функции, вот еще примеры:
(map + ’(1 2 3) ’(4 5 6)) Результат (5 7 9)
(map + ‘(1 2 3) ‘(4 5 6) ‘(7 8 9)) Результат (12 15 18)
(define my-list ‘(1 2 3 4 5))
(define (square val) (* val val))
(map square my-list) Результат (1 4 9 16 25)
(for—each proc list1 list2 …) —
аналогична map, но используется в основном для функций с побочными эффектами, результат которых не определен.
(let ((v (make-vector 5)))
(for-each (lambda (i)
(vector-set! v i (* i i)))
‘(0 1 2 3 4))
v)
Результат #(0 1 4 9 16). Создаем вектор v из пяти элементов. Затем применяем (lambda (i) к вектору v. Заносим данные из списка ‘(0 1 2 3 4) (который сразу не вычисляется из-за одинарной кавычки) следующим образом: в вектор v записывается элемент списка, умноженный сам на себя (запись осуществляется посредством vector—set!, при этом в качестве индексов для доступа к вектору используется все тот же список ‘(0 1 2 3 4)). После выхода из блока let вектор v будет разрушен, а его содержимое будет передан как результат работы блока let.
PLT Scheme
Теперь немного подробней о самой IDE. PLT Scheme состоит из нескольких компонентов:
. MrEd – расширение MzScheme для графического программирования
. DrScheme – среда проектирования
. Mzc – компилятор в байт-код, не зависимый от платформы (позволяет создавать переносимые приложения)
. MzScheme3m – экспериментальная версия MzScheme, особенность которой более точное управление распределением памятью (в сравнении MzScheme).
MzScheme, основной компилятор, интерпретатор, и система поддержки исполнения программ. Кроме того, PLT Scheme, содержит в себе не только описанный выше стандарт R5RS, но также дополнительные возможности, а именно:
. система поддержки пространства имен и управления трансляцией
. поддержка механизма исключений
. приоритетные потоки
. классы и система объектов
. регулярные выражения
. расширенная поддержка макросов
. поддержка хэшей (как встроенного типа данных)
. поддержка юникода.
И более того, PLT Scheme содержит также группу диалектов Scheme, каждый из которых имеет свои задачи (например, есть диалект специально адаптированный для изучения функционального программирования студентами высших учебных заведений). Так как система построена в минималистичном и строгом стиле рекомендуется начинать изучение с DrScheme (он не так суров, и не сильно отпугивает пользователей привыкших к обилию кнопок, картинок и иконостасу на Рабочем столе). Его-то мы и рассмотрим подробней.
Как уже упоминалось ранее, DrScheme имеет два окна, одно предназначено для ввода текста программы, второй есть командный интерпретатор (команды, введенные в него, исполняются немедленно, что удобно для изучения языка). В последнее же окно выводится и сообщения от drScheme, именуемое как главная текстовая область (см. рисунок 1):
Поскольку PLT Scheme поддерживает несколько языков программирования, то прежде чем приступить к работе, нужно выбрать* соответствующий язык программирования Language|Choose Language (см. рисунок 2):
* Комментарий автора
наименование пунктов меню может немного отличаться в зависимости от версии среды разработки
Стандарт языка называется Standart (R5RS), для освоения материала статьи его вполне достаточно. Остальные диалекты отличаются различными свойствами, в том числе и поддержкой графического интерфейса пользователя. PLT Scheme запоминает последний выбранный диалект и при следующем запуске сразу же готов работать в выбранном контексте.
Изюминкой PLT Scheme является возможность компиляции текстов программ. Исторически и по ряду объективных причин большинство реализаций Scheme есть интерпретаторы. Однако готовые к употреблению программы без стороннего окружения также необходимы (что, кстати, требуют и решаемые задачи, круг которых гораздо шире в PLT Scheme, чем в голом стандарте R5RS). Чтобы получить из текста программы на языке Scheme вполне функциональный exe-файл требуется, чтобы программа была введена в окно ввода программы (обычно оно первое) (см. рисунок 3). А также чтобы она была уже сохранена во внешнем файле.
Затем выбираем пункт меню Scheme|Create Executable… Далее необходимо выбрать тип исполнения файла (см. рисунок 4):
. Launcher
. Stand-alone
. Distribution.
Для простых учебных примеров Stand—alone вполне достаточно (однако, если необходимо использовать программу на другом компьютере, то потребуется перетащить некоторые библиотеки).
Заключение
Введение дает только элементарные азы и рассчитано на плавный переход от императивного стиля к функциональному. Данное введение не дает представления о функциональном программировании – это просто справочник наиболее распространенных команд языка Scheme, также знакомство с конкретной средой разработки PLT Scheme. Более полное и подробное руководство по PLT Scheme можно найти на сайте проекта (на английском языке), статья предназначена быть отправной точкой для дальнейшего самостоятельного обучения. Дополнительно можно отметить возможность встраивания Scheme и в другие языки программирования (как встроить Scheme в Дельфи, можно узнать здесь: http://www.orlovsergei.com/Progs/Scheme/SchemeToDelphi.htm). Плюсы такого союза очевидны, например, это удобно для работы с длинной арифметикой.
Ресурсы
. Лисп как альтернатива Java http://alexey.tamb.ru/scheme/lisp-scheme-java.html
. Сайт «схемщиков» http://schemers.org
. PLT Scheme http://www.plt-scheme.org
. Дополнительные библиотеки для PLT Scheme http://planet.plt-scheme.org
. Неформальное введение в Scheme http://ru.wikibooks.org/wiki/Введение_в_язык_Scheme_для_школьников
Облако меток
css реестр ассемблер timer SaveToFile ShellExecute программы массив советы word MySQL SQL ListView pos random компоненты дата LoadFromFile form база данных сеть html php RichEdit indy строки Win Api tstringlist Image мысли макросы Edit ListBox office C/C++ memo графика StringGrid canvas поиск файл Pascal форма Файлы интернет Microsoft Office Excel excel winapi журнал ПРОграммист DelphiКупить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)