Как C и Perl захватили планету

Почему C и Perl стали стандартами в своих областях и до сих пор на коне?

Дело, конечно, не только в синтаксисе и парадигме. И даже не в простоте. C, конечно, прост, это по-человечески записанный кроссплатформенный ассемблер. Но Perl совсем не прост, это многослойная обёртка вокруг парсера регулярных выражений.

Весь секрет — в нечестных преимуществах.

Компиляторы C были под все платформы и бесплатно. А какой-нибудь Pas­cal был разный и платный.

Perl изначально создавался для работы с текстом, парсинга, преобразования и т.п. А протокол HTTP целиком текстовый. Вот и писались ранние скрипты на Perl-е.

Потом появился PHP, где были те же регулярки, но c привычными классами и он был тупо проще в освоении. И о Perl для веба стало неудобно говорить. Такое же логичное развитие Perl, как C++ — для C. И как Java — для C++.

А потом появился Python, паттерн MVC дал Ruby on Rails и всё стало как сейчас. Наконец, желание писать даже на сервере знакомым синтаксисом породило Node­JS.

Провал всех без исключения “функциональных решений” немножечко предсказуем — потому что нет области, где они были бы нужны и на голову превзошли конкурентов. Go выстрелил, потому что добавил в чистый C всё, чего там не хватало. Scala — потому что это лаконичная Java. Swift — потому что Mac.

 

Д. Босуэлл, Т. Фаучер — Читаемый код, или программирование как искусство

Небольшая книжка, в которой много полезных мелочей.

Например, более точные варианты названий для типичных функций:

send — deliv­er; dis­patch; announce; dis­trib­ute; route
find — search; extract; locate;recover
start — launch; cre­ate; begin; open
make — cre­ate; set­up; build; gen­er­ate; com­pose; new

Именованные интераторы для циклов (ui лучше, чем просто i).

Дополнительные постфиксы — size_mb, html_utf луче, чем size и html.

first/last — это включающие, а begin/end — исключающие границы.

Пометы в комментах:

TODO - задумано, но не сделано.
FIXME - известно, что есть проблема
HACK - неэлегантное решение проблемы
XXX - серьёзная проблема

Уже второе недоумение насчёт цикла do-while (которые непонятно, зачем нужен).

Разоблачён миф о том, что из функции должен быть только один выход. Он тянется из чистого C, где нередко забывали вычистить память перед выходом. Но c тех пор появились исключения, деструкторы и очистка мусора. А в C простительно писать goto cleanup;

Вообще, если удаётся уменьшить количество отступов, — это хорошо.

Запутывают код: многопоточность, обработчики сигналов/прерываний, исключения, указатели на функции и анонимные функции, виртуальные методы.

В JavaScript и Python переменная, объявленная внутри цикла, будет видна и снаружи. Вообще, область видимости переменных надо сужать. А самые лучшие переменные — константы, поэтому лучше всего менять их один раз.

Переменные объявлять где используются, а не в начале блока. Объявлять всё в начале блока — дурная традиция из Pas­cal и раннего C (хотя в C99 уже разрешили объявлять где угодно).

Также есть приятные куски кода:

Макрос для C++, чтобы убрать warn­ing для неопределённого конструктора копирования или оператора присваивания.

#define DISALLOW_COPY_AND_ASSIGN(ClassName) 
  ClassName(const ClassName&); 
  void operator=(const ClassName&);

И потом писать:

class ClassName {
  private:
     DISALLOW_COPY_AND_ASSIGN(ClassName);
     ...
  public:
     ...
};

QT: error: cannot find -lQtMultimedia

The QtMul­ti­me­dia library is not avail­able in Ubun­tu. If you’re try­ing to cre­ate in Qt a project that uses it, it will fail with fol­low­ing error:

error: can­not find -lQt­Mul­ti­me­dia

To fix it, you have to install qtmo­bil­i­ty and use mul­ti­me­dia items from this lib. Install qtmo­bil­i­ty-dev and lib­de­clar­a­tive-mul­ti­me­dia. Then remove QT += mul­ti­me­dia from .pro file and add INCLUDEPATH to QtMo­bil­i­ty and QtMul­ti­me­di­aK­it direc­to­ries.

Already defined” linker error

This error is very com­mon, when you try to com­pile in Visu­al Stu­dio a huge cross-plat­form C++ project.

This is because of stan­dart C++ tem­plates, that are released in Visu­al Stu­dio libs and in addi­tion­al UNIX libs too. So, you have to exclude one of them to use anoth­er.
Just add one of them, go to Project Prop­er­ties / Link­er / Input / Ignore Spe­cif­ic Default Libraries and add the stan­dard lib that pro­duces con­flict. For me it was enough to add LIBCMT.LIB.

LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt

LINK : fatal error LNK1123: fail­ure dur­ing con­ver­sion to COFF: file invalid or cor­rupt

It’s a com­mon error when you com­pile C++-projects with Visu­al Stu­dio 2010. Ift hap­pens when 2 ver­sion of Visu­al Stu­dio are installed on same PC (like 2010 and 2012) and cause con­flict between two ver­sions of cvtres.exe.

To fix it, go to the bin direc­to­ry of Visu­al Stu­dio 2010 (c:Program Files (x86)Microsoft Visu­al Stu­dio 10.0VCbin or some­thing like this) and rename cvtres.exe to cvtres0.exe.
Don’t wor­ry, it willn’t break link­er of 2010.

C++: Счастливый билет с длинной арифметикой

Счастливый трамвайный билет — это такой, у которого сумма первых трёх цифр номера равна сумме трёх последних. При встрече его полагается съесть.

Сколько таких билетов всего? Какова вероятность встретить счастливый?

Алгоритм для этих вычислений в Википедии настолько ужасен, что народ с Хабра довольно быстро породил в комментариях огромное количество вариантов на C++, Perl и… SQL.

Я тоже не смог пройти мимо и написал считалку на C++ с арифметикой указателей и поддержкой длинной арифметики. При желании она может считать хоть 12-значные числа.

Оптимизировал всем, о чём пишут в пособиях для начинающих. Получилась миниатюрная машина Тьюринга, которая бегает указателем по числам и считает разряды:

void inline count_lucky(unsigned int num_length_val)
{
  bool is_odd = (num_length_val % 2) > 0;
  unsigned int num_length = (is_odd) ? num_length_val - 1 : num_length_val;
  register unsigned int lucky=1, total=pow(10.0,(int)num_length), i;
  char *num = new char[num_length], *end=num+(num_length-1);
  register char *pos=end;
  for(i=0; i < num_length; i++)
    num[i]=0;
  while(pos>=num)
  {
     if((*pos)<9)
     {
        (*pos)++;
        if(pos==end)
        {
           if(is_lucky((unsigned char*)num, num_length))
             lucky++;
        }
        else
          pos++;
     }
     else
     {
       *pos=-1;
       pos--;
     }
  }
  printf("Lucky are %d of %d (%.3f%%)n",(is_odd) ? lucky * 10 : lucky, (is_odd) ? total * 10 : total,((float)lucky/total*100));
  delete[] num;
}
bool inline is_lucky(unsigned char* items, unsigned int items_count)
{
  unsigned char val1=0, val2=0;
  unsigned int half = items_count >> 1;
  for(unsigned int i=0; i < half; i++)
  {
    val1 += items[i];
    val2 += items[items_count-1-i];
  }
  return (val1==val2);
}

Увы! Как показывает практика, уже на 7-значном билете тупой перебор, развёрнутый и оптимизированный компилятором, оказывается эффективней. Похоже, компилятор попросту выполняет сам большую часть явно заданных вычислений.
В этом легко убедиться, запустив тест хотя бы для 7 разрядов:

void inline count_lucky(unsigned int num_length);
bool inline is_lucky(unsigned char* items, unsigned int items_count);
int _tmain(int argc, _TCHAR* argv[])
{
  clock_t start = clock(), mine;
  count_lucky(7);
  mine=clock();
  printf("Mine time was: %dn", (mine - start));
  count_lucky_fromwiki();
  printf("His time was: %dn", (clock() - mine));
  return 0;
}

void count_lucky_fromwiki()
{
  int total=0,lucky=0;
  for(int i1=0; i1<10; i1++)
    for(int i2=0; i2<10; i2++)
      for(int i3=0; i3<10; i3++)
        for(int i4=0; i4<10; i4++)
          for(int i5=0; i5<10; i5++)
            for(int i6=0; i6<10; i6++)
              for(int i7=0; i7<10; i7++, total++)
                if(i1+i2+i3 == i5+i6+i7)
                  lucky++;
   printf("Lucky are %d of %d (%.3f%%)n",lucky,total,((float)lucky/total*100));
}

Человек уже не может обогнать машину :(. Слава роботам!

В качестве утешения — на 8 вложенный циклах валился компилятор из Bor­land C++ Builder 6.

C++: Вопросы на собеседовании

Вопросы на собеседовании по С++” — один из самых популярных запросов, по которым находят этот блог.

А значит, настало время расширить этот постинг.

Т.к. такие списки периодически пропадают из Сети, я буду делать свой — с приложенными ответами.

Итак, понеслось:

Напоследок — картинка от jia3ep-а.