Задать вопрос
  • Задача на строки в Си: как конкатенировать строки без библиотечных функций(старый вопрос удален)?

    @res2001
    Developer, ex-admin
    Как можно было сделать то же самое, но при помощи традиционной обработки массива?

    А что такого по вашей ссылке не традиционного в смысле обработки массива? Там вполне традиционные операции.
    Видимо вы привыкли, что обращение к элементам массива это arr[i]. Но это лишь один из вариантов.
    Вариант примененный в коде по ссылке - инкремент указателей - просто смещает указатель на следующий элемент массива. По идее это должно работать немного быстрее, чем arr[i].
    Кстати, принцип работы итераторов в C++ std как раз тот же самый, что использован тут. Так что можете считать, что dest и src это итераторы по строке :-)

    Если очень хочется, то можете переписать код с применением индексации. Ничего сложного в таком преобразовании кода нет.

    По ссылке, реализован аналог strcat, но эта функция (так же как и функция по ссылке) может приводить к выходам за пределы массива, т.к. тут вообще ни как не контролируется размеры массивов. Было бы интересно реализовать аналоги strncat или strncat_s.
    Ответ написан
    Комментировать
  • Что означает память с явными адресами?

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

    @res2001
    Developer, ex-admin
    Основная проблема - быстро узанать размер каталога. Стандартных средств cmd для этого нет.
    Остается только делать рекурсивный обход каждого каталога и суммировать размеры каждого файла, как только сумарный размер превысит 1 Мб подсчет можно прекращать и пропускать каталог.
    Размер конкретного файла можно получить из переменной цикла for /f с помощью модификатора %%~zi. Этот же модификатор действует и для нумерованных параметров процедур
    Смотрите:
    for /?
    call /?
    set /?
    rmdir /?
    Ответ написан
    Комментировать
  • Почему такая низкая скорость с openvpn?

    @res2001
    Developer, ex-admin
    РКН начинает блокировать openvpn?

    Если бы начал, то скорость бы упала в ноль.

    Для начала стоит замерить задержки на пути пакетов от дома до ВПН сервера. Это надо сделать когда скорость нормальная и когда скорость упала. Проводите замеры несколько дней, чтоб набрать статистику. Сравнивая задержки, вы сможете найти на каком участке по пути есть провалы скорости. Возможно, во время провала скорости меняется маршрут пакетов и т.п.
    Измеряйте задержки не внутри ВПН, а по "чистому" каналу. Измерять задержки можно с помощью traceroute (tracert) или с помощью iperf.

    Если провалы скорости у ваших операторов (Мегафон или Contabo), то можно попробовать пообщаться с поддержкой операторов. Если же это где-то по середине, у других операторов, то вряд ли можно что-то реально сделать. Вероятно только сменить своего оператора, или попробовать как-то повоздействовать через своего оператора, предоставив ему статистику.
    Ответ написан
    Комментировать
  • Как сделать сортировку Шелла на Си?

    @res2001
    Developer, ex-admin
    Возвращайте значение iterations из shellsort. В main суммируйте эти значения и в конце находите среднее.
    Ответ написан
    Комментировать
  • Как сымитировать потерю пакетов?

    @res2001
    Developer, ex-admin
    Например во FreeBSD в штатном фаерволе ipfw есть такая штука как dummynet - специально для целей тестирования. Там можно настройками задавать скорость и процент потерь. Можно очень хорошо отлаживать сетевые приложения, если сделать фряху с подобным фаерволом шлюзом между клиентом и сервером вашего приложения. Подобную сетку запросто можно поднять на виртуалках.
    Ответ написан
    Комментировать
  • Почему вылезает сообщение "make: «build» не требует обновления"?

    @res2001
    Developer, ex-admin
    Ответ в комментариях
    Ответ написан
    Комментировать
  • Как передать массив в функцию С++ ( пишет no matching function to call)?

    @res2001
    Developer, ex-admin
    Написал опус на вопрос, который вы удалили, хорошо сохранился в буфере обмена :-) а то было бы обидно.

    Ваш массив пожно просто привести к указателю, по старинке (int*)a или используя касты.

    Но у вас тут на самом деле 2 проблемы.
    Первая - обращение к элементам массива в average используя [i][j]. Вторая - VLA.
    По первой проблеме:
    В С/С++ оператор индексации (array[i]) выполняет следующее действие: *(array+i).
    Отсюда должно быть понятно, что раз array у вас это int*, то после array[i] вы получите int, от которого уже нельзя взять второй индекс, т.к. это просто 1 int, а не массив.

    Отсюда есть несколько выходов:
    1. дурацкий (самый долгий по исполнению и затратам памяти): использовать динамический массив массивов
    Выглядит примерно так:
    int **array = new int*[rowCount];
    for(int i=0; i < rowCount; ++i)
       array[i] = new int[colCount];

    Как видите array превратился в двойной указатель, теперь каждый элемент в первом измерении - это указатель на одномерный массив. Всего у вас получается rowCount + 1 выделений памяти. Не забудьте столько же раз вызвать оператор delete.
    В average теперь передавайте int** и у вас будет работать оператор [][], т.к. первая индексация уже будет возвращать int*.
    Не рекомендую использовать этотт способ.

    2. Вычислять индекс массива вручную (не использовать индексацию):
    *(array + i*colCount + j)
    Это такой хардкорный стиль. Но зато работает быстро и масштабируется на массивы любой размерности без особых проблем.

    3. использовать std::vector<std::vector<int>> - это то же самое, что и вариант 1, но закамуфлированный под вектор :-)

    Вторая проблема это VLA (Variable Length Array).
    Статические (автоматические) массивы в С++ вы можете определять, только константным размером (размером известным на этапе компиляции).
    У вас же размерность массива динамическая (вводится пользователем во время выполнения программы). Отсюда следует, что вы должны использовать динамические массивы, выделенные с помощью new.
    В стандарте С++ нет VLA. VLA есть только в Си и то начиная с С99.
    Ваша функция task3 компилируется, только потому что в gcc/clang по умолчанию включены расширения. В расширения входит так же и возможность использовать VLA. Если задать опциями более строгое соответствие стандарту С++, то функция не соберется.
    И кстати, например в микросовтовский компилятор VLA до сих пор не завезли.

    Но если уж у вас есть VLA, то вы можете преобразовывать указатель в VLA массив с помощью такой кучерявой конструкции:
    int (*array2)[colCount] = (int(*)[colCount]) array;

    В этом случае обращаться к элементам массива можно как обычно через двойную индексацию: array2[i][j]
    Когда-то делал тест на эту тему: https://ideone.com/4i6lRw
    Кстати, если в average сначала передать размерности, и последним параметром массив, то по идее массив можно сразу объявить двумерным, используя ранее переданные размерности:
    void average(int rowcount, int colcount, int aarray[rowCount][colCount])

    Это то же VLA.

    Вообще не рекомендую в С++ использовать VLA, т.к. программа становится не переносимой и зависимой от компилятора.
    Ответ написан
    4 комментария
  • Как скопировать файлы по дате изменения посредством bat?

    @res2001
    Developer, ex-admin
    Развернуто не выйдет - нет под рукой винды. Могу дать направление.

    Получить отсортированный по дате изменения список файлов можно с помощью команды: dir /b /a-d /od *
    За сортировку отвечает ключ /od, можно получить обратную сортировку, тогда надо задать ключ /o-d. Ключ /a-d удаляет из вывода каталоги (по умолчанию dir выводит и каталоги то же).
    Эту команду надо запихнуть в цикл, примерно так:
    for /f "tokens=* delims=" %%a in ('dir /od ...') do (
      echo %%a
    <тут команды тела цикла>
    )

    В цикле просто на первой итерации копируете файл в to и to2 и выходите из цикла (goto).
    Для дальнейших действий аналогичные циклы по соответствующим каталогам, только пропускаете первых 5 итераций, на остальных файлы удаляете. Пропустить 5 итераций в цикле можно либо счетчиком в теле цикла, либо есть опция цикла skip.
    Примерно схема уже должна быть ясна.
    Отработайте этапы команды по одному, а потом запихните все этапы в один батник.
    Детали применения команд смотри:
    dir /?
    for /?
    set /?
    goto /?
    Ответ написан
    6 комментариев
  • Что в CMAKE я должен считать библиотекой?

    @res2001
    Developer, ex-admin
    Вообще обычно бибилотеки ставятся отдельно в систему (для линукс) с помощью стандартного пакетного менеджера.

    Если вашей библиотеки в пакетном менеджере нет, то можно и собирать из исходников.
    В этом случае можно и просто "сувать" все файлы в add_executable. Никто ж вам это запретить не может.
    Но обычно проще, лучше и универсальней для сторонних библиотек создавать свои собственные цели с помощью add_library и уже их подключать к основной цели с помощью target_link_libraries. Библиотеку можно делать как динамическую, так и статическую.
    Если проект достаточно развесистый и содержит например тесты и/или несколько исполняемых файлов, то вообще можно в каждом каталоге проекта создавать отдельную статическую библиотеку. На больших проектах это часто может сэкономить время на компиляции, за счет того что в несколько конечных целей будут линковаться уже готовые библиотеки, а не пересобираться из исходников каждый раз.
    Ответ написан
    3 комментария
  • Bat файл работает через раз как исправить?

    @res2001
    Developer, ex-admin
    В команде call, на соклько помню нужно указывать имя файла с расширением. Она вызывает другой внешний батник. Проверить сейчас поведение команды без указания расширения не могу.
    В любом случае, если тут должен вызваться activate.bat, то надо его смотреть то же.

    По остальным командам вообще не чему тормозить, кроме, конечно питоновского скрипта.
    Ну и не забывайте, что в конце стоит команда pause - она ждет нажатия any key пользователем. Ждать может до посинения.
    Ответ написан
  • Стоит ли учить Boost в 2021 году?

    @res2001
    Developer, ex-admin
    Вполне востребованная библиотека.
    Но учить не стоит. Стоит знать, какие возможности она предоставляет и как ее исопльзовать в своем проекте. Сделать пример с какими-нибудь достаточно сложными компонентами буста, например asio.
    Ответ написан
    Комментировать
  • Как удалить наименьшую цифру из числа?

    @res2001
    Developer, ex-admin
    Проще всего, по моему, перевести число в строку и работать с символами. Находите минимальную цифру перебором, запоминаете ее позицию в строке, копируете остаток строки после минимальной цифры в позицию минимальной цифры.
    Ответ написан
    Комментировать
  • Как скрестить локальное .exe-приложение с интерфейсом управления в веб-браузере?

    @res2001
    Developer, ex-admin
    Проще всего использовать старый добрый интерфейс CGI, его ни кто не отменял и поддержка в веб серверах есть.
    Возможно есть что-то на замену CGI, более свежее и быстрое.

    Другой вариант - встроить веб сервер в приложение. Думаю можно найти какой-то готовый веб сервер в виде библиотеки С/С++ и использовать эту библиотеку (из того что приходит на ум - libonion). Можно написать самому какой-то урезанный вариант веб сервера с минимальным функционалом. Для этого можно использовать какой-либо библиотечный HTTP парсер или опять же написать его самому.
    Ответ написан
    Комментировать
  • Как правильно использовать указатель?

    @res2001
    Developer, ex-admin
    Когда вы передаете в функцию указатель на объект (на что угодно), это значит, что вы можете в функции изменять этот объект и все изменения будут видны вызывающему коду.
    Если вам надо что бы вызывающий код увидел новый указатель, то передайте в функцию указатель на указатель:
    int next_edge(edge_t **out_edge)
    {
      edge_t * tmp = malloc(sizeof(edge_t));
      if(tmp)
      {
         *out_edge = tmp;
         return 1;
      }
      return 0;
    }

    Но обычно проще в таком случае возвращать указатель в возвращаемом значении. Вызывающий код может сравнить возвращенное значение с NULL для выяснения того вернула функция нормальный указатель или произошла ошибка. Так делает, например, функция malloc().
    Ответ написан
    2 комментария
  • Можно ли в tracert увидеть 2 и более роутеров поключенных последовательно?

    @res2001
    Developer, ex-admin
    tracert выполняет обычные пинги (ICMP echo request) с постепенным увеличением значения TTL пакета от 1 и до max hop.
    На любом шлюзе/роутере правилами фаервола можно блокировать ICMP. Тогда на этом хопе tracert покажет * вместо нормальной статистики.
    Ответ написан
    Комментировать
  • EventLoop, потоки и блокировки, как правильно блокировать?

    @res2001
    Developer, ex-admin
    Что касается ImageMemoryCache: в методе get вы возвращаете ссылку на элемент мапы. Блокировка с мапы снимается при выходе из get, но вызывающий код имеет ссылку и может с этим объектом делать все что угодно.
    Параллельно вы можете вызвать clear, который удалит элемент на который осталась ссылка в другом потоке.

    По уму вы должны блокировать мапу до тех пор пока жива любая ссылка на содержимое мапы.
    Второй вариант - создавать в get копии объектов из мапы и возвращать их. При этом изменение этого нового объекта никак не повлияет на объект в мапе. Ну тут можно что-нибудь придумать, сделать какой-то прокси объект и т.п.
    Третий вариант - каждый объект в мапе защищать своим мьютексом.
    Ответ написан
  • OpenVPN на протоколе UDP не видит только отключение клиента в логах?

    @res2001
    Developer, ex-admin
    Используйте в конфиге сервера опцию keepalive. Это заставит OpenVPN отправлять тестовые пинги для проверки соединения.
    https://openvpn.net/community-resources/reference-...
    Ответ написан
    Комментировать
  • Почему массивы в Си заполняются "М"?

    @res2001
    Developer, ex-admin
    Не заполняются они М.
    Если объявляется массив автоматический на стеке без инициализатора, то просто отводится память на стеке (уменьшение/увеличение регистра счетчика стека), никаких "теневых" присваиваний элементам не происходит, элементы массива принимают те значения, которые были в этих ячейках памяти ранее.
    То же самое и с динамическим массивом, только механизам выделения памяти другой.
    По любому адресу в памяти всегда находится какое-то значение, даже если эта память еще не выделена, просто потому что плашка памяти уже вставлена в материнку и на нее подано питание.

    Возможно в вашем случае это и не случайность - вы же не приводите код, которым выделяете память.
    Ответ написан
    7 комментариев
  • Где найти информацию по конфигурации uboot?

    @res2001
    Developer, ex-admin
    У меня был некоторый опыт с uboot, правда для другой ОС

    Если у вас какая-то стандартная покупная плата, то возможно в uboot уже есть готовый config. Обычно производители плат в документации указывают как собрать uboot под их плату (если они поддерживают uboot), либо это можно нагуглить в интернете.
    Если же плата самодельная, то берете самый близкий для вашей платы config (вы же брали за основу какой-то референс дизайн платы, вот эту плату и берите за основу), переименовываете его и вносите в него соответствующие изменения.
    Бывает, что вместе с config'ом требуется вносить изменения и в dts, они в uboot лежат в ./arch/<platform name>/dts. Название используемых dts лежит в переменной CONFIG_DEFAULT_DEVICE_TREE и/или в CONFIG_OF_LIST в config файле.

    Config файл - это просто набор параметров, которые превращаются в набор инструкций #define при сборке.
    С dts все сложнее. Там целый язык описания железа.

    Для сборки uboot рекомендую следующую последовательность:
    1. Заведите для сборки отдельный пустой каталог. Он будет текущим каталогом для всех дальнейших команд
    2. Пусть каталог где лежит сам uboot хранится в переменной UBOOT_DIR. Архитектура процессора вашей платы (например arm) в переменной ARCH. Префикс для кросскомпилятора в CROSS (например arm-linux-gnueabihf-). Имя выбранного defconfig файла в переменной DEFCONFIG (имя указываете вместе с суффиксом _defconfig)
    3. Очистка каталога сборки:
    make -C $UBOOT_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS distclean

    Эта команда пригодится при пересборках в случае изменения конфигурации
    4. Подготовка конфигурации для сборки:
    make -C $UBOOT_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS $DEFCONFIG

    5. Сборка: make -C $UBOOT_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS

    Несколько полезняшек:
    1. Вы можете задавать дополнительную опцию для make: -O <путь>
    Она задает каталог, в котором будет происходить сборка. Этот каталог make создаст сама. Это бывает удобно, если работаете сразу с несколькими конфигами.
    2. В uboot встроен конфигуратор конфигов :) Конфигурация происходит в текстовом режиме с помощью меню, присутствуют подсказки для опций и т.п. Когда вы создали начальную конфигурацию в п.4 выдайте команду:
    make -C $UBOOT_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS menuconfig

    Тут то же можно добавлять опцию -O для выбора каталога с конфигурацией. После исправления конфигурации, не забудьте ее сохранить.
    Дальше нужно дать команду:
    make -C $UBOOT_DIR ARCH=$ARCH CROSS_COMPILE=$CROSS savedefconfig

    Она создаст на основе текущей конфигурации defconfig файл в каталоге сборки. Этот файл можно переименовать в <имя платы>_defconfig и подложить в каталог с конфигами uboot и в дальнейшем использоавть его для сборки.
    3. В каталоге с uboot дайте комаду make help для получения списка возможных опций.
    4. Обычно я собираю uboot под линукс, но та же схема вполне работает и в WSL под виндой. Набор кросс-компиляторов есть в портах (в WSL исопльзовал дистрибутив ubuntu).

    Желаю удачи!
    Ответ написан
    4 комментария