Iterators must go by Andrei Alexandrescu. Всем C++-никам посвящается!
PS. Всех коллег поздравляю с Днем программиста.
Iterators must go by Andrei Alexandrescu. Всем C++-никам посвящается!
PS. Всех коллег поздравляю с Днем программиста.
Нужен хороший C++-программист для интересного проекта (создание поискового движка для веб-сайта).
Требования:
Работать нужно в офисе (как оказалось, для некоторых это критично). Офис находится в Днепропетровске, в центре города.
Ответы пишите сюда, в Skype (fxposter), Jabber (fxposter@gmail.com) или ICQ (625585).
PS. Для того, чтобы не появлялись вопросы типа “а причем тут рельсы?” - сам проект пишется на Ruby/Rails, часть поискового движка - на C++.
Кто-нибудь может посоветовать хорошую библиотеку регулярных выражений для C++. Требования (желательно, но, в принципе, не обязательно):
Погуглил - нашел кучу самых разных библиотечек. Выбирать наугад не хочется, так что прошу совета у C++’ников.
… статья под названием “За что я не люблю С++“. Лично мне как человеку знающему язык C++ достаточно хорошо статья очень понравилась и я практически во всем согласен с её автором. C++ действительно очень сложный язык, который к тому же является очень негибким на этапе выполнения (да, да, скорость работы, я понимаю…), и имеющий просто потрясающе огромное количество мелких ловушек, при встрече с которыми можно стать в ступор на долгое время.
PS. Линк на статью нашел у Bolk’а.
PPS. А есть ли аналоги C++, кроме D? Я имею ввиду, которые бы компилировались в нативный код и были такими же эффективными (или хотя бы похожими по эффективности).
Вообще крышу срывает эта учеба…
Делал лабу по C++. Имеем классы:
enum AttributeType {BOOL, INT, DOUBLE, STRING};
class Attribute;
class BoolAttribute;
class IntAttribute;
class DoubleAttribute;
class StringAttribute;
Зачем - не спрашивайте. Кривовато (из-за AttributeType), но на С++ по другому не получалось.
Неделю назад час ебался мучался вопросом, какого хера почему это у меня каст из BoolAttribute* в Attribute* делал хер знает непонятно что, но только не то, что нужно… В итоге забил… Сейчас сел доделывать лабу… На 2-й минуте меня осенило - забыл прописать наследование… Пипееец. Нужно было так:
enum AttributeType {BOOL, INT, DOUBLE, STRING};
class Attribute;
class BoolAttribute : public Attribute;
class IntAttribute : public Attribute;
class DoubleAttribute : public Attribute;
class StringAttribute : public Attribute;
Я с себя потихоньку шизею…
Что-то я затянул немного выполнение лабораторных работ некоторых по универу, нужно исправляться. Сегодня решил вернуться ко второй лабе по ООП. Задание таково:
“Разработать объектно-ориентированную библиотеку для работы со структурами данных по одной из нижеперечисленных тем в соответствии с нижеуказанными требованиями. Свойства и методы для классов разработать в соответствии с известными определениями соответствующих структур данных. Составить тесты для проверки работоспособности библиотеки. Составить программу, демонстрирующую возможности разработанной библиотеки.”
Требования - хрен с ними, а вот тема мне попалась интересная: “Сетевые базы данных (ввод/вывод, навигация)”. Когда я это задание читал в первый раз - я впал в ступор. Потом оклемался, но когда видишь такое задание как-то не по себе становится…
Сетевая бд - это бд, в которой для связи записей используются графы (граф, по курсу структур данных, - это сеть). Т.е. здесь, в отличии от иерархических бд, связи получаются “много к многим” (а там - “один ко многим”).
Поговорил немного с преподами о задании, итог получился такой - “нам не нужна универсальная бд, сделай несколько таблиц статических и связывай их”. Говорил действительно немного - минуты полторы, так что кроме фразы выше я ничего особо не услышал. Сегодня решил хоть чего-нибудь напроектировать, чтобы в пятницу показать преподам и убедится, правильно ли я делаю, или нет. Мысля сейчас такая: есть отдельные таблицы (неважно, как представленные) и есть какой-нибудь класс Relation, который их связывает. Собственно, это очень напоминает обычную иерархическую бд (таблица - связующая таблица - таблица), но как это оформлять по другому я пока что не представляю.
Сел за комп, закодил… Получилось такая фигня:
class Masseur : public Record {
public:
Masseur();
virtual ~Masseur();
private:
char* _name;
char* _surname;
char* _fathername;
char* _qualification;
Date _birthday;
};
class Service : public Record {
public:
Service();
virtual ~Service();
private:
char* _name;
char* _part;
int _duration;
double _price;
};
class MasseurServiceRelation : public Relation {
public:
MasseurServiceRelation();
virtual ~MasseurServiceRelation();
private:
void add(Masseur*, Service*);
void remove(Masseur*, Service*);
void remove(Service* service);
void remove(Masseur* masseur);
};
Сейчас сижу и думаю, правильным ли путем я иду…
PS. А первые две таблицы очень напоминают паттерн ActiveRecord, на правда ли? :)
В свое время выбирал IDE для работы с C++, посоветовали попробовать Code::Blocks. Попробовал, понравилось. Симпатичная IDE, хороший автокомплит, неплохая настраиваемость, поддержка gcc - а мне другого и не нужно было. После того, как я заинтересовался Qt, я стал искать плагины для поддержки этой библиотеки к Code::Blocks. Нашел QtWorkbench. Вот только плагин к линукс-версии можно подключить, только заново скомпилировав саму программу. Чем я раньше и занимался - ведь вот есть хорошая инструкция. Вчера заметил странную директорию debian, которая находится в Code::Blocks’овом trunk’е. Там есть файлик rules, после его просмотра стало ясно, что здесь все уже сделано для построения пакетов для Debian-based дистрибутивов линукса. И вот решил я ночью пакет сделать, со встроенным QtWorkbench’ем.
Для конфигурирования и сборки пакетов:
sudo apt-get install libtool autoconf automake dh-make
Если у вас не Ubuntu/Gutsy - следуем этим инструкциям и добавляем в apt нужный репозиторий. Устанавливаем wxwidgets и g++:
sudo apt-get install g++ wx-common libwxgtk2.8-dev
Также мне в Kubuntu пришлось установить libgtk:
sudo apt-get install libgtk2.0-dev
Далее - следуем начальным инструкциям отсюда:
svn checkout svn://svn.berlios.de/codeblocks/trunk codeblocks
cd codeblocks/
wget http://qtworkbench.googlecode.com/files/QtWorkbench-src-0.5.1.tar.gz
tar zxf QtWorkbench-src-0.5.1.tar.gz
patch --unified --strip=0 --forward --input=qtworkbench.patch
./bootstrap
Конфигурируем для установки всех плагинов и указываем, что ставить нужно в /usr:
./configure --prefix=/usr --with-contrib-plugins=all
Теперь нужно указать, что мы хотим включить в пакеты и QtWorkbench (если этого не сделать - dh-make выдаст после линкования и компиляции всех файлов, что у вас есть лишние файлы и откажется создавать пакет):
sudo nano debian/codeblocks-contrib.install
И добавляем в конец файла эти строчки:
usr/share/codeblocks/QtWorkbench.zip*
usr/share/codeblocks/plugins/libQtWorkbench.*
Сохраняем файл и начинаем делать пакеты (у меня компилировалось и линковалось долго, больше получаса, так что будьте терпеливы):
sudo ./debian/rules binary-arch
На выходе получаем 7 пакетов и ставим Code::Blocks:
cd ..
sudo dpkg -i libcodeblocks0_1.0svn4561_i386.deb libwxsmithlib0_1.0svn4561_i386.deb codeblocks_1.0svn4561_i386.deb codeblocks-contrib_1.0svn4561_i386.deb
Я использовал svn4561-ревизию, так что у вас номер в deb-файлах скорее всего будет другой. Учитывайте это.
Собранные мной пакеты лежат здесь (ubuntu 7.10) и здесь (debian unstable).
Начнем издалека… Есть в C++ встроенный тип size_t, который является “целым типом без знака, используемым реализацией для индексирования массивов” © Страуструп. То есть, если вы работаете с индексами в массивах и их длинами, то в общем-то “правильнее” использовать не int, что в большинстве случаев и делается, а именно size_t (для длин можно еще использовать ptrdiff_t - тип, который возвращает операция вычитания двух указателей). Вчера эта “правильность” для меня вышла боком…
size_t length;
...
for(size_t i = 0; i < length; ++i) {
double x = 2 * (i - length / 2) / length;
...
}
Вот такой был изначальный код. Через несколько минут после написания я вспомнил, что неплохо бы сделать так:
size_t length;
...
for(size_t i = 0; i < length; ++i) {
double x = 2 * static_cast<double>(i - length / 2) / length;
...
}
потому что при делении двух целых чисел у нас тоже целое будет, а мне нужно было как раз вещественное.
Но это еще ладно. После этого я отдал свой кусок лабораторной (мы ее пишем парами) своей девушке (а я как раз с ней пишу). Когда она добралась до этого кода и стала тестить его - у нее стали получаться какие-то странные, неправильные числа. Долгое время я копался в коде и не мог понять, в чем проблема, а потом до меня наконец-то дошло - разность двух беззнаковых чисел также будет беззнаковая (т.е. число -1 будет на самом деле 0xFFFFFFFF), после чего код превратился в такой:
size_t length;
...
for(size_t i = 0; i < length; ++i) {
double x = 2 * static_cast<double>(static_cast<int>(i) - static_cast<int>(length) / 2) / length;
...
}
После чего я на всякий случай еще полчаса проверял небольшую программу на вот такие ошибки - на всякий случай. К счастью, таких больше не нашлось, но неприятный осадок остался.
Выводы: или пишите не особо заморачиваясь на правильности употребления типов (везде используйте int и double, например), или пишите семантически правильно, но не делайте таких ошибок, как я… Может, конечно, это только я такой, но мне лично сложно было именно по коду определить, что результат будет получаться не такой как я хочу.
PS. Я теперь немного понимаю, почему в Java нет unsigned типов. :)
Не могу не отметить статью из октябрьского номера MSDN Magazine про “Оптимизацию управляемого кода для многоядерных компьютеров”. В статье рассказывается о библиотеке TPL, которая позволяет использовать все преимущества многоядерности практически без изменений исходных кодов (по сравнению с переписыванием кода с использованием Thread’ов - здесь изменения в коде потребуются лишь чисто косметические).
На мой взгляд, готовится бомба, так как использование фич многоядерных процессоров становится до неприличия простым. Статья очень интересна как в теоретическом, так и в практическом плане. Так что советую ее почитать всем программистам, даже тем, кто с C# не знаком - ведь возможно, в ближайшем будущем именно такой подход и будет использоваться.
PS. В “более далеком” будущем, как мне кажется, эта библиотека перекочует в компилятор, который сам будет решать - нужно ли распараллеливать текущий код или нет.
PPS. Интересно, уйдут ли Thread’ы в небытие? :)
Достаточно интересный факт - MS открывает исходники многих библиотек .NET фреймворка, в частности .NET Base Class Libraries (System, System.IO, System.Collections, System.Configuration, System.Threading, System.Net, System.Security, System.Runtime, System.Text, etc), ASP.NET (System.Web), Windows Forms (System.Windows.Forms), ADO.NET (System.Data), XML (System.Xml), and WPF (System.Windows). В дальнейшем планируется открытие и остальных библиотек.
В чем основные плюсы этого решения для .NET-программистов:

Теперь о подводных камнях - код открыт по лицензии Microsoft Reference License (MS-RL), которая подразумевает возможность только просмотра кода, перекомпиляция или изменение этих кодов по лицензии строго-настрого запрещены. То есть на развитие того же Mono Project это решение фирмы MS никак не повлияет, а жаль - очень бы хотелось, чтобы Mono был реальным аналогом того .NET’а, которым нас балует MS.
И вдогонку - на днях наткнулся на очень хорошую статью по нововведениям в C# 3.0, которая меня очень порадовала - в отличии от Java, C# не стоит на месте, а развивается. В Java в основном меняется библиотека стандартная, в случае же C# + .NET Framework меняются обе составляющие: язык становится более удобным (как по мне - гораздо более удобным, мне Linq ну просто очень понравился), а .NET Framework обрастает новыми функциями.
Последние комментарии