Ответы пользователя по тегу Программирование
  • Как сделать и вывести срез строки(String) C/C++?

    @Mercury13
    Программист на «си с крестами» и не только
    1.
    std::cout << text.substr(начало, длина) << std::endl;

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

    2. Ничего, что, если строка не оканчивается точкой, последнее «недопредложение» выведено не будет? Может быть, так и верно, но если задача — разделить текст по tab’ам или запятым, надо после цикла выкинуть то, что осталось.
    Ответ написан
    Комментировать
  • Где располагаются переменные в данном случае (стэк, куча)?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы совершенно правы. Это массив из одного элемента, и при таком расположении он будет в стеке. Со всеми его полями: alloc, size и mp_d. При выходе из функции есть шансы, что он будет затёрт, и так действовать нельзя.

    Кто затрёт? Да кто угодно. Хоть драйвер, пожелавший воспользоваться твоим стеком. Хоть последующий вызов какой-нибудь функции.

    С другой стороны, на то и помечена структура __mpz_struct двумя подчерками, чтобы её не использовали.
    __mpz_struct* foo()
    {
        mpz_t var;
        return (__mpz_struct *)var;
    // C:\TestApps\RetLocal\main.cpp|15|warning: address of local variable 'var' returned [-Wreturn-local-addr]|
    }


    А так работает: всё в куче. Только не забывайте очищать через delete[].
    __mpz_struct* bar()
    {
        __mpz_struct* var = new mpz_t;
        return var;
    }
    Ответ написан
    2 комментария
  • При компиляции VC++, Opencv 3.2 проекта не работает exe на другой системе, требует opencv_world330.dll что делать?

    @Mercury13
    Программист на «си с крестами» и не только
    Краш, вероятно, связан с другой вещью. Компилятор-то новенький, и на ту машину не успели подвезти его среду исполнения. Выясни, какие файлы нужны: MSVCR140.DLL, MSVCP140.DLL или MFC140U.DLL.
    (при условии, что сам OpenCV также скомпилирован C++2017; если нет — также нужны и файлы другого компилятора.)

    Если так и не удастся отыскать — найди программу Dependency Walker и точно найди, чего ей не хватает.
    Ответ написан
    6 комментариев
  • Возможен ли в XML атрибут с пространством имён ранее XMLNS?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Опять приходится отвечать самому. Возможен.
    www.oracle.com/technetwork/articles/srivastava-nam...
    <?xml version="1.0"?>
    <Book isbn="1234"
          pfx:cover="hard"
          xmlns="http://www.library.com"
          xmlns:pfx="http://www.library.com">
      <Title>Sherlock Holmes</Title>
      <Author>Arthur Conan Doyle</Author>
    </Book>
    Ответ написан
    Комментировать
  • Какой использовать алгоритм?

    @Mercury13
    Программист на «си с крестами» и не только
    Очень важный вопрос. Может ли содержимое папки попасться раньше, чем сама папка? Для простоты считаем, что нет, и что вы нашли библиотеку для JSON.
    Нужны два объекта: дерево (самодельный) и словарь ID (map: id → развилка дерева).
    Для каждого элемента…
    1. По parent id через словарь находим, куда его впихнуть. Если не нашли — вывести ошибку.
    2. Если folder: создать развилку, присвоить ID, вписать её в словарь ID.
    3. Если не folder: создать лист, присвоить ID и вписать в словарь ID (если надо по какой-то другой причине).
    Я плохо знаю Си с диезом, так что поправляйте меня.
    class Node {
      List<Node> children;
      List<Leaf> leaves;
    }
    
    class Leaf {
      // в нём может быть что угодно
    }
    
    class Tree {
      Node root;
    }
    
    Tree tree;
    Dictionary<string, Node> idDic;  // считается, что словарь нужен только на разбор JSON,
       // и он временный
    Ответ написан
    Комментировать
  • Простой пример одного и того же кода в ООП, функциональном и процедурном стиле?

    @Mercury13
    Программист на «си с крестами» и не только
    Просуммировать элементы std::vector<int>. Си++.

    Процедурный
    int sum = 0;
    for (int v : vec)
      sum += v;
    std::cout << sum << std::endl;


    ООП.
    class Accumulator
    {
    public:
      void feed(int value) { fSum += value; }
      int sum() const { return fSum; }
    private:
      int fSum = 0;
    }
    
    Accumulator acc;
    for (int v : vec)
      acc.feed(vec);
    std::cout << acc.sum() << std::endl;


    Функциональный (правда, слегка настоянный на шаблонах)
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    std::cout << sum << std::endl;


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

    UPD2. А теперь представьте себе, что нужно вычислять не сумму, а что-то сложное — например, среднее и квадратичное отклонение. В процедурном придётся или раскрывать сложные формулы, или налаживать какие-то обобщения. Объектное меняется на раз-два. В функциональном придётся менять функцию-шаблон, работающую над итератором.
    Ответ написан
    Комментировать
  • Как возможна замена Юникодов?

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

    UPD. Посмотрел, как это делается в Java. Годятся любые символы, являющиеся буквами в Юникоде. Как минимум по спецификации Гослинга.
    Ответ написан
    4 комментария
  • Header в header'е и можно ли делать игру на одних Header'ах?

    @Mercury13
    Программист на «си с крестами» и не только
    Такой механизм называется «одна единица компиляции» и вполне имеет право на жизнь: на одном процессоре время полной сборки будет наименьшим, потому так распространяют некоторые библиотеки (SqLite, Google Test). Правда,
    игра — обычно масштабный проект, и чем больше будет кода, тем дольше нужно компилировать, чтобы проверить изменения.

    Потому код обычно разбрасывают по единицам компиляции (*.cpp) в соответствии с его внутренней логикой, и к каждой единице (кроме точки входа) приписывают хедер (*.h), который показывает, что эта единица делает. Повторяю, только описывает, что делает — весь код в CPP. И в большинстве случаев самый длинный этап сборки — линковка (особенно с оптимизацией по ходу линковки aka LTO).

    Единственное, что в 80% случаев не получается закинуть в CPP — это шаблоны.

    Чтобы один хедер не подключался несколько раз — есть include guard. Правда, если вы не продумали зависимость между хедерами, может попасться циклическое включение — это вредно, но лишь потому, что программа может не скомпилироваться.

    Чтобы не было циклических включений, для сохранения скорее всего потребуются два хедера: один отвечает за собственно процедуру сохранения и подключается к одному-единственному модулю — системе меню. Второй — за какие-то общие функции, которые позволяют сохраняться в абстрактный поток плиточному фону, снаряду, монстру… Называется как-нибудь SaveUtils.h и подключается повсюду.

    (Примечание. И SqLite, и Google Test разрабатывались по традиционной схеме, с проектом из кучи CPP. SqLite собирается в один большой *.c автоматикой, и я даже качал традиционный код — на 5-метровом файле некоторые версии Embarcadero вылетали с нехваткой памяти. В Google Test есть файл all.cpp или что-то подобное, в котором #include остальных CPP — пользователь подключает в проект all.cpp, и библиотека отнимает минимум его времени.
    Ответ написан
  • Как записать в excel поле время?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Записать время как double в формате «1 сутки = 1; 1 секунда = 1/86400».
    2 — простой путь. Применить какой-нибудь из предопределённых числовых форматов (думаю, лучше всего подходит 2E16 = [h]:mm:ss сверх 24 часов).
    2 — сложный путь. Похимичить с форматными строками.
    Ответ написан
  • С чего начать создания текстовой игры?

    @Mercury13
    Программист на «си с крестами» и не только
    Движок можно даже самописный. Считается, что движок — дело тяжёлое, но для таких игр это не так.
    Начать надо со среза механики и предельно упрощённого движка на чём угодно (хоть в консоли, хоть на Java AWT).
    Ответ написан
  • Как сделать численно равные выборки из нормального и любого иного распределения?

    @Mercury13
    Программист на «си с крестами» и не только
    UPD. Раз у нас нормальное распределение — надо построить нормальное распределение, оцененное по методу наивысшего правдоподобия.
    А затем вычислить F−1(0,05), F−1(0,1), …, F−1(0,95).
    Ответ написан
    Комментировать
  • Правильно ли объясняется в тексте почему в 1 кб 1024 байт?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело вот в чём. Возьмём магнитную память. У неё есть проволочки-ряды, проволочки-столбцы и проходящий через все сердечники провод считывания-записи. Чтобы считать ячейку, мы пускаем ток через нужный ряд и нужный столбец (сила тока подбирается так, чтобы две проволочки работали, а одна — нет). Чтобы пустить ток ровно через одну проволочку, используется такой девайс, как дешифратор: двоичный код, например, 010=2 превращает в позиционный код 00100000 (единица на 2-м месте, начиная с ноля).

    Вот у нас есть такой блок памяти. Пришёл адрес — как получить номер строки и столбца? Разделить адрес на кол-во столбцов; частное — № строки, остаток — № столбца. Для удобства столбцов должна быть степень двойки: во-первых, это полностью задействует возможности дешифратора; во-вторых, частное и остаток сводятся к тому, что часть линий адреса отводим на один дешифратор, часть на второй.

    Если у нас несколько таких блоков, из тех же соображений и строк должна быть степень двойки — так что получается, что ёмкость устройства памяти произвольного доступа (магнитной, оперативной, постоянной, флэш-) степень двойки. Количество блоков — не обязательно, и батарея чипов на SSD может содержать любое удобное количество — а ёмкость одного чипа действительно степень двойки.

    С появлением полупроводниковой памяти тяга к степеням двойки даже усилилась: стоимость чипа зависит от его ёмкости постольку, поскольку часть чипов идёт в выбраковку. Есть некий (и довольно узкий) оптимальный диапазон ёмкостей: больше — велика выбраковка; меньше — только для спец. приложений вроде совместимости и энергопотребления.

    Вот и всё.
    Ответ написан
    Комментировать
  • Что такое bulk-запрос?

    @Mercury13
    Программист на «си с крестами» и не только
    Это понятие никак не формализовано. Но в целом это…
    Запрос, позволяющий массово выполнить несколько сходных действий. Например, получить информацию сразу по нескольким контрагентам, со всем, что им подчинено. Залить в БД кучу информации.
    Ответ написан
    Комментировать
  • Как написать картинку кодом?

    @Mercury13
    Программист на «си с крестами» и не только
    Формат JPEG очень сложен, и КРАЙНЕ не рекомендую писать поддержку самому. Лучше пользоваться любой подходящей библиотекой. Вот, например, на Qt:
    #include <QImage>
    #include <QPainter>
    
    int main()
    {
        QImage pix(100, 100, QImage::Format_RGB888);
        pix.fill(Qt::darkBlue);
        QPainter painter(&pix);
        painter.setPen(QPen(Qt::yellow, 2.0));
        painter.drawEllipse(QPoint(50, 50), 40, 30);
        pix.save("test.jpg");
    }

    Приду домой — отыщу код на PHP, призванный уменьшать размер картинок. В общем, для любого современного языка библиотека найдётся.
    Ответ написан
    2 комментария
  • Как правильно организовать код большого проекта на C++(и не только)?

    @Mercury13
    Программист на «си с крестами» и не только
    Имена классов с большой буквы в CamelCase, например class EventHandler;.

    Принято в Java, Qt.

    Названия объектов аналогично, но первая буква маленькая, например Image backgroundImage;.

    Принято в Java, Qt.

    Названия примитивных типов(int, char, double, etc) маленькими через нижнее подчёркивание, например double percent_of_fails;

    Думайте как хотите, но, по-моему, нет нужды.

    Названия методов с мальнькой в camelCase и отражают действие функции, например void addModule(std::shared_ptr module);

    Принято в Java, Qt.

    Структура файлов:

    При таком количестве файлов (и даже впятеро большем) — норма.

    Первым идёт инклуд C++ хедеров, затем сторонние библиотеки типа буста, затем *.i файл из данной директории и после всё остальное.

    Свой хедер → стандартные библиотеки Си/Си++ → сторонние библиотеки, причём чем больше мы от них архитектурно зависим, тем они раньше → внутренние файлы (опять-таки, движок раньше утилит и наборов данных).

    Первым свой хедер — это архиважно. Как правило, модули идут парой «хедер + единица компиляции», и мы сразу же убеждаемся, что в хедере есть все нужные #include.

    1 forward declarations(чтоб не замусоривать ими остальные файлы)

    Forward declarations конкретно чего?

    2 инклуды всех *.h файлов из данной директории.

    Пункт спорный даже не из-за перекомпиляции, а из-за 1) циклической зависимости между модулями; 2) если сделать это в хедере — может привести к некомпилирующемуся проекту.

    Сущности в каждой директории имеют своё одноимённое пространство имён,

    Пространств имён должно быть намного меньше, чем файлов, плюс они должны быть предельно короткими. Избегать using namespace.

    Кроме того…
    1) Рекомендую в каталоги поиска хедеров поставить основной каталог проекта. В #include ни в конем случае не должно быть «каталог вверх» (..).
    2) Возможно, чужие библиотеки стоит вынести из каталога проекта. Их каталоги также стоят в каталогах поиска хедеров.
    3) Категорически запрещены повторы файлов в разных каталогах.
    Ответ написан
    2 комментария
  • Как создать событие закрытия формы из другого Юнита?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Перемести «uses соответствующую форму» из интерфейса в implementation. Такие циклические обращения разрешены.
    Правило хорошего тона: что угодно — uses, const, var — желательно держать в implementation, если только они не нужны интерфейсу.
    Впрочем, подобный циклический «комок грязи» говорит о том, что архитектура программы плохо продумана, и для больших программ это нежелательно.

    2. Явно неверный код Form3.Create(self);
    Если создать форму — то правильно Form3 := TForm3.Create(self);
    Если кто-то создал, а ты повторно вызвал конструктор — зачем такое?
    Ответ написан
    4 комментария
  • Для чего нужно так много портов?

    @Mercury13
    Программист на «си с крестами» и не только
    Их там 65536. Видимо, сделали с запасом, потому что 256 явно не хватает.
    Каждой игре свой порт, чтобы минимизировать вероятность, что две службы захотят один порт и их придётся принудительно разводить.
    Ответ написан
  • Возможно ли решить данную задачу?

    @Mercury13
    Программист на «си с крестами» и не только
    1018 — это обычное 64-битное целое. long long в Си, long в Java, int64 в Delphi.

    Очевидно, задача переводная, спичка не только match (это слово у них очень многозначное), но и matchstick. Причём переводил то ли автомат, то ли редкий надмозг, пример неговорящий, и откровенно непонятно: то ли где находится число 11, то ли что на 11-й позиции. Будем решать 2-ю задачу: что на 11-й позиции.

    1. Определить количество разрядов (для этого хватает несложного цикла) и какой номер у данного числа среди N-значных чисел.
    2. А теперь находим, сколько есть N-значных чисел из M спичек. Рекуррентное соотношение:

    Q[N, M] = sum{k = 1..9} (Q[N−1, M−q(k)]), если N — найденная нами значность, но не 1-ца,
    Для остальных N формула та же, но суммирование 0…9.
    q(0) = 6, q(1) = 2, q(2) = 5, и т.д. — кол-во спичек в цифре.
    Граничное условие: Q[0, 0] = 1, Q[0, M] = 0 для остальных M.
    «Методом выкручивания рук» также примем, что для отрицательных M все Q равняются 0.

    Решаем рекуррентное соотношение динамическим программированием.
    3. А теперь самое интересное: воспользовавшись таблицей динамического программирования, находить цифру за цифрой, начиная со старшей.

    Например, у нас 15-е число. Первый шаг опустим, поверьте мне: это 4-е двузначное, начиная с нуля.
    2-й шаг.
    Q[1,2] = 1
    Q[1,3] = 1
    Q[1,4] = 1
    Q[1,5] = 3
    Q[1,6] = 3
    Q[1,7] = 1
    Q[2,4] = 1
    Q[2,5] = 2
    Q[2,6] не вычислял, главное — запредельно большое.

    Q[2,0]…Q[2,3] равняются нулю.
    Вычитаем Q[2,4] — получается 3.
    Вычитаем Q[2,5] — получается 1.
    Вычитаем Q[2,6] — не получается. Итого у нас шесть спичек, остаётся 1.

    3-й шаг, работаем по цифре.
    Ноль, Q[1, 6−6] = 0. Остаётся 1.
    Единица, Q[1, 6−2] = 1. Остаётся 0.
    Двойка, Q[1, 6−5] = 0. Остаётся 0.
    Тройка, Q[1, 6−5] = 0. Остаётся 0.
    Четвёрка, Q[1, 6−4] = 1. Не вычитается, остаётся 2 спички, 1 знак и номер 0. Записываем цифру 4.
    Ноль, Q[0, 2−5] = 0. Остаётся 0.
    Единица, Q[0, 2−2] = 1. Не вычитается, остаётся 0 спичек, 0 знаков и номер 0. Записываем цифру 1.

    Итого получили 41.
    Ответ написан
    3 комментария
  • На чем лучше программировать для кроссплатформенности?

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

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

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