Задать вопрос
Ответы пользователя по тегу C++
  • Как исправить заполнение массива минимальными значениями другого массива?

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

    @res2001
    Developer, ex-admin
    У вас в коде забито другое выражение: (a + b) * (c - d)
    Где реализация стека?

    По реализации:
    1. Для вычислений вам не нужны 4 переменные или 10 (в зависимости от того сколько в выражении), достаточно двух для обычных бинарных операций (с двумя операндами). Результат промежуточного вычисления нужно снова вставлять в стек в место вытащенных операндов и операции.
    2.Алгоритм вычисления по прямой польской нотации неплохо описан на вики.
    нужно считывать выражение слева направо, рассматривая оператор и ближайшие к нему два операнда. Если среди этих операндов находится еще один оператор, то вычисление первого оператора откладывается, до тех пор, пока не будет вычислен новый оператор. Итерации этого процесса повторяются до тех пор, пока оператор не будет вычислен, что должно в конечном счете произойти, если в выражении количество операндов на один больше, чем количество операций (в случае бинарных операций). Как только оператор вычислен, он и его два операнда заменяются полученным значением (операндом). Поскольку оператор и два операнда заменяются на вычисленный операнд, то становится на один оператор и один операнд меньше.

    Таким образом стек тут не очень подходит, кроме операций push и pop нужно еще делать и обход списка в прямом направлении и вставка/удаление элементов в произвольной позиции.
    Либо как вариант со стеком - использовать 2 стека. Т.е из одного извлекаете отложенные и результаты вычислений помещаете во второй пока первый не опустеет, затем переключаетесь на второй и так до тех пор пока в стеке не останется единственное значение - результат вычислений.
    Либо с одним стеком, но изменить реализацию. Так чтобы не было структуры P_STACK.
    Ответ написан
  • С++ - как отсортировать структуру?

    @res2001
    Developer, ex-admin
    Реализуйте в структуре конструктор копирования и/или копирующий оператор присваивания, и сортируйте пузырьком (т.к. самая простая реализация соритровки). Можно еще реализовать несколько функций сравнения по разным атрибутам и передавать эти функции в пузырек (чтоб можно было делать сортировку по разным атрибутам с помощью одной функции сортировки).

    По коду:
    1.Вы начинаете писать на С++, а потом перескакиваете на Си (puts, printf) ...
    2.В struct student поля surname и gr объявлены как char, а в коде вы их используете как си-строки - это абсолютно разные вещи.
    3.Вы не правильно используете функцию puts. В таком виде у вас программа не соберется. Посмотрите документацию.

    Возможно что-то еще ...
    Ответ написан
    Комментировать
  • Можно воспользоваться HINSTANCE exe файла для поиска адреса функции?

    @res2001
    Developer, ex-admin
    NtCreateFile находится в NtDLL.dll
    Думаю, что можно использовать LoadLibrary/GetProcAddress для загрузки библиотеки и адреса функции.
    Ответ написан
    2 комментария
  • Как записать звук с микрофона и колонок в один поток?

    @res2001
    Developer, ex-admin
    Не знаю как это в DirectShow, но теоретически просто поэлементно сложить оба потока, при одинаковой частоте дискретизации. Если частота дискретизации различается, нужно привести к одной, а потом все равно сложить.
    Ответ написан
  • Как заставить std::array различать родителя и наследника?

    @res2001
    Developer, ex-admin
    Танцы с virtual. Для того они и придуманы.
    Тут еще вопрос в том как именно вы помещаете объекты в std::array и какие именно это объекты. В вашем случае вам нужно помещать в массив либо ссылки, либо указатели (умные), иначе рискуете словить проблемы.
    Ответ написан
    Комментировать
  • Как итерируется ranged for?

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

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

    Вообще Рихтер хорошо пишет, попробуйте перечитать :-)

    Виртуальная память не "взаимодействует с ОЗУ" - ОЗУ неотъемлемая часть виртуальной памяти.
    Ответ написан
    2 комментария
  • Как сделать выход из цикла ввода строк в vector?

    @res2001
    Developer, ex-admin
    Оператор break.
    Ответ написан
    Комментировать
  • Связь между cpp файлами? Как можно получить и записать значение переменной из одного cpp в другой?

    @res2001
    Developer, ex-admin
    Возвращайте значения из одной функции и передавайте их в другую как параметры.
    Вернуть 2 значения можно в структуре или с помощью входных параметров ссылок. Пример.
    void writeCfgFile(int & directX, int & analogX){
           analogX =6;
           discretX=8;
    }
    void writeBinaryFile(int directX, int analogX) {
    }
    main() {
    int analog, direct;
    writeCfgFile(direct, analog);
    writeBinaryFile(direct, analog);
    }

    Когда нужно возвращать много значений, то их объединяют в структуру и точно таким же образом заполняют структуру.
    Глобальные переменные - это, конечно, просто и работает, но это не правильный подход.
    Ответ написан
    Комментировать
  • Как инжектить DLL через текстовый редактор?

    @res2001
    Developer, ex-admin
    :-) не верьте глазам своим. Скорее всего в текстовом редакторе правится конфиг для инжектируемой библиотеки. Сама библиотека отслеживает изменение конфига и перечитывает его.
    Ответ написан
    Комментировать
  • Почему буфер приема WinSock заполняется мусором?

    @res2001
    Developer, ex-admin
    А если я смотрю strlen(recvbuf) то получаю 16. Откуда берется такой хвост?

    В recvbuf вы получаете не с-строку, а массив байт, применять строковые функции к массиву байт бессмысленно.
    Отличие с-строки от массива в том, что строка оканчивается завершающим нулем, а в массиве байт вы должны знать длину массива. В с-строке символ 0 не может быть в теле самой строки, только в качестве терминального символа, в массиве байт 0 - такой же равноправный элемент данных, как и все остальные, может быть в любом месте массива или не быть вовсе.
    Вам еще повезло, что выдает 16 байт, вместо 4, вполне могло бы сложиться так, что нулевого байта не было бы на достаточно продолжительном участке памяти, тогда был бы просто вылет из программы или какие-либо трудно диагностируемые глюки.
    Ответ написан
    5 комментариев
  • Что делать с 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 комментарий