Ответы пользователя по тегу C++
  • Что делать с include-ами?

    @res2001
    Developer, ex-admin
    Не правильно вы понимаете. Директивы препроцессора используются практически в любом проекте на С/С++. Посмотрите заголовочные файлы стандартной библиотеки. Темплейты - это про другое.
    ада с define-ами

    Это сильно преувеличено.
    Пример использования:
    1. При компиляции устанавливаете через опцию компилятора /D свой define: /Dsome_const_name
    2. В коде:
    #ifdef some_const_name
    #include "my_header.h"
    #else
    #include "my_other_header.h"
    #endif

    3.Все
    Ответ написан
    2 комментария
  • Как вывести каждый байт значения типа int?

    @res2001
    Developer, ex-admin
    1234 в шестнадцатеричной системе 4D2.
    Младший байт равен D2, в двоичной системе это: 1101 0010
    Как видите старший бит установлен в 1 - значит, если это знаковое число, то оно отрицательное и закодировано дополнительным кодом. Осталось только разложить D2 в дополнительном коде и получите -46 - это результат вам и вывела printf.
    Ответ написан
    Комментировать
  • В чем разница между malloc() и calloc() а также free() и dellete()?

    @res2001
    Developer, ex-admin
    Разница только в том, что calloc обнуляет выделенную память перед тем, как возвратить указатель, а malloc этого не делает. Внутри calloc, наверняка вызывает malloc для выделения памяти, а потом memset для обнуления. Так что calloc это просто надстройка над malloc для удобства. Вот схематично реализация calloc:
    void * calloc (size_t num, size_t size)
    {
       void * mem = malloc(num * size);
      memset(mem, 0, num * size);
      return mem;
    }

    Сами эти функции оперируют исключительно размером выделяемой области в байтах, им все равно что вы в дальнейшем будете делать с выделенной памятью - инты туда писать или "стринги".
    Ну и как бы никто не мешает вам одну и ту же область памяти сначала использовать как массив интов, а потом как массив байт. Или так например:
    int a = 0x33323130;
    char * c = (char*)&a;
    printf("%c %c %c %c\n", c[0], c[1], c[2], c[3]);

    Пример не использует malloc/calloc для выделения памяти, память выделяется в стеке просто объявлением int a. Тут я попытался показать, что содержимое памяти можно интерпретировать как угодно, главное находится в границах выделенного диапазона.
    Причем языки С/С++/asm это позволяют делать, а другие - нет.
    Пример предполагает, что int имеет размер 32 бита, не для всех платформ это так, но в основном - именно так.
    Кстати этот пример можно использовать для определения порядка байтов платформы: если выведется "1 2 3 4" значит у вас LITTLE ENDIAN, а если "2 1 4 3" - BIG ENDIAN.

    PS: free() - это Си, а delete - C++
    Ответ написан
    4 комментария
  • Как правильно передать двумерный массив в функцию?

    @res2001
    Developer, ex-admin
    Если вы изучаете С++, то лучше использовать классы стандартной библиотеки для массивов. В функцию передаете ссылку на класс.
    В чистом Си передается просто указатель и размер в отдельном параметре (или 2 размера для двумерного массива).
    Сам двумерный массив может быть представлен в двух вариантах:
    1.Как массив указателей, где каждый указатель представляет собой одномерный массив. Нужно отдельно выделять память для массива указателей и для каждого одномерного подмассива и аналогично освобождать. В этом случае возможна операция индексации обоих измерений массива, при этом массив указателей и каждый подмассив могут находится в разных участках памяти.
    void foo(int ** arr, int N, int M)
    {
    ...
    }
    int main()
    {
      int N = 10; // первое измерение массива
      int M = 20; // второе измерение массива
      int ** arr = new int * [N];
      for(int i = 0; i < M; ++i)
      {
         arr[i] = new int[M];
      }
      ...
      foo(arr, N, M);
      ...
      // Тут освобождение массива аналогично выделению в обратном порядке
    }

    2.Как одномерный массив размерностью N * M. В этом случае память под массив выделяется и освобождается вся оптом одним куском, но операция индексации первых размерностей не возможна. Но можно легко переходить от двумерного массива к одномерному, сразу вычислять нужный индекс или просто перемещаться по элементам массива с помощью временного указателя.
    void foo(int * arr, size_t N, size_t M) 
    {
      ...
    }
    int main()
    {
      int N = 10; // первое измерение массива
      int M = 20; // второе измерение массива
      int * arr = new int * [N*M];
      int * arrcur = arr;  // временный указатель для обхода массива
      int * arrone = arr;  // вариант с переходом к одномерному массиву
      for(int i = 0; i < N; ++i)
      {
        for(int j = 0; j < M; ++j)
        {
            // Вариант с вычислением адреса текущего элемента по индексам
           *(arr + i * M + j) = rand() % 10;   // вычисление нужного индекса на месте
           // Вариант с обходом массива с помощью временного указателя
           *arrcur = rand() % 10; 
           ++arrcur;  // переход к следующему элементу
           // Вариант с переходом к одномерному массиву
          arrone[j] = rand() % 10; 
        }
        arrone += M;
      }
      ...
      foo(arr, N, M);
      ...
      delete[] arr;
    }
    Ответ написан
  • Какую книгу по C++ стоит прочитать новичку?

    @res2001
    Developer, ex-admin
    Хорошая книга, можете ее продолжать изучать, а главное делайте побольше примеров, возможно в дальнейшем захочется реализовать что-нибудь свое. Тут главное практика, а не то какую книгу читаете.
    Ответ написан
    Комментировать
  • Записать значения дискретных каналов в бинарный файл. С++?

    @res2001
    Developer, ex-admin
    Инициализируя вот так массив:
    int ChValue [6] = {000011};
    Вы получите в ChValue[0] = 9 - десятичное 9 - это восьмеричное 011. По правилам языка, целочисленные числовые константы, начинающиеся с 0 являются восьмеричными. В остальных элементах массива будут 0.
    Вы хотите записать шесть значений в одну двухбайтовую переменную (хотя было бы достаточно и 1 байта).
    Для этого вам нужно использовать битовые операции.
    Например:
    // ChValue - исходный массив значений по каждому каналу
    int ChValue [6] = {0, 0, 0, 0, 1, 1};
    uint16_t val = 0;
    for(int i = 0; i < 6; ++i)
    {
      if(ChValue[i] == 1)
         val |= 1 << i;
    }
    // в результате в val будет установлен в 1 бит с номером канала в котором в ChValue единица.

    После этого просто запишите val в файл.
    Ответ написан
  • Как распределять свои проекты?

    @res2001
    Developer, ex-admin
    Освойте утилиту make и makefile.
    Ответ написан
    1 комментарий
  • С ++. Создание и запись бинарного файла?

    @res2001
    Developer, ex-admin
    1. unsigned int на большинстве платформ - 4 байта, поэтому используйте более подходящие типы для сигналов: uint16_t например.
    2. Раз количество каналов меняется, то есть смысл отделить заголовок (n и timestamp) от собственно данных каналов. Заголовок пишете отдельно, а данные каналов храните в массивах соответствующих типов и записываете целиком массив.
    3.Т.к. у вас не известно заранее количество каналов, то стоит писать в файл эту информацию (включить количество аналоговых и дискретных каналов в заголовок). 4.Так же есть смысл ввести в заголовок некую преамбулу (набор из 2-5 символов идентифицирующих ваш тип файла) и версию файла. Это поможет при последующих модификациях структуры файла.
    5.Удобно проверять получившийся файл с помощью HEX редактора 010 Editor - там можно на бинарный файл накладывать структуру и просматривать уже структурированный файл. Структуры описываются в Си подобном стиле, так что научится можно за 20 минут на готовых примерах.
    Ответ написан
    Комментировать
  • Как из программы на c++ отправлять ответ на запрос в консоль linux?

    @res2001
    Developer, ex-admin
    Генерируйте random_port > 1024 и запроса на ввод пароля не будет.
    Ответ написан
    Комментировать
  • Как редактировать скрытые расширенные атрибуты файлов в windows?

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

    @res2001
    Developer, ex-admin
    Откройте для себя операцию взятия остатка от деления - % (в вашем случае на 10), с ее помощью ваша задача решается тривиально.
    Ответ написан
    Комментировать
  • Почему не работают массивы переменной длины?

    @res2001
    Developer, ex-admin
    Поддержка VLA (и вообще всех новых расширений языка), действительно, зависит от компилятора.
    Например в MSVC, по моему, до сих пор поддержки VLA нет.
    Официально микрософт заявляет о поддержке С90: https://docs.microsoft.com/en-us/cpp/c-language/an...
    Но в компиляторе присутствуют расширения языка (по умолчанию включенные), список расширений можно посмотреть в описании опции компилятора /Zc, и VLA там нет.
    При том, что присутствуют некоторые расширения из С++17.
    Кроме того присутствуют некоторые вещи, которые появились в С99, но их в "расширениях" нет, они уже вошли в компилятор "по умолчанию", например переменное количество аргументов в #define.
    Ответ написан
    2 комментария
  • Как используются ссылки и указатели в С++?

    @res2001
    Developer, ex-admin
    Указатель - это такая же переменная как и все остальные, т.е. область памяти для хранения целочисленного значения. Чтоб ее использовать, ее нужно сначала инициализировать корректным значением, иначе получите ошибку/предупреждение на этапе компиляции.
    Т.е. чтоб использовать *p, в p должно лежать корректное значение, поэтому перед этим оператором идет присваивание. В принципе ваш пример откомпилируется, но скорее всего он вызовет падение программы, т.к. адрес 0x1010101 взят с потолка и скорее всего укажет в нераспределенную область памяти. Может и не вызвать падение, тут уж как повезет.
    Ответ написан
    Комментировать
  • Как закрыть фоновый экземпляр программы?

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

    @res2001
    Developer, ex-admin
    Ваша функция работает делает свое дело за 1 проход по массиву, второй вариант - за shift проходов - сложность O(N) и O(N*shift) соответственно. Во втором случае скорость зависит от величины сдвига, что очень плохо для такого алгоритма.

    Циклический сдвиг массива "на месте" реализуется с помощью трех операций revers (операция изменения порядка элементов на противоположный):
    1.весь массив делится на 2 массива в точке сдвига (условно, без выделения памяти)
    2.revers первой части
    3.revers второй части
    4.revers всего массива
    Встречал на stackoverflow реализацию на Си.
    Работает за 2 полных прохода с операциями swap по массиву - O(2*N), но каждая операция тяжелее чем в ваших вариантах. Но быстродействие не зависит от величины сдвига и не требует дополнительной памяти, что может быть важно при работе с массивами большой размерности.
    UPD: вспомнил, этот способ был описан в книге Бентли "Жемчужины программирования"!
    Ответ написан
    Комментировать
  • С++ Как поменять символ на другой?

    @res2001
    Developer, ex-admin
    a[2]='n';
    В двойных кавычках - это строка с завершающим нулем, даже если она содержит 1 символ. В одинарных кавычках - символ.
    Ответ написан
    Комментировать
  • Какую литературу выбрать для изучения WINAPI?

    @res2001
    Developer, ex-admin
    PVOID - void*
    PWSTR - wchar_t *
    HANDLE - просто целое, подробностей, обычно, знать не нужно - это идентификатор объекта (хэндл).
    И берите Русиновича по совету 15432
    Ответ написан
    3 комментария
  • Как сделать невидимое консольное приложение - видимым?

    @res2001
    Developer, ex-admin
    Попробуйте в настройках службы, в командной строке запуска приложения, сделать перенаправление потоков стандартного вывода и ошибок в файл:
    proga.exe 1>praga.log 2>&1
    тогда сможете видеть в файле весь вывод приложения без окна. Файл должен быть доступен на запись для пользователя, под которым запускается приложение/служба.
    Настройки всех служб хранятся в реестре в HKLM\System\CurrentControlSet\Services
    Ответ написан
    1 комментарий
  • Альтернатива Visual Studio?

    @res2001
    Developer, ex-admin
    В качестве компилятора подойдет msys2/mingw64 или тот же микрософтовский компилятор, его можно установить отдельно от студии.
    На счет библиотек - в msys2 есть пакетный менеджер, можно установить огромное количество свободные библиотеки и использовать их. Для микрософтовского компилятора либо придется искать уже готовые бибилотеки, либо собирать самому из исходников (обычно это не вызывает особых проблем).
    Ответ написан
    Комментировать
  • VisualStudio не удается запустить программу. Не удается найти указанный файл.(?

    @res2001
    Developer, ex-admin
    Видимо программа не собралась. Может быть ошибка компиляции.
    Ответ написан