Задать вопрос
  • ПК выключили под нагрузкой?

    @Mercury13
    Программист на «си с крестами» и не только
    Расскажу историю из своей жизни. Мэн тайком от мамы включал компьютер (ОС WinXP), однажды слышит — идёт мама, выключает, тот тормозит и ни в какую. Обесточивает — с винчестером что-то случилось. Вот только не помню, до какой степени: переразбивать или только переустанавливать.
    Вероятность аппаратной поломки крайне мала, но вот что бывает, если обесточить, когда комп шуршит винтом.

    UPD. Винчестер работает и поныне.
    Ответ написан
    Комментировать
  • Как добавить элементы в QStatusBar?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Подобных шероховатостей в Qt вагон и маленькая тележка. Не знаю, как статус-строка, но toolbar’ы (если они не состоят из одних кнопок, или если их много на одной форме) приходится собирать программно.
    2. Нельзя. Нам нужен конструктор конкретного типа — QLabel, а значит, нам нужен хедер, где этот конструктор есть.
    3. Понимайте, что даже если редактор форм идеальный, как в Embarcadero, найдутся задачи, которых он не выполняет. Это может быть хитрое поведение при изменении размеров формы, запросы компонентам «погоди обновлять меня» и «всё, теперь можно», настройки внешнего вида и многое-многое другое… Разделение кода и графики надо производить отделением в другой модуль рабочего кода, а не отделением графики в файл *.ui (или *.dfm).
    Ответ написан
    3 комментария
  • Как узнать время выполнения сортировки в C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Используйте либо time.h из Си, либо std::chrono из Си++11. Вот пример по второму.
    #include <iostream>
    #include <chrono>
    
    int main()
    {
        using Time = std::chrono::time_point<std::chrono::high_resolution_clock>;
        using Diff = std::chrono::milliseconds;
    
        Time t1 = std::chrono::high_resolution_clock::now();
        int i;
        std::cin >> i;
        Time t2 = std::chrono::high_resolution_clock::now();
        Diff diff = std::chrono::duration_cast<Diff>(t2 - t1);
        std::cout << diff.count() << " ms" << std::endl;
        return 0;
    }
    Ответ написан
    Комментировать
  • Как вытянуть одномерный массив Arr[j] с функции min и отсортировать его в функции quicksort?

    @Mercury13
    Программист на «си с крестами» и не только
    double* min(double **Arr, int SizeArr) {
       // Всё оставь как есть, убери вывод   
       return MinArr;
    }

    Ну и не забудь уничтожить результат функции min где-то ниже по коду. «Си с крестами» сам ничего созданного через new не уничтожит.
    Ответ написан
    1 комментарий
  • Как работать с двусвязными списками в delphi?

    @Mercury13
    Программист на «си с крестами» и не только
    В Delphi языком записей — в точности так же.
    Языком классов…
    type  
      TCell = class
       public
        info: TReki; 
        next, previous: TCell;
      end; 
      TList = TCell;
      TPosition = TCell;

    Да, об именовании типов. В Си мы пишем Cell cell, а в Паскале cell : Cell нельзя, он регистронезависимый. Общепринято, что тип начинается на T, указатель — на P. Иногда добавляют другие префиксы (event — Ev, dynamic array —Da), но типы без префикса — плохой тон.
    Ответ написан
  • Как работать с bmp?

    @Mercury13
    Программист на «си с крестами» и не только
    Открыть как картинку: Lister из Total Commander, любой продвинутый просмотрщик картинок (XnView, FastStone…), любой нормальный графический редактор (Paint.NET, GIMP, PhotoShop…)

    Увидеть внутреннее устройство: любой HEX-просмотрщик (проще всего Lister из Total Commander) или HEX-редактор. К сожалению, текстовым редактором двоичный файл лучше не открывать, файл может необратимо испортиться.

    Работать программно: насколько мне известно, поддерживает Qt.
    Если именно на Си — https://sourceforge.net/projects/libimage/

    Написать поддержку самому: достаточно качественное описание есть ан англовике: https://en.wikipedia.org/wiki/BMP_file_format
    Также вот несколько готовых структур: jenyay.net/Programming/Bmp paulbourke.net/dataformats/bmp
    Вот пример самодельной поддержки BMP для OpenGL: paulbourke.net/dataformats/bmp/BITMAP.C
    Ответ написан
    1 комментарий
  • Объединение пересекающихся периодов?

    @Mercury13
    Программист на «си с крестами» и не только
    отсортировать массив по start
    текКонец := −∞   // или, например, ⌀ или 0000-01-01
    текИндекс := −1
    для v : массив
      если v.start > текКонец
        текИндекс += 1
      результат[текИндекс].приклеить(v)
      текКонец := макс(текКонец, v.end)


    Если же нужно объединять прямо на ходу…
    отсортировать массив по start
    текКонец := −∞   // или, например, ⌀ или 0000-01-01
    текИндекс := −1
    для v : массив
      если v.start > текКонец
        текИндекс += 1
        результат[текИндекс] := v
      иначе
        результат[текИндекс] := объединить(результат[текИндекс], v)
      текКонец := макс(текКонец, v.end)


    Разумеется, я тут опустил вопросы, связанные с датами-строками и их сравнением. Но вам их придётся решить.
    Изначально считается, что везде end > start. Если не так — данные некорректные и с этим придётся что-то делать.
    Также считается, что массив «результат» ассоциативный (как в PHP).
    Ответ написан
  • Почему деструктор выполняется раньше конструктора копирования?

    @Mercury13
    Программист на «си с крестами» и не только
    По крайней мере у меня G++ выдал предупреждение вот тут:
    List<size_t>& newList(size_t a) {
        	List<size_t> result;
        	result.pushBack(a);
        	return result;
        }

    C:\TestApps\ListTest\main.cpp | 118 | warning: reference to local variable 'result' returned [-Wreturn-local-addr]
    Понятно?

    Что изменить…
    1. Изменить сигнатуру на…
    List<size_t> newList(size_t a) {
    2. Поработать с временными ссылками Си++11. Добавить две функции.
    List(List<T>&& other);
    List<T>& operator = (List<T>&& other);

    Два амперсанда — это не ссылка на ссылку (понятие «ссылка» идемпотентно), а новая вещь Си++11 — ссылка на временный объект. Она говорит: объект идёт на заклание, из него можно выпотрошить все данные.
    3. Насчёт обычной операции присваивания — её можно или реализовать, или =delete (тоже нововведение Си++11).
    4. UPD. Проглючил, но да, верно. Обычный конструктор копирования должен иметь параметр const!
    Ответ написан
    Комментировать
  • Как исправить конфликт заголовочных файлов?

    @Mercury13
    Программист на «си с крестами» и не только
    Да тут у нас циклическая зависимость по интерфейсам! Такого не потерпит ни один язык, и Си тоже.
    Если в трёх модулях есть какие-то общие типы, их обычно выносят в отдельный хедер с названием вроде «MyUnitDefines.h».

    Как это выглядит технически? Пусть Unit3 описывает переменную extern Type1 var3;
    // Начало Unit1
    // Начало Unit2
    // Начало Unit3
    // Начало Unit1
       // Поскольку сработала защита от двойного включения, второго включения не было.
       // Так что кода typedef int Type1; к сожалению, йок.
    // Конец Unit1
    
    extern Type1 var3;    // Type1, естественно, не определён. 
                          // Си (как минимум старые редакции) это понимает как extern int Type1 var3.
    // Конец Unit3
    // Конец Unit2
    
    // Определение стоит ниже по коду, но это ПЕРВОЕ включение.
    typedef int Type1;
    // Конец Unit1

    (Да, препроцессор тупо копипастит код и не больше.)

    Циклическую зависимость по реализациям (то есть в C-файлах) большинство языков терпят. И Си тоже.
    Ответ написан
    Комментировать
  • Как синхронизируются потоки на низком уровне?

    @Mercury13
    Программист на «си с крестами» и не только
    Этого мало.
    Первое. Нужны особые операции, которые гарантированно выполняются атомарно. Например (из исходников Delphi)
    function InterlockedAdd(var Addend: Integer; Increment: Integer): Integer;
    asm
          MOV   ECX,EAX
          MOV   EAX,EDX
     LOCK XADD  [ECX],EAX
          ADD   EAX,EDX
    end;

    Здесь префикс LOCK (блокирование шины) и даёт атомарность. Также используют операцию XCHG (exchange) — единственная атомарная без префикса LOCK.

    На основе этого можно устроить объект, который называется spinlock. Крутим цикл, пока система не скажет: свободно. Из Википедии.
    mov eax, spinlock_address
    mov ebx, SPINLOCK_BUSY
    
    wait_cycle:
    xchg [eax], ebx  ; xchg - единственная инструкция, являющаяся атомарной без префикса lock
    cmp ebx, SPINLOCK_FREE
    jnz wait_cycle
    
    ; < критическая секция захвачена данным потоком, здесь идёт работа с разделяемым ресурсом >
    
    mov eax, spinlock_address
    mov ebx, SPINLOCK_FREE
    xchg [eax], ebx  ; используется xchg для атомарного изменения
    ; последние 3 инструкции лучше заменить на mov [spinlock_address], SPINLOCK_FREE -
    ; это увеличит скорость за счёт отсутствия лишней блокировки шины, а mov и так выполнится атомарно
    ; (но только если адрес spinlock_address выровнен по границе двойного слова)


    От спинлока до настоящего мьютекса остаётся один небольшой шаг. Спинлок потребляет ресурс процессора, не производя полезной работы. После того, как спинлок проработал несколько микросекунд и не освободился, мы говорим: не судьба — и передаём работу другому процессу. Надеюсь, вы в своей мини-ОС как-то научились переключать процессы.

    В однопроцессорном ядре никаких спинлоков нет. Если надо захватить ресурс, а он чей-то — сразу отдаём управление другому.

    UPD1. Почему не сразу отдавать работу другому процессу. Хороший тон — защищать мьютексом не системные вызовы (которые действительно долги) а какие-нибудь структуры данных вроде связных списков и атомарных struct. Так что вероятность, что объект просидит занятым долго, крайне мала. В настоящем мьютексе есть очередь с приоритетом, которая защищается, как ни странно, спинлоком. И этого достаточно.
    Ответ написан
    2 комментария
  • Как работает генератор случайных чисел?

    @Mercury13
    Программист на «си с крестами» и не только
    Рассказываю на пальцах.
    Компьютер запомнил число (или кучу чисел), которое называется «случайная затравка» (random seed).
    По команде «сгенерируй случайное число» он проводит два алгоритма.

    1. Собственно генератор случайных чисел — преобразование seed → seed.
    Например: seed := (37·seed + 234) mod 997.
    (знаком :=, как в Паскале, я обозначил «переприсвоить»)

    2. Интерпретация результатов: seed → Y*.
    Например, y = seed/997.
    Y — это [0…1), {1…6} или любое другое желаемое множество.
    Y* — множество конечных последовательностей: каждый бросок генератора может не дать ни одного числа (и потребуется переброс), одно число, два числа… Например, наиболее известный генератор нормально распределённых чисел каждым броском даёт или ноль чисел (т.е. нужен переброс), или сразу два.

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

    Если же нужны настоящие случайные числа, да в большом количестве — это откровенно тяжело. В ход идут…
    • таймеры и счётчики команд — ну, это понятно;
    • шум в звуковой плате;
    • задержки ввода с клавиатуры и мыши;
    • аппаратные датчики случайных чисел на диодном шуме, применяемые в некоторых процессорах.
    MacOS, например, этим добром не пользуется; и в dev/random, и в dev/urandom идёт один и тот же криптостойкий псевдослучайных генератор Ярроу.
    Ответ написан
    Комментировать
  • Как автоматически создать 100 папок и переместить в каждую по 10 картинок из общей папки?

    @Mercury13
    Программист на «си с крестами» и не только
    Берёшь любой язык программирования с достаточно мощной библиотекой и пишешь:

    целое iFile = 0
    строка sourcePath = добавитьРазделитель(общаяПапка)
    строка targetPath = ""
    для fname : перебор по файлам в sourcePath + '*'
      строка sourceName = sourcePath + fname
      если iFile % РАЗМЕРПАПКИ = 0
        строка targetFolder = добавитьРазделитель(целеваяПапка) + целоеВСтроку(iFile / РАЗМЕРПАПКИ)
        создатьНовуюПапку(targetFolder)
        targetPath = добавитьРазделитель(targetFolder)
      копироватьФайл(sourceName, targetPath + fname)
      удалитьФайл(sourceName)
      iFile = iFile + 1
    Ответ написан
    Комментировать
  • Как быть со слепой ветвью в TortoiseHg?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Нашёл решение.
    1. Перейти (update) на рабочую ветвь.
    2. Слить (merge) ветви, сказав: «Ignore changes from other branch» (или как там?)
    Ответ написан
    Комментировать
  • На чем лучше программировать для кроссплатформенности?

    @Mercury13
    Программист на «си с крестами» и не только
    Два вопроса.
    1. С чем имеет дело ваша программа/библиотека? Есть ли у неё что-то интересное сверх консоли — окна, сеть и прочее?
    2. Нужно ли, чтобы один и тот же пакет — физически один и тот же — работал под разными ОС?

    Минус-минус: это самое простое. Используйте хорошо заспецифицированный язык с реализациями под разные ОС вроде Си++, Java и Питона.
    Плюс-минус: используйте такой же язык, но с кроссплатформенным фреймворком. Я бы предложил фреймворк Qt и библиотеку Boost, хотя на каждом языке есть что-то своё.
    Минус-плюс: Используйте язык со стандартизированным промежуточным кодом вроде Java. Или Питон и JavaScript, исполняющие напрямую исходный текст.
    Плюс-плюс: Тут нужны и стандартизированный промежуточный код, и кроссплатформенный фреймворк. Поскольку часто этот фреймворк нужно отдельно качать в версии под нужную ОС — тут покатит Java и, возможно, Питон.
    Ответ написан
    2 комментария
  • Где и как хранится имя переменной?

    @Mercury13
    Программист на «си с крестами» и не только
    Для компилируемого языка (коим является Си) — в объектном файле (и будет выброшено, когда линкер соберёт EXE) и в отладочных данных. Больше нигде. Переменные различаем их адресом.
    Возьми DosBox, возьми старый добрый Turbo Assembler и собери какой-нибудь COM-файл (пускай даже по руководству). А затем возьми хакерский просмотрщик типа Hiew и посмотри дизассемблер того, что получилось. Почему COM — потому что устроен он просто.
    Ответ написан
    Комментировать
  • Как решить данную задачу?

    @Mercury13
    Программист на «си с крестами» и не только
    Задача сложна и требует серьёзного исследования. Дело тут в том, что второй эшелон — склад промежуточного хранения — добавляют, если затраты НЕлинейны и в больших объёмах развоз товара дешевле. Это, конечно, можно сымитировать более дешёвым завозом на склады. (А также чтобы разгрузить «мёртвые запасы» магазинов и законом больших чисел скомпенсировать случайные колебания спроса, но это, как я понял, не ваше дело.)

    У вас написано: «Стоимость доставки это расстояния между точками». Таким образом, стоимость доставки не зависит от объёма подвоза, а зависит только от расстояния? Тоже, так сказать, нелинейное поведение. Приближённое решение ищите в алгоритмах кластеризации: зона, охватываемая одним складом — и есть кластер. Если же нужно точнее, приходится использовать какие-нибудь эвристики.

    Например, расположим семь складов в каких-нибудь городах, вычислим вытекающую стоимость. А теперь вопрос: можно ли перенести какой-нибудь склад в соседний город, чтобы было дешевле? Итерационно работаем, пока не уляжемся в «оптимальное положение». Случайно набрасываем семь точек — и «скатываемся вниз», пока не успокоимся, и так много-много раз.

    Лучше выводить не одно решение, а несколько — например, до 120% от оптимального. Дело в том, что после компьютерного вычисления возникнут какие-то человеческие факторы: узнав, что восточный склад только в Комсомольске-на-Амуре, а северо-западный можно ставить где угодно в окрестностях Ленинграда, принимаем решение ставить склады в Комсомольске и недалеко от ленинградского метро.
    Ответ написан
    Комментировать
  • Как реализовать приближенный двоичный поиск?

    @Mercury13
    Программист на «си с крестами» и не только
    Алгоритм такой.
    1. Реализуй двоичный поиск с указанием места, куда вставить (см. Википедию).
    2. Если вставить до первой позиции или за последнюю — return соотв. первое или последнее число.
    3. В противном случае выяснить, какое ближе из (i−1)-го и i-го.

    Дома проверю, где там ошибка в двоичном поиске, в нём любят ошибаться.

    К тому же код у вас чисто олимпиадный, я бы отделил рабочую логику от генерации выходного файла.
    Ответ написан
  • Как хапустить exe в веб брвузере?

    @Mercury13
    Программист на «си с крестами» и не только
    На клиенте — как уже было сказано, это невозможно. Производители браузеров затягивают и затягивают гайки, чтобы даже плагины неугодные не работали, давая попущение только Флэшу. Что уж говорить про машинный код.
    Но существует несколько обходов.
    Первый применён в службе GoToMeeting. Без программы под вашу ОС не обойтись, но по обычной HTTP-ссылке запускается эта программа. Как технически — не исследовал.
    Второй обход. Существуют службы, которые запускают EXE на своих виртуальных машинах и транслируют наружу результат. Спрошу у босса, какой пользуемся конкретно мы.
    Третий — часто в браузере делают игры для DOS и старых приставок через эмулятор, написанный на Java.
    Ответ написан
    1 комментарий
  • Как задать в Windows 10 цвет плитки по умолчанию?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    А я нашёл.
    https://msdn.microsoft.com/en-us/library/windows/a...

    Вкратце. Создаём файл НазваниеПрограммы.VisualElementsManifest.xml с таким содержимым.
    <Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <VisualElements
            BackgroundColor="#000066"
    		ForegroundText="light" 
    		ShowNameOnSquare150x150Logo="on" />
    </Application>

    Этого мне хватило. Если нужны ещё и большие иконки — см. по ссылке.
    Ответ написан
    Комментировать
  • Как сравнивать значения строки в структуре на языке С++?

    @Mercury13
    Программист на «си с крестами» и не только
    1. У вас неверное условие (z[i].birth >= ageyoungest).
    2. Никакой защиты от переполнения буфера в scanf.
    3. Идентификатор birth реально означает возраст. Плохо.
    4. Неверное условие
    if (z[i].education == "master" || z[i].education == "specialist" || z[i].education == "bachelor")
    . Для массивов это просто сравнение адреса массива с адресом вкомпилированной в программу строчки, что автоматически даёт false. Используйте str(n)cmp.
    5. Излишнее условие
    else if (z[i].education != "master" || z[i].education != "specialist" || z[i].education != "bachelor")
    . Оно автоматически выполнено.
    6. Отсутствует delete[] employees;
    Ответ написан
    Комментировать