29 мая 2010 г.

Изучаю C++. Проблемы с функцией fgets(). Выкидываем символ новой строки из строковой переменной.

Я люблю хорошую музыку. Вы тоже? Отлично. А ещё я люблю переделывать простые и скучные программы из учебников по программированию, добавляя в них дополнительную функциональность и улучшая их. В одной из таких программ (Герберт Шильдт, "C++. Руководство для начинающих, 2-е изд.", стр.182-183) предлагалось написать простой телефонный справочник, используя массив строк. Стоп, телефонный справочник?.. гм... звучит не очень интересно. Я попробовал создать небольшую и простую музыкальную базу данных. Конечно, то, что получилось, было мало похоже на Musicbrainz или Discogs... Ну конечно, ведь это - просто улучшенная версия телефонного справочника из учебника по C++.

Итак, что мы имеем изначально? Программа, приведённая в книге, очень проста. Создаётся массив строк numbers[10][80], этот массив сразу заполняется данными: имя, телефон, имя, телефон ... и т. д. Вы вводите имя, программа последовательно сравнивает введённую вами строку с элементами строкового массива. Если есть совпадение, программа отображает телефонный номер. Конец программы.

cin >> str; // Считываем строку в символьную (char) переменную str[80]
for(i = 0; i < 10; i += 2)
   if(!strcmp(str, numbers[i])) { // Проверяем на совпадение с элементом массива
     cout << "Телефонный номер: " // и выводим на экран
          << numbers[i+1] << "\n";// телефонный номер 

     break;
   }

Теперь пора превратить этот телефонный справочник в музыкальную БД. Во-первых, я поменял название массива и сделал его "безразмерным", вот так: bands[][200]. Как видите, компилятор сам подсчитывает количество строк массива. Кроме того, я увеличил количество столбцов массива  (т. е. максимальную длину записи) до 200, чтобы можно было перечислить несколько альбомов для каждого музыканта:

char bands[][200] = {
   "группа1", "альбом1, альбом2 ...",
   "группа2", "альбом1, альбом2, альбом3 ...",
   // ...
   "группаN", "
альбом1, альбом2 ...",
   "", ""
};


Здесь я добавил в конце массива две пустые строки, содержащие нулевой символ "\0" (компилятор самостоятельно добавляет этот символ в конце каждой строковой переменной). Это пригодится для огранизации цикла последовательного просмотра элементов строкового массива.

Поместил считывание строки, поиск совпадений, и вывод результата в бесконечный цикл, из которого два выхода (а как же иначе?..) - или клавиша <q>, или... <Ctrl>+<c>.

Теперь проблема с cin >> str; - нам не удастся ввести название группы, состоящее из нескольких слов, разделённых пробелами - знак пробела будет воспринят как конец ввода и в переменную str попадёт только первое слово из названия группы. Чтобы исправить это, потребуется использовать... ну, скажем, fgets(str, 100, stdin) для считывания строки. Однако именно эта функция и явилась причиной очень занятного бага, из-за которого программа не могла корректно работать. Дело в том, что функция fgets() прежде, чем завершить свою работу после нажатия <Enter>, считывает в строковую переменную str символ новой строки "\n"! Из-за этой "особенности" функция strcmp(str, bands[i]) работала некорректно - как я не бился, она "в упор" не видела очевидные совпадения введённой строки с элементом строкового массива... И вот теперь я знаю, в чём дело. Но как это исправить? В Интернете нашлось несколько различных howto на тему "как выкинуть ненужный символ новой строки из переменной". Однако все эти способы показались мне чресчур сложными для подобной задачи. После размышлений, я написал следующее:

// с функцией fgets проблема...
fgets(str, 100, stdin);
// ...она передаёт в символьную переменную str, кроме "обычных" символов,
// символ новой строки (\n). Из-за этого операции со str выполняются некорректно.
// Поэтому, с помощью простого цикла, мы находим символ конца строки
// и заменяем его на нулевой символ.
for(i = 0; i < strlen(str); i++) 

  if(str[i] == '\n') str[i] = 0;

После этого программа стала работать корректно.

В процессе изучения языка C++ я часто сталкиваюсь с различными проблемами, которые пытаюсь решить. Иногда это бывает очень просто, а иногда приходится потратить немало времени. В большинстве случаев, больше всего времени уходит на то, чтобы понять, где же я ошибся.

А вообще, на поиск и исправление ошибок может уйти время даже большее, чем на написание самой программы.

22 мая 2010 г.

Стихи на тему "грозы в начале мая"

Сегодня днём взял книгу, лёг на диван и... уснул. И вот, я один на асфальтированной (!) дороге в густом лесу, ночью. Вокруг вековые деревья огромной высоты, у меня в руках волшебная палочка и я никак не могу вспомнить заклинание, вызывающее свет... Проснулся. Из открытой форточки в лицо струится поток свежего воздуха с запахами мокрой травы, листвы, древесины, земли и асфальта. Пока я спал, в городе N^2 прошёл дождь. Кажется, я слышал несколько раскатов грома где-то вдалеке. Ну что же, давно пора - май уже скоро закончится, а ещё не было ни одной грозы.

Кстати, вот стихи на тему "грозы в начале мая", которые я написал уже давно, и, наверное, это совсем "детские" стихи. Точнее, стихи для детей. Однако, например, я до сих пор люблю стихи многих "детских" авторов, которыми зачитывался много-много лет назад. Возможно, эти стихи, написанные мной, будут интересны некоторым читателям этого блога.

http://poptsov-artyom.narod.ru/texts/2007/2007-05-16.html

21 мая 2010 г.

Размышления о "семантическом рабочем столе"

Недавно у меня были неполадки с компьютером (см. предыдущий пост) - при загрузке отказала одна из планок ОЗУ. Оперативная память оказалась заполнена на ~80-90%, ещё столько же сброшено в swap. В связи с активным swapping'ом нагрузка на процессор - ~100%. Таким образом стало ясно, что мне недостаточно 512Мб для обычной работы за компьютером. Недостаточно, чтобы держать запущенными все приложения и сервисы, которые запущены обычно.

Простой запуск системного монитора выявил приложения, которые занимают больше всего памяти в ОЗУ. Ими оказались броузер Firefox с более чем 10 открытыми вкладками (>100Мб), музыкальный проигрыватель Amarok (>50Мб), и сервис Nepomuk, обеспечивающий так называемый "семантический рабочий стол" (>250Мб).

Выключил сервис Nepomuk, после этого стало возможным нормально работать. Впоследствии оказалось (опять же, см. предыдущий пост), что обе планки ОЗУ работают, по крайней мере, пока - уже несколько раз перезагружал компьютер, ещё ни одна не отказала. И можно снова включить сервис Nepomuk...

Однако резкое уменьшение оперативной памяти оказалось отличным поводом задуматься над тем, а нужен ли мне этот сервис? Nepomuk отхватывает под себя более 200 мегабайт в оперативной памяти, и его база данных разраслась уже до более чем 600 мегабайт. Он индексирует файлы, я проставляю "теги" для файлов и папок... Вроде бы, всё нормально. Но за то время, пока работаю в интегрированной среде KDE - часто ли я пользовался "интеллектуальным" поиском, основанным на содержимом файлов, моих тегах и рейтингах?.. Я и так знаю, что и где у меня лежит на жёстких дисках - по крайней мере, те данные, к которым я часто обращаюсь.

Проблемы с поиском нужной информации, в первую очередь, связаны с тем, что эта информация плохо организована. Несомненно, количество информации так же влияет на время и успешность поиска - чем больше информации, тем сложнее её организовать, и "выловить" из неё то, что нужно в данный момент. Ярким примером может служить всё более разрастающийся Интернет. Но, если взять в привычку "по-умолчанию" раскладывать всё на своё место, то увеличение количества информации не будет так сильно сказываться на успешности её поиска.

Ну, и что же я жду от "семантического рабочего стола"? Отвечаю: во-первых, это практическая польза. Это помощь в организации данных, накопленных за всё время. Автоматическое архивирование и/или сжатие (с согласия пользователя, т. е. меня) редко используемых документов. Гибкая система настроек, возможность программировать поведение системы при определённых событиях. Работа сервиса не только в пределах пользовательских данных, но и тесная интеграция с системой, слежение за системными файлами и данными, взаимодействие с системами управления пакетами и исходными кодами ПО, подобными системе портежей в ОС Gentoo и т. д.

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

19 мая 2010 г.

Проблемы с ОЗУ. 512Мб - много или мало?

Вчера утром я подошёл к компьютеру и нажал на кнопку включения. Компьютер начал загружаться, но на начальной стадии загрузки (когда опрашивается аппаратное обеспечение, "железо"), пропищал последовательно несколько раз и перезагрузился. После перезагрузки всё снова повторилось - писк и перезагрузка. Нажал на кнопку <Reset>, после очередной перезагрузки компьютер наконец-то загрузился. Ну что же, замечательно - только вместо 1024Мб ОЗУ я обнаружил только 512Мб.

Помню, давно как то я читал, что "писк" в начале загрузки - это не просто вопль компьютера, которого заставляют работать. Дело в том, что с помощью этого звукового сигнала компьютер сообщает пользователю о состоянии аппаратного обеспечения. Так, одиночный звуковой сигнал говорит о том, что всё в порядке. Если при опросе "железа" что-то пошло не так, то компьютер сообщит об этом опять же звуковым сигналом. Есть определённая последовательность звуковых сигналов для каждой неисправности. Если сломалась видеокарта - то одна последовательность, если что-то случилось с ОЗУ - другая, если блок питания барахлит - третья. Разная продолжительность и количество звуковых сигналов, и пауз между ними. Это похоже на азбуку Морзе. Таким образом, специалисты (к которым я, увы, не отношусь пока) могут определить на слух неисправность уже на этапе начальной стадии загрузки, ещё до того, как будут доступны какие-либо консольные средства диагностики (не говоря уже о графических).

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

И вот, компьютер загрузился, половины ОЗУ нет. Жуткие "тормоза". Даже курсор двигается рывками, иногда на время словно "прилипая" к окнам и рабочему столу. Работать невозможно. Эх, слышали бы это лет 15 назад - тогда пользователи и не мечтали о объёме ОЗУ в 512 мегабайт...

Но сейчас такого объёма недостаточно. Сервис Nepomuk, который постоянно находится в памяти и обеспечивает так называемый "семантический рабочий стол", иногда разрастается до огромных размеров в ~200-400Мб. Броузер "отхватывает" для себя ~100Мб и более (в зависимости от количества открытых вкладок), интегрированная среда KDE, без всяких супер-спецэффектов и т. н. "плазмоидов" на рабочем столе, тоже требует в ОЗУ несколько десятков мегабайт. Запущенный Emacs "ест", по сравнению с ними, всего лишь ~6-10Мб. Ах да, ещё свалка временных файлов /tmp располагается в ОЗУ благодаря монтированию в неё файловой системы tmpfs... А ведь были времена, когда оперативное запоминающее устройство в 64Кб считалось вполне достаточным для работы.

Уменьшение ОЗУ в два раза было отличным поводом задуматься, а нужен ли мне вообще сервис Nepomuk. Рассуждения по поводу "семантического рабочего стола" будут в следующем посте, я думаю.

А сегодня я разобрал компьютер, почистил его от пыли, запустил сначала с одной планкой ОЗУ, потом - с другой. Обе планки оказались рабочие. Вернул всё, как было. Запустил. Снова 1024Мб. Но подобный случай не может не насторожить. Пора читать умные книги о том, как чинить/обновлять/собирать компьютеры.

14 мая 2010 г.

Недавно открыл для себя музыку эмбиент/пост-рок проекта lowercase noises

Недавно открыл для себя музыку эмбиент/пост-рок проекта "lowercase noises". Этот проект состоит из одного человека по имени Andу Othling. С его творчеством можно ознакомиться на официальном сайте проекта:
http://www.lowercasenoises.com/

Сейчас можно бесплатно скачать его альбом "Seafront" с сайта проекта, для этого нужно получить специальный код, который музыкант периодически публикует через свой аккаунт на Twitter'е (кстати, вот его аккаунт: http://twitter.com/lowercasenoises). Каждый код действует только один раз (насколько я понял). Сегодня мне удалось заполучить этот альбом, причём, его можно скачать в различных форматах, в том числе, в формате FLAC, что приятно удивило.

Ах да, быть может, это мелочь, но альбом был упакован в архив zip (в Интернете, по моим наблюдением, чаще можно встретить проприетарный формат архивов rar)

Теперь о музыке (собственно, ради чего и написан этот пост). Плавное, даже как бы "танцующее" звучание гитары в эмбиент-композициях "Reeds", "Certain Remembrances" и "It Was A Sight", в последних трёх композициях альбома периодически срывается в пост-рок, контрастируя со спокойными треками в начале. В некоторых композициях фоном идёт повествовательный текст - не думаю, что он каким-то образом улучшает звучание, скорее, даже наоборот. Но это лишь IMHO.

На мой взгляд и слух, интересны песни, исполняемые "в живую", а так же эксперименты со звуком - которые музыкант записывает на видео и выкладывает на YouTube. Вот одна из композиций с альбома "Seafront", которая мне особенно понравилась в живом исполнении - "It Was A Sight" aka "Ambient Song #2"

10 мая 2010 г.

Helios - Bless This Morning Year

За проектом Helios стоит один человек - Keith Kenniff.

Красивая музыка, близкая к стилю эмбиент, с лёгкими оттенками пост-рока -- в слегка жёстком (на общем фоне), неровном ритме, с электронным, но иногда нарочито-живым акустическим звучанием гитары, и исчезающим, непостоянным звучанием клавишных.

Это любительское видео на песню. Красивые съёмки, вполне соответствующие музыке. Если вы не равнодушны к творчеству группы Hammock, то это видео и эта музыка должны вам понравиться.

3 мая 2010 г.

Немного о практическом использовании alias'ов

В замечательной книге Алексея Федорчука "Доступный UNIX", которая мне очень помогла на стадии базового освоения Linux и продолжает помогать до сих пор, есть отдельный параграф, посвящённый назначению псевдонимов для команд. Вряд ли я смогу сказать об этой возможности что-то новое. С помощью команды alias можно назначить псевдоним или переопределение для любой команды с любыми параметрами. Команда alias имеет следующий синтаксис:

# alias [имя_псевдонима[=значение_псевдонима] ...]

Будучи данная без аргументов, выведет список всех определённых пользователем псевдонимов. Например,

# alias
alias grep='grep --colour=auto'
alias ls='ls --color=auto'

Если, в качестве аргумента, дать название псевдонима/переопределения, то команда выведет его значение:

# alias grep
alias grep='grep --colour=auto'

Чтобы удалить псевдоним/переопределение, достаточно дать команду

# unalias grep

"Алиасы", будучи прописанными в конфигурационных файлах оболочки (shell), сохраняются и после перезагрузки, в противном случае - будут действовать только в пределах текущей сессии. Например, глобальные alias'ы оболочки bash хранятся в /etc/bash/bashrc. Кроме этого, для каждого пользователя существует отдельный конфигурационный файл для командной оболочки, хранящийся в домашней директории и считывающийся после глобального конфигурационного файла.

Для примера, создадим переопределение для команды удаления rm

# alias rm='rm -i'

Это может спасти пользователя от случайного удаления нужных файлов. Как это работает? Всё очень просто. Командой выше мы создали переопределение для команды удаления rm с флагом -i. Имя псевдонима совпадает с именем оригинальной команды, но псевдоним обладает как бы более высоким "приоритетом" выполнения, и, если мы сейчас дадим команду

# rm file1.txt

она будет равносильна

# rm -i file1.txt

Флаг -i или --interactive, как понятно из его имени, запускает команду в интерактивном режиме. Команда, запущенная с данным флагом, запросит подтверждение у пользователя - действительно ли он хочет удалить файл file1.txt? Этот флаг применим ко многим комадам/утилитам, выполнение которых может привести к нежелательным/неприятным последствиям, таким, как упомянутое выше случайное удаление важных файлов.
Теперь сохраним созданный alias в конфигурационном файле пользователя:

# echo alias rm='rm -i' >> ~/.bashrc

Всё, теперь переопределение команды rm сохранится и после перезагрузки.

Псевдонимы работают похожим образом, но их имена не совпадают с именами доступных команд/утилит. Например,

# alias ll='ls -l'

позволит выводить список директории в расширенном формате, дав команду ll.

Я сейчас мало использую alias'ы, так как они не способствуют запоминанию важных флагов команд. Более того, к ним привыкаешь, и в системе, где привычные alias'ы не определены, можно запросто ввести что-то вроде rm -r ~/*, после чего все файлы в домашней директории будут удалены без предупреждения. Конечно, этот глупый пример, зато наглядный. На мой взгляд, alias'ы не отменяют требование внимательности со стороны пользователя при выполнении команд, особенно, если он работает от имени суперпользователя (root'a).

А вот свежий пример использования команды alias.
Несколько дней назад установил консольный тренажёр "слепого" набора на клавиатуре gtypist:

# emerge -av gtypist

При попытке запустить тренажёр, получаю сообщение:

# gtypist
(null): i18n problem: invalid value for msgid "Y/N": Д/Н

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

# LANG="en" gtypist

А ещё лучше, чтобы каждый раз не указывать локаль, создать переопределение:

# alias gtypist='LANG="en" gtypist'
# echo alias gtypist='LANG="en" gtypist' >> ~/.bashrc
# gtypist
Happy Typing!


Теперь приложение работает без проблем.

1 мая 2010 г.

Завершил основную работу над сайтом магазина

Завершил основную работу над сайтом магазина "Всё для печати", и опубликовал его в Интернет. Может быть, правильнее говорить не "опубликовал", а разместил на сервере narod.ru, или скопировал на сервер... впрочем, сейчас это неважно. Сайт теперь доступен в сети Интернет. Вот ссылка:
http://nnov-print.narod.ru/

Это первый сайт, который я сделал на заказ. Сайт полностью написан в текстовом редакторе Emacs. Возможно, этот способ не совсем профессионален, и подходит только для небольших проектов. Но и я ещё далеко не профессионал в создании сайтов, и учусь по ходу работы.

Для ленты новостей применил уже отработанную технологию использования в связке blogger+feedburner.

Для оформления использовал свободные изображения с Вики-склада, для редактирования использовал графический редактор GIMP.

Проверял сайт на браузерах Mozilla Firefox, Opera, Internet Explorer - всё работает. Однако, если вы заметите какую-нибудь ошибку на сайте - можете оставить комментарий к этому посту или написать мне на почту.

Если вдруг вас заинтересовал сайт, написанный в Emacs, оформленный с помощью GIMP и размещённый на Народе - и вы хотите что-то в таком же духе для себя/своей фирмы - то вы так же можете написать мне на почту.

Адрес моего почтового ящика можно найти здесь:
http://poptsov-artyom.narod.ru/about.html (см. обратная связь)

Попробовал организовать чтение новостей из Emacs

Попробовал организовать чтение новостей из Emacs с помощью расширения newsticker. Просто из интереса. Пока рано говорить, насколько это удобно или неудобно, т. к. нужно сначала всё правильно настроить и испытать в действии.

Если кто не знает, Emacs - многофункциональный текстовый редактор, распространяющийся под свободной лицензией GNU GPL. И с редактированием текста он справляется хорошо, что бы там не говорили. Однако его возможности не исчерпываются банальным редактированием текста. С этим неплохо справляется и консольный редактор Nano.

В ОС Windows я считаю одним из самых универсальных и удобных инструментов файловый менеджер FAR Manager. Так вот, Emacs - это FAR Manager систем GNU/Linux. Да, он ещё умеет работать файловым менеджером, причём, двух-, трёх-, даже черытёхпанельным файловым менеджером. Но я сравниваю его с FAR'ом не только поэтому, а из-за его универсальности. Он написан на языке C и Emacs Lisp (ELisp), благодаря этому для него разработано огромное количество расширений, позволяющих читать новости, просматривать изображения, читать/отправлять электронную почту, просматривать/изменять файлы и многое другое.

Кроме того, Emacs использует не только специально написанные для него расширения, но и всю мощь консольных утилит, входящих в состав GNU/Linux-систем.

Ещё одна замечательная возможность для программиста: внутри Emacs можно запустить любимый shell и компилировать/отлаживать программы, написанные здесь же, в этом текстовом редакторе. Emacs поддерживает автодополнение и подсветку синтаксиса большинства распространённых языков программирования.