Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10

Оценка стиля кода

25.01.2015, 01:27. Показов 2818. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Народ, есть предложение. Оцените мой код. Не в смысле функционала - в смысле стиля написания.

Значится, вот тут есть некий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
bool __fastcall TForm1::check_condition( void )
{
    for ( t_cells::iterator it( cells.begin( ) ), end( cells.end( ) );
        it != end;
        ++it )
    {
        if ( it->second->charged && it->second->gp == GP_MUST_PASS )
        {
            return false;
        }
    }
    return true;
}
 
// ---------------------------------------------------------------------------
bool __fastcall TForm1::engine_make_step( void )
{
    if ( check_condition( ) )
    {
        return false;
    }
 
    t_neibs accepting_neibs, declinatory_neibs;
    t_cell * receiver;
 
    // bool charge_passed_this_step( false );
 
    for ( t_cells::iterator it( cells.begin( ) ), end( cells.end( ) );
        it != end;
        ++it, accepting_neibs.clear( ), declinatory_neibs.clear( ) )
    {
        t_cell * cell( it->second );
        for ( t_neibs::iterator neib( cell->neibs.begin( ) ), neib_end( cell->neibs.end( ) );
            cell->charged && !cell->just_received && ( neib != neib_end );
            ++neib )
        {
            t_cell * neib_cell( cells[ * neib ] );
            if ( !neib_cell->charged )
            {
                if ( neib_cell->rp == RP_PASS_WANTED )
                {
                    accepting_neibs.push_back( * neib );
                }
                else
                {
                    declinatory_neibs.push_back( * neib );
                }
            }
        }
        if ( accepting_neibs.size( ) > 0 )
        {
            receiver = cells[ accepting_neibs[ std::rand( ) % accepting_neibs.size( ) ] ];
            cell->pass_charge_to( receiver );
            // charge_passed_this_step = true;
        }
        else if ( ( declinatory_neibs.size( ) > 0 ) && ( cell->gp == GP_MUST_PASS ) )
        {
            receiver = cells[ declinatory_neibs[ std::rand( ) % declinatory_neibs.size( ) ] ];
            cell->pass_charge_to( receiver );
            // charge_passed_this_step = true;
        }
    }
    recalc_priorities( );
    // return charge_passed_this_step;
    return true;
}
Небезызвестный товарищ Avazart имел удовольствие мне намекнуть на, прости хоспаде, говнокодность стиля моего. Прения не дали желаемого результата, потому выношу на суд общественности. Ну, еще мне просто любопытно вас послушать)

Итак, кто за мою аннигиляцию, как написателя адекватного цпп кода - поднимите руки и скажите свое язвительное слово.
Кто против - тоже не стесняйтесь.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.01.2015, 01:27
Ответы с готовыми решениями:

Советы по ускорению работы кода + оценка самого кода
Вчера вечером сел написать 3 консольные программки для работы с шаблонами размножения текста: 1.Выборка групп синонимов(создание словаря)...

Оценка кода
Здравствуйте, прошу вас всех оценить мой код , по возможности дать советы что так , а что не так и как это исправить либо в каком...

Оценка кода
Добрый день! Есть задание в ВУЗе: Я сделал следующий код: #include <iostream> #include <conio.h> int...

34
Заблокирован
25.01.2015, 01:45
BRcr, я бы переписал 1 функцию в таком оформлении:
C++
1
2
3
4
5
6
7
8
bool __fastcall TForm1::check_condition( void )
{
    for ( t_cells::iterator it( cells.begin( ) ), end( cells.end( ) ); it != end; ++it )
        if ( it->second->charged && it->second->gp == GP_MUST_PASS )
            return false;
 
    return true;
}
1
 Аватар для Tordek
58 / 51 / 38
Регистрация: 22.01.2015
Сообщений: 176
25.01.2015, 02:05
Мне немного мешают многочисленные пробелы (в особенности, перед скобками), но, хоть я и новичок, код вполне адекватный и читабельный, как по мне. То ли дело у меня
1
209 / 183 / 114
Регистрация: 15.03.2014
Сообщений: 398
25.01.2015, 02:55
BRcr, выскажу свое мнение.
Пробелы
1) После скобки и перед скобок. Если между скобками пусто, то и пробел не нужен. Но подряд идущие скобки также отделяются пробелом.
2) Знаки бинарных операций отделены пробелами с обеих сторон от своих операндов. Унарные операции не отделяются пробелом от своих операндов.
C++
1
2
3
4
5
6
7
...
it != end;
...
cell->gp == GP_MUST_PASS
...
declinatory_neibs.push_back( *neib ); // удален пробел между знаком операции разыменования и ее операндом
...
3) Конструкции языка ( if, for, while и другие ) отделены пробелом от открывающей скобки, а имена методов и функций не отделены.
C++
1
2
3
...
for ( t_cells::iterator it( cells.begin() ), end( cells.end() ); // удалены пробелы между скобками
...
4) Открывающую фигурную скобку предпочитаю писать в той же строке, отделяя ее пробелом.
Вложенные операторы типа for и нижеследующих if отделяю пустой строкой если "родительский" оператор верхнего уровня имеет предыдущие операторы в своем теле. Не пишу фигурных скобок, когда этого не требуется. Знаю что это спорный вопрос для многих.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
        // удалены фигурные скобки
    if ( !neib_cell->charged )
        if ( neib_cell->rp == RP_PASS_WANTED )
            accepting_neibs.push_back( *neib );
        else
            declinatory_neibs.push_back( *neib );
...
// открывающие  фигурные скобки в той же строке и отделены пробелом, но КОНКРЕТНО тут я бы их вообще не использовал
for ( t_cells::iterator it( cells.begin() ), end( cells.end() ); it != end; ++it ) { 
    if ( it->second->charged && it->second->gp == GP_MUST_PASS ) {
        return false;
    }
}
...
Я бы отделил пустой строкой строки 32 и 33, 37 и 38 и подобные, описанные в данном пункте.

Добавлено через 6 минут
Дополнение - согласен с Ev_Hyper, что return в конце функции также отделяется пустой строкой.

Пустые строки иногда заменяю комментариями.
1
117 / 114 / 65
Регистрация: 18.09.2014
Сообщений: 337
25.01.2015, 08:14
BRcr, единственное, что вызвало негатив, пробелы между скобками. Я привык ставить пробелы только между знаками сравнения:
C++
1
2
if (check_condition());
if (it->second_changed() && it->second->gp == GP_MUST_PASS);
ну и при вызове функции тоже не ставлю пробелы
C++
1
func(check_condition(), a, b, &x[0], calc_score(90));
открывающие фигурные скобки тоже раньше писал с новой строки, теперь по какой-то неизвестной мне причине перешёл на другой формат. Думаю, дело вкуса
1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
25.01.2015, 08:20
Цитата Сообщение от BRcr Посмотреть сообщение
for ( t_cells::iterator it( cells.begin( ) ), end( cells.end( ) );
Да, дряной стиль. Легко прочить как если бы это был весь заголовок цикла и пустой оператор в качестве тела.
1
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.01.2015, 11:10
форматирование в данном случае читать не мешает.

1. В теле метода check_condition страшный цикл с итераторами заменяется на return find_if(...) == cells.end();
2. В методе engine_make_step первый цикл перегружен логикой. Помимо итерации он еще на каждом шаге сбрасывает состояние accepting_neibs, declinatory_neibs. Значит, их вообще нужно вынести в другой метод.
3. Второй цикл не лучше — опять в нем какая-то логика помимо итерации. Причем условия, связанные с cell инвариантны. Первая мысль — заменить на range-for. Но если посмотреть дальше, то по сути это два вызова функции типа filter.
4. Последний блок условий — "выбрать receiver и передать его в функцию". Так и переписываем.
5. Семантика проверок типа "size > 0" — проверка на непустоту. Переписываем на not empty.

Что еще не нравится.
6. Выбор случайного элемента можно вынести в отдельную функцию, чтобы это страшное выражение не мозолило глаза.
7. Использование сырых сишных указателей.
8. Нужно больше const'a.
9. Если уж говорить о стиле, поля класса лучше именовать, например, с суффиксом _. По фрагменту кода приходится просматривать все, чтобы понять, объявлена переменная локально или находится в скрытом от глаз коде.

Дисклеймер:
1. При переписывании кода могла быть искажена логика. По очевидным причинам отладить я не мог.
2. Для форматирования использовал clang-format с настройками по умолчанию, поэтому так сильно отличается. Считаю это непринципиальным вопросом.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
bool __fastcall TForm1::check_condition(void) {
  return std::find_if(cells.begin(), cells.end(), [](const t_cell& cell) {
           return it->second->charged and it->second->gp == GP_MUST_PASS;
         }) == cells.end();
}
 
static const t_cell* const find_receiver(const t_cell* const cell,
                                         const t_neibs& accepting_neibs,
                                         const t_neibs& declinatory_neibs) {
  if (not accepting_neibs.empty()) {
    return cells[accepting_neibs[std::rand() % accepting_neibs.size()]];
  }
 
  if (not declinatory_neibs.empty() and cell->gp == GP_MUST_PASS) {
    return cells[declinatory_neibs[std::rand() % declinatory_neibs.size()]]
  }
 
  return NULL;
}
 
static void do_stuff(const t_cell* const cell) {
  if (not cell->charged or cell->just_received) {
    return;
  }
 
  const t_neibs accepting_neibs = std::copy_if(
      cell->neibs.begin(), cell->neibs.end(), [&](const t_neib& neib) -> bool {
        const t_cell* const neib_cell(cells[neib]);
        return neib_cell->rp == RP_PASS_WANTED;
      });
 
  const t_neibs declinatory_neibs = std::copy_if(
      cell->neibs.begin(), cell->neibs.end(), [&](const t_neib& neib) -> bool {
        const t_cell* const neib_cell(cells[neib]);
        return neib_cell->rp != RP_PASS_WANTED;
      });
 
  const t_cell* const receiver =
      find_receiver(cell, accepting_neibs, declinatory_neibs);
 
  cell->pass_charge_to(receiver);
}
 
bool __fastcall TForm1::engine_make_step(void) {
  if (check_condition()) {
    return false;
  }
 
  for (const auto& item : cells) {
    t_cell* cell = item.second;
    do_stuff(cell);
  }
 
  recalc_priorities();
 
  return true;
}
Добавлено через 2 минуты
И еще все вызовы copy_if и любых других сложных конструкций для читаемости можно обернуть в функции с человекопонятным названием.
3
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.01.2015, 11:16
По мне так вполне нормальный код. На четверку (по пятибальной шкале).

Замечания:

* строки 28-35 явно перегружены. Разгрузить for и будет ок.

* закомментированные строки (26, 54, 60, 64) вызывают желание найти
разработчика и, тряхнув его как следует, спросить: нафига ? что здесь было ?
почему закомментил ? почему просто не стер ? И т.д. Короче, такие вещи или
снабжать TODO-комментами, или сразу затирать, чтобы не вносить неясность.

*
C++
1
if ( it->second->charged && it->second->gp == GP_MUST_PASS )
"gp" - да, такое короткое и такое сразу всем понятное имя.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.01.2015, 11:35
Цитата Сообщение от BRcr Посмотреть сообщение
Небезызвестный товарищ Avazart имел удовольствие мне намекнуть на, прости хоспаде, говнокодность стиля моего
Если я правильно понял постановку задачи, то оценить требуется не форматирование текста программы (расстановку пробелов, фигурных скобок и т.п.), что сделали некоторые отписавшиеся, а оценить читабельность/понимаемость кода и подхода к программированию вообще (факториал можно вычилсить через рекурсию, а можно и через цикл).

Например, вместо:

C++
return cells[accepting_neibs[std::rand() % accepting_neibs.size()]];
как бы более удобным было бы:

C++
r = gen_random (accepting_neibs.size());
a = accepting_neibs[r];
return cells[a];
и т.п.
1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
25.01.2015, 15:09
Цитата Сообщение от 0x10 Посмотреть сообщение
1. В теле метода check_condition страшный цикл с итераторами заменяется на return find_if(...) == cells.end();
И чем это лучше? К тому же это уже алгоритм, а не стиль.
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.01.2015, 15:26
Цитата Сообщение от taras atavin Посмотреть сообщение
И чем это лучше? К тому же это уже алгоритм, а не стиль.
Есть стандартные алгоритмы, реализующие распространенные действия. Их грамотное использование позволяет писать простой для разработчика, более высокоуровневый код. В данном случае отсутствует громоздкий оператор цикла и вложенный блок с условием — этот паттерн реализован в стандартной библиотеке, отлажен, понятен и привычен разработчикам, следовательно его нужно использовать.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
25.01.2015, 15:28
Цитата Сообщение от 0x10 Посмотреть сообщение
Их грамотное использование позволяет писать простой для разработчика,
И в чём же здесь упрощение? Наоборот, было просто, стало чуть сложнее.

Добавлено через 28 секунд
Цитата Сообщение от 0x10 Посмотреть сообщение
более высокоуровневый код.
Ну и где там изменение уровня? Метод что делал, то и продолжает, вызывается тем же синтаксисом и в тех же местах. Ничего вообще не меняется кроме лишнего вызова.
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.01.2015, 15:30
Не хочу продолжать этот спор.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
25.01.2015, 15:31
Слив защитан.
0
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.01.2015, 15:36
Да как угодно.
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
25.01.2015, 22:49
Цитата Сообщение от BRcr Посмотреть сообщение
TForm1
Дальше не читал, как говорится, nuff said

Добавлено через 12 минут
Цитата Сообщение от taras atavin Посмотреть сообщение
И в чём же здесь упрощение? Наоборот, было просто, стало чуть сложнее.
Только для неосиляторов. Знать стандартные алгоритмы? Не-е, конечно же лучше на пустом месте засандалить новую функцию и впихнуть туда тупой цикл. Helloworld'щикам никак в голову похоже не придет мысль о том, что одну строчку кода может и легче будет прочесть, но, никак не легче, а гораздо сложнее будет прочесть целый кусок кода состоящего из таких вот "простых" строчек.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
26.01.2015, 13:43
Цитата Сообщение от Voivoid Посмотреть сообщение
Только для неосиляторов. Знать стандартные алгоритмы?
При чём здесь неосиляторы? Для меня и без знания не проблема догадаться, что делает find. Но и прочитать цикл тоже не проблема, если бы он был правильно оформлен. И проще этого цикла как раз уже некуда, его не надо ни зубрить, ни знать ещё один язык, причём, не программирования, а общения, достаточно знать операторы. Причём, операторы то ты будешь юзать всегда и везде и знать обязан, а find только для поиска и подробности его применения быстро подзабудещь, из-за чего переврёшь. Возможность же допустить ошибку появляется при усложнении, при упрощении она может разве что исчезнуть.

Добавлено через 3 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
Не-е, конечно же лучше на пустом месте засандалить новую функцию и впихнуть туда тупой цикл.
Функция то остаётся, но у Вас она становится ещё и оболочечной, а оболочечные функции на пустом месте - это как раз и есть самое наглядное пособие, как делать не надо. Уж заменил бы уж тогда все вызовы метода вызовами фаинда что ли.

Добавлено через 6 минут
Оболочечный бред хорош ровно в двух случаях:
1. Когда надо реализация сделана в dll, а нужен синтаксис метода.
2. Если надо быстро перешить большой исходник на другой прототип вызываемой функции с другими параметрами.
В остальных случаях единственный их эффект - добавление лишнего вызова в цепочку. Задача израсходовать стек решается проще, эффективней и вообще не стоит.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
26.01.2015, 14:38
Эйси. Название формы бессмысленно и чревато забывчивостью.
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
26.01.2015, 15:01
Честно сказать я иной раз вздрагиваю, видя как ты заполняешь шапку цикла. Унификация это конечно хорошо, но не в угоду читаемости же. Если привыкнуть, то конечно ничего страшного. Но у меня стек в голове переполняется, когда пытаюсь вот так с размаху скобки в цикле поглядеть:
C++
1
2
3
4
for ( int diagonal( 0 ); diagonal < arr_size; ++diagonal )
{
    for ( int row( 0 ), col( diagonal ), value( diagonal + 1 ); col < arr_size; ++row, ++col )
    {
Не надеяться на вот эту мелкую оптимизацию компилятора это все конечно хорошо, но инициализация простых типов с помощью присваивания на мой взгляд привычнее и беглочитабельне смотрится.

Про пробелы при скобках
Что же касается скобочки при for, при if, при функции любой в общем случае, то тут несколько вариантов визуального выделения на выбор:
C++
1
for( ... // Хорошо просматриваются параметры
C++
2
for (... // Хорошо видно, что это цикл (имя функции)
C++
3
for(... // Все плохо
C++
4
for ( ... // Избыточно
Лично мне более по душе первый вариант так как, к примеру, если описать подряд с десяток прототипов функций, то будет гораздо приятнее читать. Для сравнения:
C++
1
2
3
4
5
6
7
8
9
10
11
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall FormClick(TObject *Sender);
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
        void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose);
        void __fastcall FormDestroy(TObject *Sender);
        void __fastcall FormDblClick(TObject *Sender);
        void __fastcall FormCreate(TObject *Sender);
        void __fastcall FormKeyPress(TObject *Sender, char &Key);
        void __fastcall FormPaint(TObject *Sender);
        void __fastcall FormResize(TObject *Sender);
        void __fastcall FormShow(TObject *Sender);
C++
1
2
3
4
5
6
7
8
9
10
11
        void __fastcall Button1Click( TObject *Sender );
        void __fastcall FormClick( TObject *Sender );
        void __fastcall FormClose( TObject *Sender, TCloseAction &Action );
        void __fastcall FormCloseQuery( TObject *Sender, bool &CanClose );
        void __fastcall FormDestroy( TObject *Sender );
        void __fastcall FormDblClick( TObject *Sender );
        void __fastcall FormCreate( TObject *Sender );
        void __fastcall FormKeyPress( TObject *Sender, char &Key );
        void __fastcall FormPaint( TObject *Sender );
        void __fastcall FormResize( TObject *Sender );
        void __fastcall FormShow( TObject *Sender );
Что до тела функции, до фигурных скобок, то тут действительно дело привычки. Мне привычнее такая вот запись:
C++
1
2
3
4
void foo()
  { // Пустая строка, плюс отступ слева
  // Начало кода
  }
Пустая строка, содержащая одну лишь скобочку безусловно увеличит длину кода суммарно, но и сильно повысит читабельность.


Про пустые круглые скобки (.size() .end()...), то тут пробел на мой взгляд не нужен. Полезной нагрузки он не несет, а вот наоборот заставляет глаз за него цепляться, а это сто лет не надо.


Про указатель и разыменовывание
Опять же несколько вариантов расположения вчастности звездочки. Но в единственном числе сильно не принципиально где она будет расположена, а вот уже когда несколько в ряд идет объявлений тех же указателей, то разница ощущается:
C++
1
int* pi1,* pi2,* pi3,* pi4,* pi5; // По левой стороне
C++
2
int *pi1, *pi2, *pi3, *pi4, *pi5; // По правой
C++
3
int * pi1, * pi2, * pi3, * pi4, * pi5; // По центру
C++
4
int*pi1,*pi2,*pi3,*pi4,*pi5; // Вприлипочку
Лично мне кажется, что второй вариант самый хороший. Сразу понятно, что звездочка относится именно к переменной.
Сложно, к примеру, неверно прочесть вот такую запись:
C++
some_type *pst, st;
А вот в такой уже можно подумать, что обе переменные имеют тип указатель:
C++
some_type* pst, st;
Вот что это (из первого поста):
C++
32
t_cell * cell( it->second );
? Умножение?


Итог: вцелом все замечательно, но инициализация без оператора равно вырывает глаза.
1
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
26.01.2015, 15:05
Цитата Сообщение от Ev_Hyper Посмотреть сообщение
BRcr, я бы переписал 1 функцию в таком оформлении:
Стив Макконнелл в своём "Совершенный код" не одобряет.

Цитата Сообщение от taras atavin Посмотреть сообщение
Да, дряной стиль.
Это не стиль. Это оптимизация по созданию временных объектов. Встречается в книгах C++ In-Depth.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.01.2015, 15:05
Помогаю со студенческими работами здесь

оценка кода
Дайте оценку моему коду (https://onlinegdb.com/r1i-i8Cqm), укажите на ошибки

Оценка кода
Суть задачи описал вначале кода, хотелось бы услышать, что можно было сделать лучше, где можно было бы написать/описать...

Оценка кода динамического двумерного массива
Доброго времени суток. Прошу оценить правильность выделения и удаления памяти, а также заполнения массива. Два примера. Вот первый. В...

Оценка стиля написания кода
Здравствуйте! Я к вам пожаловал не с очередной проблемой. Код у меня рабочий. Меня интересует то, насколько стандартен мой стиль...

Настройка стиля кода
Привык писать код в таком формате: class Man { public: Man(const QString &amp;name); private: QString _name; }; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru