ВЫДЕРЖКА
Научите свой компьютер быть вежливым
Из Tiny C Projects Дэна Гукина
В этой статье рассказывается о написании программы на C, которая выводит соответствующее приветствие в зависимости от времени суток при запуске компьютера.
Получите скидку 35% на Tiny C Projects, введя fccgookin в поле кода скидки при оформлении заказа на manning.com.
Простое приветствие
Все крупные проекты по программированию начинаются с простого и имеют тенденцию превращаться в сложных, уродливых монстров. Я уверен, что Excel начал свое существование как быстрый и грязный калькулятор в текстовом режиме — и теперь взгляните на него. Тем не менее, хорошей практикой программирования является не начинать проект с написания сразу всего, что вам нужно. Нет, лучше развивать проект, начав с чего-то простого и глупого, в чем смысл этого раздела.
Написание приветствия
Самая простая программа-приветствие, которую вы можете сделать, — это просто повторение дурацкой программы Hello World, которая появляется на страницах каждой вводной книги по программированию на C со времен Моисея. В листинге 1 показана версия, которую вы можете написать для своей программы приветствия.
Листинг 1 welcome01_basic.c
#include <stdio.h> int main() { printf("Hello, Dan!\n"); return(0); }
Не строить. Не беги. Если вы это сделаете, используйте эту команду для создания программы с именем greetings:
clang -Wall greet01_basic.c -o greetings
Вы можете заменить clang
на свой любимый, но слабый компилятор. В случае успеха результирующая программа называется greetings
. Установите эту программу в сценарий запуска вашей оболочки, добавив последнюю строку, которая выглядит следующим образом:
Greetings
Убедитесь, что вы добавляете к имени программы префикс пути или полный путь, например:
/home/dang/bin/greetings
или относительный путь:
~/bin/greetings
Сценарий запуска не может волшебным образом найти программные файлы, если вы не укажете путь, например, к моему личному каталогу ~/bin, показанному в примерах. (Я также использую свой сценарий запуска оболочки, чтобы поместить мой личный каталог ~/bin в путь поиска — еще один трюк Linux, найденный где-то в другой книге.)
После обновления сценария запуска следующее открытое окно терминала запускает сценарий запуска, который выводит следующую строку, делая ваш день более веселым:
Hello, Dan!
А если тебя зовут не Дэн, то приветствие вызывает больше недоумения, чем веселья.
Добавление имени в качестве аргумента
Первоначальная версия программы greetings негибкая. Вероятно, поэтому вы не закодировали его, а вместо этого стремитесь изменить его с помощью некоторых настроек.
Рассмотрим небольшое улучшение, предлагаемое в листинге 2. Это обновление кода позволяет представить программу с аргументом, что делает ее более гибкой.
Листинг 2 welcome02_basic.c
#include <stdio.h> int main(int argc, char *argv[]) { if( argc<2) #A puts("Hello, you handsome beast!"); else printf("Hello, %s!\n",argv[1]); #B return(0); }
#A Количество аргументов для имени программы всегда равно 1. Если это так, выводится сообщение по умолчанию.
#B Все, что было введено после имени программы (только одно слово), представляется как argv[1] и выводится здесь.
Встройте этот код в программу и вставьте его в сценарий запуска вашей оболочки, как написано в древних свитках, а также в предыдущем разделе.
greetings Danny
Теперь программа выводит следующее сообщение при открытии нового окна терминала:
Hello, Danny!
Это новое сообщение гораздо более радостное, чем исходное, но все еще требует некоторого улучшения.
Время суток
Одна из первых программ, которые я написал для своего старого компьютера с DOS, приветствовала меня каждый раз, когда я запускал машину. Программа немного скучновата, к сожалению. Чтобы оживить его, вдохновленный моим словесным взаимодействием с людьми, с которыми я сталкиваюсь в реальной жизни, я добавил код, чтобы приветствие отражало время суток. Вы также можете сделать это с разной степенью точности.
Получение текущего времени
Кто-нибудь действительно знает, который час? Компьютер может угадать. Он поддерживает полуточное время, потому что время от времени связывается с сервером времени в Интернете. В противном случае часы компьютера каждый день отставали бы на несколько минут. Поверьте мне, компьютеры делают паршивые часы, но эта истина не мешает вам вытаскивать текущее время из его внутренностей.
Библиотека C изобилует временными функциями, все они определены в заголовочном файле time.h
. Тип данных time_t также определяется в заголовке. Для большинства компиляторов тип данных time_t представляет собой положительное целочисленное значение (тип данных long, printf() заполнитель %ld
), в котором хранится эпоха Unix. , количество секунд, прошедших с полуночи 1 января 1970 года.
Эпоха Unix очень полезна для использования в вашей программе приветствия. Например, представьте свою радость, видя — каждый день при запуске терминала — следующее веселое сообщение:
Hello, Danny, it's 1624424373
Конечно, значение time_t должно быть преобразовано во что-то более полезное. В листинге 1 показан пример кода. Имейте в виду, что многие функции времени, такие как time() и ctime(), используемые в коде для time01.c
, требуют адрес time_t. переменная. Да, это указатели.
Листинг 3 time01.c
#include <stdio.h> #include <time.h> #A int main() { time_t now; time(&now); #B printf("The computer thinks it's %ld\n",now); printf("%s",ctime(&now)); #C return(0); }
#A Файл заголовка time.h
требуется, чтобы компилятор не рассердился на вас.
#B Для функции time() требуется адрес переменной time_t, перед которым здесь стоит оператор & address-of.
#C Функция ctime() требует аргумента-указателя и возвращает строку с добавлением новой строки.
Вот пример вывода получившейся программы:
The computer thinks it's 1624424373 Tue Jun 22 21:59:33 2021
Выходные данные показывают количество секунд тик-так с 1970 года. Это же значение используется функцией ctime() для вывода отформатированной строки времени. Этот результат может быть приемлемым для вашей программы приветствия, но данные о времени можно дополнительно настроить. Ключ к раскрытию информации о конкретном времени находится в функции localtime(), как показано в коде в листинге 4.
Листинг 4 time02.c
#include <stdio.h> #include <time.h> int main() { time_t now; struct tm *clock; #A time(&now); clock = localtime(&now); puts("Time details:"); printf(" Day of the year: %d\n",clock->tm_yday); printf(" Day of the week: %d\n",clock->tm_wday); #B printf(" Year: %d\n",clock->tm_year+1900); #C printf(" Month: %d\n",clock->tm_mon+1); #D printf("Day of the month: %d\n",clock->tm_mday); printf(" Hour: %d\n",clock->tm_hour); printf(" Minute: %d\n",clock->tm_min); printf(" Second: %d\n",clock->tm_sec); return(0); }
A# Поскольку localtime() возвращает указатель, лучше всего объявить структуру как указатель.
B# Первый день недели — 0 для воскресенья
C# Чтобы получить текущий год, необходимо добавить 1900 к элементу tm_year
. Вы забудете об этом.
D#. tm_mon
член находится в диапазоне от 0 до 11.
Я отформатировал код в листинге 4 с кучей пробелов, чтобы вы могли легко идентифицировать элементы структуры tm
. Эти переменные представляют лакомые кусочки времени, которые функция localtime() извлекает из значения time_t
. Убедитесь, что вы не забыли скорректировать некоторые значения, как показано в листинге 2: Значение года tm_year
должно быть увеличено на 1900, чтобы отразить текущий действительный год; значение месяца tm_mon
начинается с нуля, а не с единицы.
Вывод тривиален, поэтому мне не нужно его показывать — если только вы не пришлете мне чек на 5 долларов. Тем не менее, смысл кода в том, чтобы показать, как вы можете получить полезную информацию о времени, с помощью которой должным образом приправить приветствие терминала.
Смешивание общего времени суток
Программа, которую я написал несколько лет назад для своего компьютера с DOS, называлась GREET.COM
. Это была часть программы AUTOEXEC.BAT
моего компьютера, которая запускалась каждый раз, когда я запускал свой старый добрый IBM PC. Поскольку я люблю ностальгические вещи, я сохранил копию программы. Написан на ассемблере x86, работает под DOSBox. Ах, сладкий аромат цифрового прошлого. Пахнет озоном.
Увы, у меня нет исходного кода моей программы GREET.COM
. По памяти (и на разборке) я вижу, что код выбирает текущий час дня и выводит соответствующее приветствие времени суток: доброе утро, добрый день или добрый вечер. Вы можете написать тот же трюк, но на C для вашего текущего компьютера, а не на ассемблере x86 для древнего IBM PC.
В листинге 5, собранном воедино из ресурсов первой части этой главы, показана текущая версия моей старой программы приветствия.
Листинг 5 welcome03_time.c
#include <stdio.h> #include <time.h> int main(int argc, char *argv[]) { time_t now; struct tm *clock; int hour; time(&now); clock = localtime(&now); hour = clock->tm_hour; #A printf("Good "); if( hour < 12 ) #B printf("morning"); else if( hour < 17 ) #C printf("afternoon"); else #D printf("evening"); if( argc>1 ) #E printf(", %s",argv[1]); putchar('\n'); return(0); }
#A Это утверждение предназначено для удобства, чтобы избежать повторного использования clock->tm_hour
многократного
#B До полудня скажите "Доброе утро"
#C С полудня до 17:00 говорите "Добрый день"
#D В противном случае уже вечер
#E Проверить и вывести первый аргумент командной строки
Предполагая, что встроенная программа называется greetings, что пользователь вводит Дэнни в качестве аргумента командной строки и что сейчас 4 часа дня, вот выход:
Good afternoon, Danny
Этот код эффективно повторяет то, что я написал несколько десятилетий назад в качестве моей программы GREET.COM
. Результатом является веселое, релевантное по времени приветствие с учетом текущего времени суток.
Для дополнительного юмора вы можете добавить тест на ранние часы, например, с полуночи до 4:00. Выведите какой-нибудь причудливый текст, например «Работаете допоздна?» или «Ты еще не спишь?» О, шутливость! Я надеюсь, что ваши бока не болят.
Добавление информации о времени
Еще один способ побаловать себя при открытии окна терминала — вывести подробную строку времени. Простой способ выполнить эту задачу — вывести приветствие, за которым следует строка времени, сгенерированная функцией ctime(). Вот две соответствующие строки кода:
printf(“Good day, %s\n”,argv[1]); printf(“It’s %s”,ctime(&now);
Эти два утверждения должны дать вам представление о том, как может выглядеть код. Тем не менее, программа ленивая. Лучше включить функцию strftime(), которая форматирует строку отметки времени в соответствии с вашими требованиями.
Функция strftime() работает аналогично printf() со специальной строкой, которая форматирует информацию о времени. Вывод функции сохраняется в буфере, который ваш код может использовать позже. Код, показанный в листинге 6, демонстрирует это.
Листинг 6greet04_time.c
#include <stdio.h> #include <time.h> int main(int argc, char *argv[]) { time_t now; struct tm *clock; char time_string[64]; #A time(&now); clock = localtime(&now); #B strftime(time_string,64,"Today is %A, %B %d, %Y%nIt is %r%n",clock); printf("Greetings"); if( argc>1 ) printf(", %s",argv[1]); printf("!\n%s",time_string); return(0); }
#Хранилище для строки, заполненной функцией strftime().
#B Чтобы функция strftime() работала, необходимо заполнить структуру localtime() tm
.
Вы можете просмотреть man страницу для strftime(), чтобы узнать обо всех забавных заполнителях и их функциях. Как и функция printf(), заполнители имеют префикс %
. Любой другой текст в строке форматирования выводится как есть. Вот основные моменты оператора strftime() в листинге 6:
Выходные данные отражают строку времени, сгенерированную и сохраненную в буфере time_string[]
. Строка времени появляется после общего приветствия, как описано ранее в этой статье:
Greetings, Danny! Today is Wednesday, June 23, 2021 It is 04:24:47 PM
На этом этапе кто-то может сказать, что весь этот вывод может быть легко выполнен с помощью языка сценариев оболочки, который в любом случае является родным языком файла запуска и конфигурации оболочки. Тем не менее, ваша работа как программиста на C состоит в том, чтобы придать приветствию больше понимания и мощи. Такие дополнения невозможны при использовании унылого маленького языка сценариев оболочки.
Это все для этой статьи. Если вы хотите узнать больше о книге, посмотрите ее здесь.