Задать вопрос
Ответы пользователя по тегу Программирование
  • Существуют ли эталонно красиво написанные программы?

    @res2001
    Developer, ex-admin
    Код должен решать определенную задачу. Читать абстрактный код без понимания сути решаемой им задачи - бессмысленное занятие. Т.е. вы должны сначала вникнуть в задачу и хотя бы в черне представить как бы вы ее решали. В этом случае, читая код, уже можно оценивать те приемы, которые там применены.
    У меня сложилась такая практика: когда мне требуется использовать библиотеку, в которой реализован нужный мне функционал (т.е. я изначально уже знаю какую задачу должна решать библиотека), я сначала читаю обзорно документацию на нее, потом лезу в исходники и смотрю как оно там все устроено. Некоторые библиотеки после такого анализа отбраковываются, из других можно вынести для себя что-то полезное, но в любом случае начинаешь лучше понимать как работает библиотека.
    На изучение кода толстых библиотек может уйти много времени, поэтому смотрю только какую-то небольшую часть, которая нужна в данном конкретном случае.
    Многие просмотренные мной библиотеки написаны не плохо с моей точки зрения, но на сколько они "эталонно красивы" судить не берусь.
    В целом считаю, что читать чужой код - полезный навык. Но все таки умение программировать самому еще более полезный. Поэтому надо правильно расставить приоритеты.
    Ответ написан
    Комментировать
  • Что такое уровни абстракции в книге 'Чистый код' Мартина?

    @res2001
    Developer, ex-admin
    А мне это вообще не очевидно, ведь тут подразумевается, что в методе несколько уровней абстракции

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

    Для данного примера очевидно, что "более одной операции" - это расчет выплат для разных типов сотрудников.
    А раз разные типы, то значит в этом методе, по мнению автора, не хватает абстракций для типов сотрудников.
    Об этом же говорит и способ решения проблемы, предлагаемый автором в следующем листинге - он предлагает применить полиморфизм, т.е. создать иерархию классов по типам сотрудников, которые будут наследоваться от абстрактного класса Employee и сделать "абстрактную фабрику", которая будет создавать объект нужного класса сотрудника в зависимости от переданного типа сотрудника. Тогда каждый дочерний класс сотрудника будет переопределять свой метод calculatePay только для своего типа. Вышестоящий код благодаря полиморфизму получит правильный расчет выплат для данного сотрудника без switch.
    Точнее в решении switch остается, но на уровне абстрактной фабрики, когда делается выбор какой объект сотрудника надо создавать. И это единственное место, где будет такой switch. Если же не использовать полиморфизм, то потенциально может существовать множество мест, где понадобится использовать switch по типам сотрудников.
    Ответ написан
    Комментировать
  • С++ На всех ли платформах одинаковая точность операций с float?

    @res2001
    Developer, ex-admin
    Форматы чисел с плавающей точкой стандартизованы IEEE754.
    Скорее всего, операции выполняемые процессором над числами с плавающей точкой будут давать одинаковый результат на разных платформах.
    Но вот программные реализации различных математических алгоритмов из стандартной библиотеки, типа того же sqrt и т.п., могут отличаться.
    Для гарантии, вам нужно использовать для этих целей какую-то единую библиотеку для всех платформ, а не стандартный math.h.
    Ответ написан
    1 комментарий
  • Чем меньше символов, пробелов и пропусков в коде, тем лучше?

    @res2001
    Developer, ex-admin
    Исходные коды программы пишут для людей, которые потом будут ее сопровождать, а вовсе не для компьютера/компилятора.
    Все эти пробелы, пустые строки, короткие имена никак не влияют на производительность программы, но зато очень сильно влияют читабельность, а следовательно и на сопровождаемость. Пишите так, что бы коллеги легко понимали вашу программу.
    Ответ написан
    Комментировать
  • В чем смысл do while? Как его можно использовать?

    @res2001
    Developer, ex-admin
    Например, функции ввода/вывода в POSIX возвращают EINTR, если во время их работы в приложение пришел сигнал.
    Сигнал вы можете перехватить, обработать и можно продолжать дальше. Но функция (например write) вернет EINTR. Если эту ситуацию не обрабатывать отдельно, то это может вызвать, например, завершение приложения (из-за ошибки ввода/вывода), тогда как приложение могло бы дальше работать.
    В этом случае удобно вызов функции заключать в do while:
    int ret;
    do {
      ret = write(...);
    } while(ret == EINTR);

    Это один из вариантов, когда надо выполнить действие, и по результатам действия будет понятно надо ли еще раз его запустить или уже достаточно.
    В этот же цикл можно добавить и другой функционал.
    В случае неблокируемых операций ввода/вывода операция может завершится не записав или не прочитав все что нужно или вообще вернуть EAGAIN, если ничего нет. Можно эти проверки добавить в этот же цикл do while вместе с проверкой на EINTR.
    Вариантов использования, на самом деле много. Вы это увидите, когда столкнетесь с таким вариантом в своей практике.

    Но самый популярный вариант у Си программистов, это использование в макросах:
    #define MACRO(x)      do { тут что-то делаем } while(0)

    Этот фиктивный цикл служит двум целям:
    1. внутри цикла можно объявлять локальные переменные, которые не будут видны вне цикла
    2. При использовании макроса можно в конце ставить точку с запятой, не нарываясь на предупреждения компилятора: MACRO(val);. Компилятор в итоге уберет цикл, но все побочные эффекты сохранятся.
    В плюсах этот вариант практически не используется, т.к. тут есть шаблоны и т.п. и от макросов в основном отказываются. Но в Си макросы вполне актуальный инструмент.

    Но циклы for и while применяются чаще, чем do while.
    Ответ написан
    Комментировать
  • Что нужно исправить в кодее сортировки merge, чтобы она правильно работала?

    @res2001
    Developer, ex-admin
    Может быть потому, что массивы в С/С++ индексируются, начиная с нуля, следовательно последний элемент будет иметь индекс (n-1), т.е. 50. А вы передаете в merge_sort в качестве right значение 51. Так что у вас выход за пределы массива. Так же вы используете начальное значение для left = 1, таким образом вы не обрабатываете 0 элемент массива.

    Кроме того. Заверните ваш код в тег code (кнопка </> на панели инструментов) и верните все отступы - код не возможно читать.
    Ответ написан
    Комментировать
  • Какой компьютер выбрать для программирования?

    @res2001
    Developer, ex-admin
    1. Как уже писали, для программирования много не надо. Но когда комп начинает тормозить в не подходящий момент - это не приятно.
    2. Ноутбук или стационарный ПК надо выбирать исходя из того как вы пользуетесь им. Если он все время на одном месте - то смысла в ноуте нет.
    3. Учтите, что стационарный выйдет дешевле при тех же характеристиках.

    Я недавно обновил свой ноут. У меня вопроса не стояло ноут или ПК, т.к. регулярно бываю на выезде, хотя основное время - дома на удаленке.
    Взял Lenovo Legion 5. Доволен как слон :-)
    У Леново есть еще хорошие варианты в рамках линеек ThinkPad T/P/X. В каждой линейке несколько моделей. Пишут, что thinkpadы сертифицируются для пентагона, так что там качество на высоте должно быть.

    Если все таки остановитесь на ноуте, обращайте внимание на то, что в некоторых моделях память распаяна на материнке и заменить (увеличить) ее практически не реально. Так же есть смысл смотреть на наличие дополнительного слота для SSD. Ну и наличие необходимых внешних интерфейсов то же может быть важным вопросом. Если подключаете внешние мониторы, то смотрите, чтоб были разъемы в нужном количестве и нужного типа.
    Обычно, можно купить ноут с небольшим SSD и количеством памяти и сразу проапгрейдить его, возможно будет дешевле, чем сразу покупать ноут с необходимым размером SSD и памяти. На процессоре экономить не стоит.
    На озоне сейчас есть наши продавцы, которые возят из китая. Доставка долгая - 1-1.5 месяца. Но сильно дешевле, чем брать там где "в наличии". Растаможка уже включена в стоимость. У продаванов из Китая растаможка, скорее всего, не включена, поэтому у них ценник будет еще ниже, но он, с большой вероятностью, не окончательный.
    Ответ написан
    1 комментарий
  • Как посчитать количество символов в char на С?

    @res2001
    Developer, ex-admin
    Конкретно для приведенного примера можно делать так: (sizeof(text) - 1)
    Это будет работать только в подобных случаях, когда text - это статический/автоматический массив фиксированного размера (как в данном примере). -1 требуется, чтоб удалить завершающий нулевой символ.
    Преимущество перед strlen в том, что sizeof вычисляется на этапе компиляции, т.е. по факту в коде вместо этого выражения будет константа 14, вычисленная компилятором.
    Кстати, можно делать еще так: sizeof("Literal string") - 1

    Если text будет определена по другому, например char *text = "Literal string";, то такой подход уже не прокатит.
    Универсальный вариант, который будет работать для всех случаев однобайтной строки с завершающим нулем - использовать strlen.
    Ответ написан
    Комментировать
  • Указываются ли комментарии в листинге кода?

    @res2001
    Developer, ex-admin
    В исходники смотрят люди, которые могут понять код. Соответственно комментарии в коде пишутся для них, т.е. для программистов. А раз человек может прочитать код, то проще всего написать код так, что бы он был достаточно прост для понимания читающего. Тут включаются стандартные правила об именовании переменных, стилю написания кода, KISS и т.д. и т.п.
    В реальности комментарии необходимы только для не тривиальных, трудных для понимания частей кода, где используется какой-то хитрый алгоритм или не очевидный хак.
    Если вы будете использовать систему авто-генерации документации, то тут уже придется писать комментарии к каждой сущности в коде по правилам этой системы и программист заодно становится и тех.писателем.
    Ответ написан
    Комментировать
  • Как реализовать дерево на основе связного списка?

    @res2001
    Developer, ex-admin
    Дерево на основе связного списка это вообще первое что приходит в голову, когда думаешь, как реализовывать дерево. Правда это не обычный последовательный связный список, а иерархический.
    Ответ написан
  • Почему одни языки быстрее, другие медленнее, и почему новички гуглят самый быстрый язык, а не самый медленный?

    @res2001
    Developer, ex-admin
    Если говорить о скорости, то компилируемые языки всегда будут быстрее интерпретируемых. Просто из-за разных принципов выполнения программы.
    Есть еще языки с JIT компиляцией, типа Java, C# и т.п.
    Они могут быть быстрее компилируемых в каких-то случаях, т.к. они точно знают на каком процессоре работают в каждом конкретном случае и могут максимально использовать возможности текущего процессора для оптимизации кода.
    В компилируемых языках, как правило, программист собирает программу под некоторую абстрактную архитектуру, например под x64, но у конкретного процессора, на котором будет выполнятся программа могут быть какие-то расширенные возможности, о которых программист (компилятор) не знает во время компиляции (или решает не использовать их для универсальности). При этом JIT компилятор может использовать эти расширенные возможности и добьется лучшей производительности.
    Но если поставить в одинаковые условия компилируемые языки и языки с JIT компиляцией, то, думаю, результат будет то же в пользу компилируемых языков. Но в реальности такое (заранее известные условия исполнения для компилируемого кода) встречается не часто.

    К слову, в том же питоне (интерпретируемый язык), например, модули для математических вычислений (numpy, scipy, ...) написаны на компилируемых языках (C/C++), поэтому они работают быстрее, чем аналогичный код на питоне без использования этих модулей. Да и сам интерпретатор питона написан на компилируемом языке :)

    Скорость не единственный критерий для ЯП. Имеет значение и скорость разработки конкретной задачи и поддержка каких-то возможностей и т.д. и т.п.

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

    Практически все задачи можно решить почти на любом ЯП, но есть ЯП, которые хорошо подходят для решения задачи, а есть те, что не очень. В общем, подбирайте язык под задачу.
    Например, если вы работаете в вебе, то это JS, php, python, java, C# и еще пачка других
    Если это десктоп приложение с GUI, то: Java, C# может быть С++
    Если это встраиваемая техника и реальное время, ядро ОС или драйверы: C/C++
    Если это ИИ, компьютерное зрение и т.п. computer science: python, R, что-то еще
    Ответ написан
    Комментировать
  • Что означает память с явными адресами?

    @res2001
    Developer, ex-admin
    Отображение - видимо применение функции типа mmap (линукс), в винде то же есть аналог.
    Явные адреса - имеется ввиду указание адреса в виде константы в коде. Такое применяется обычно для работы с железом. В прикладном софте в этом нет необходимости.
    Еще явные адреса могут указывать, когда пытаются что-то изменить в другом процессе. Например накрутить счетчик денег в игре :)
    Ответ написан
    Комментировать
  • Какие способы общения есть между серверным и клиентским приложением?

    @res2001
    Developer, ex-admin
    Общение по сети обычно идет через сокеты по TCP или UDP. Практически все API и протоколы более высокого уровня, используют этот транспорт.
    В винде можно использовать DCOM. Он, конечно, то же использует сокеты и TCP/IP, но это скрыто от программиста. Под никсами то же есть похожие механизмы RPC, но они не встроены в ОС.
    Ответ написан
  • Как лучше разместить в оперативной памяти массив комплексных чисел с точки зрения производительности?

    @res2001
    Developer, ex-admin
    Удобнее использовать массив структур:
    struct complex_t {
    float re, im;
    };

    Смысл тот же, что и в c[2*N], но пользоваться удобнее и читабельность кода повышается.
    Учтите, что операции над double обычно выполняются дольше, чем над float.
    Ответ написан
    Комментировать
  • Как быстро вникнуть в чужой код?

    @res2001
    Developer, ex-admin
    Чаще практиковаться в чтении чужого кода. Ревью хорошо помогают в этом, но и читать абсолютно посторонний код полезно.
    Это навык, его можно наработать, как и все остальное. В любом случае на это потребуется время.
    Прежде чем вникать в код большого проекта, следует изучить документацию, лучше, если это будет документация для программиста. Но и пользовательская документация сгодится, за неимением лучшего. При чтении документации пытайтесь представить, как бы вы это реализовывали (без деталей, только самые важные моменты). После документации в голове сложится картина возможной реализации кода и станет проще понимать сам код.
    Ответ написан
    2 комментария
  • Плохо ли иметь зависимости в проекте в виде исполняемых файлов в го и других языках?

    @res2001
    Developer, ex-admin
    А какая у вас альтернатива?
    Вы можете реализовать весь функционал в своей программе без использования внешнего ПО за вменяемое время?
    Если да - реализуйте, это, конечно, будет лучше.
    Но обычно подобный сложный функционал реализуется в динамических библиотеках. Программы, типа lowrite используют этот функционал. Вы то же можете использовать библиотеку, а не запускать внешнее ПО. Но это, конечно, гораздо сложнее и на это может уйти много времени.
    От установки .net вы можете отказаться, только используя ЯП не связанные с .net.
    lowrite возможно содержиться в других пакетах, более мелких, которые ставятся вместе с libre office, а библиотеки, которые он использует может находится в третьем пакете.
    Ответ написан
    Комментировать
  • Почему strcmp неправильно сравнивает кириллицу?

    @res2001
    Developer, ex-admin
    Все просто (сложно) - кодировка введенных символов не совпадает с кодировкой исходников программы.
    Вы видимо пишите консольную программу под виндой - тут это типичная проблема для новичков, т.к. в русской винде в консоли возможны 2 стандартные кодировки cp1251 и cp866, причем по умолчанию используется cp866 (по умолчанию - это когда вы просто запустите cmd.exe). Проверить текущую установленную кодировку консоли из самой консоли можно командой chcp, ею же можно и изменить кодировку.
    Кодировка исходников может быть вооще какой угодно, кроме вас ее никто не знает.

    Для простоты, чтобы у вас заработала программа перекодируйте исходники в cp866 и пересоберите ее.
    Но это будет работать лишь до той поры пока вы запускаете программу на русской винде и пока кодировка консоли в ней cp866.

    Нормальный подход в этом случае:
    1. писать исходники в UTF8,
    2. узнать текущую кодировку консоли,
    3. перед выводом любого текста перекодировать текст из UTF8 в кодировку консоли,
    4. при вводе текста с консоли перекодировать из кодировки консоли в UTF8, и только после этого с текстом можно совершать какие-то действия, например strcmp().
    5. в коде для хранения строк использовать wchar_t и wstring, а не char и string.
    Ответ написан
    1 комментарий
  • В чем разница между ооп с классами и без классов?

    @res2001
    Developer, ex-admin
    Без классов можно говорить только о некотором стиле программирования похожем на ООП. Это не будет полноценный ООП. В ООП компилятор многие вещи делает сам, в процедурном языке вам придется эти вещи реализовывать руками, например наследование. Так же хватает других ограничений накладываемых процедурными языками, например в Си нет перегрузки операций как С++, поэтому писать на Си в ООП стиле придется без них и т.д. и т.п.
    В ранних версиях С++ был чем-то вроде препроцессора для Си компилятора. Так что ничего не возможного нет. Полноценная реализация на процедурном языке ООП слишком затратное занятие, имеет смысл только в каких-то экспериментальных целях или для изучения.
    Ответ написан
  • В чем суть процедурного программирования?

    @res2001
    Developer, ex-admin
    Можно запросто писать в ООП стиле на процедурном языке. Плюшек в виде готовых конструкций, конечно нет и кода будет больше, чем то же самое реализованное на ООП ЯП. Но это не значит, что код будет медленнее или менее эффективен, просто в ООП язык программирования (компилятор) делает некоторую работу за вас, а в процедурном вы сами это делаете и этот факт увеличивает размер вашего кода.
    Вообще ООП вырос из процедурного стиля.
    Говоря о том, что многие проекты написаны в процедурном стиле, вы преувеличиваете важность "стиля". На самом деле многие проекты написаны на Си (процедурный стиль туда просто прикладывается как данность) и на то есть куча причин.
    Ответ написан
    Комментировать
  • Умножение вещественного числа на -1 происходит на общих основаниях, не быстрее, чем на произвольное число?

    @res2001
    Developer, ex-admin
    Потренируйтесь тут или тут.
    Можно просто инвертировать старший бит.
    Ответ написан
    Комментировать