Ответы пользователя по тегу C++
  • Почему массив заполнился буквой H?

    Память не инициализирована, поэтому там мусор. Что именно -- Unspecified Behavior.
    Ответ написан
    6 комментариев
  • Чему будет равно i при таком необычном указателе?

    1028. При инкременте указателя к нему добавляется sizeof от того, на что он указывает, то есть
    i++;
    эквивалентно
    (int&)i += sizeof(uint32_t);

    По поводу скомпилировать, если задать язык как C, а не C++, то он это проглотит, так как менее строгий в плане приведения типов (целое число приводить к указателю не безопасно). Чтобы скомпилировать в C++, нужно немного подправить код.
    Ответ написан
    1 комментарий
  • Как заставить C++ не деконструктить экземпляр класса лишний раз в конце цикла?

    Используйте передачу по ссылке:
    for (auto& neuron : neurons)

    Иначе при обходе цикла вы скопируете весь массив. А то, что конструктор вызывается только вначале, — очень странно, скорее всего, это ещё один баг. Можно увидеть всё объявление класса neuron (без реализации функций)?
    Ответ написан
  • Как неопределенное поведение в javascript складывается на уровне V8?

    NaNNaNNaNNaNNaN Batman!
    Если серьёзно, то это неявные приведения типов операндов. Вот отличное объяснение.
    Ответ написан
    5 комментариев
  • Передача функции - шаблоны или std::function?

    Первый вариант:
    template<typename Func> void MyFunc (const Func & otherFunc);

    Гарантирует, что otherFunc будет заинлайнена в MyFunc, то есть такой вариант предпочтителен там, где требуется максимальная производительность. Но шаблонные функции не могут быть виртуальными. То есть такой вариант очень хорошо подходит для функций-утилит, и плохо подходит для методов публичного API и на границах модулей, так как там как раз инлайн не нужен, а нужны виртуальность и сокрытие реализации.

    Важное замечание! Приведённый код не совсем корректен, всегда в таких случаях используйте передачу по универсальной ссылке:
    template<typename Func> void MyFunc (Func&& otherFunc);

    Такой вариант покрывает и константные функторы, и те, которым необходима мутабельность для работы. Если вы планируете сохранить функтор, то это ещё и позволит воспользоваться perfect forwarding -- по сути, единственный способ, корректно работающий с любым переданным функтором:
    field = std::forward<Func>(otherFunc);

    Второй вариант:
    void MyFunc (const auto & otherFunc);
    Можно использовать, если вам не нужен тип функтора. По сути он эквивалентен предыдущему.

    Третий вариант:
    void MyFunc (const std::function<void()> & otherFunc);

    Возьмите отрицание моих предыдущих аргументов и примените сюда. Можно использовать с виртуальными функциями, больше подходит для API, но теряет в производительности. А именно, вызов otherFunc эквивалентен вызову виртуальной функции.

    Четвёртый вариант:
    void MyFunc (const void (&otherFunc)());
    Работает только с простыми, глобально определёнными функциями. Вместо этого практически всегда стоит использовать std::function.
    Ответ написан
    Комментировать
  • Лучший вариант проверки ввода на несколько условий в C++?

    Можно немного упростить код:
    while (true) {
      cin>>x;
      if (x < 0) {
        cout<<"x должно быть положительным числом"<<endl;
      } else if (x == 0) {
        cout<<"x не должно равняться нулю"<<endl;
      } else if (x == 5) {
        cout<<"x не должно равняться пяти"<<endl;
      } else {
        break;
      }
    }
    Ответ написан
    Комментировать
  • Как отсортировать строки в алфавитном порядке в СИ?

    Нужно воспользоваться qsort.
    Функция сравнения:
    int compare_prices(const void* price1, const void* price2) {
        const char* name1 = ((const price*)price1)->name;
        const char* name2 = ((const price*)price2)->name;
        return strcmp(name1, name2);
    }

    Вызов qsort:
    qsort(МАССИВ_СТРУКТУР, РАЗМЕР_МАССИВА, sizeof(price), &compare_prices);
    Ответ написан
    Комментировать
  • Ошибка: no matching constructor for initialization, что делать?

    Неправильно объявлен конструктор копирования и оператор присваивания:
    TemplateRequirement(TemplateRequirement &);
    TemplateRequirement& operator=(TemplateRequirement&);

    Надо так:
    TemplateRequirement(const TemplateRequirement &);
    TemplateRequirement& operator=(const TemplateRequirement&);

    Ещё советую заменить параметры типа QString и QString& на const QString&.
    Ответ написан
    3 комментария
  • Как создать палитру цветов для bmp изображения?

    Можно применить Median cut.
    Суть алгоритма заключается в следующем:
    1. Создаём одну корзину (вектор) со всеми пикселами изображения
    2. Определяем цветовую компоненту (R, G или B), по которой диапазон значений (max - min) в корзине наибольший
    3. Находим медиану этого цвета и разбиваем корзину на две
    4. Повторяем шаги 2 и 3 до достижения нужного числа корзин
    5. Далее можно, например, найти в каждой корзине средний цвет и создать std::unordered_map из текущего цвета в усредненный
    Ответ написан
    Комментировать
  • Как превратить очередь в 2 очереди?

    Не разобрался, в чем проблема, вот рабочее решение:
    spoiler
    #include <stdlib.h>
    #include <stdio.h>
    
    struct TNode {
    	int data;
    	struct TNode *next;
    };
    typedef struct TNode Node;
    
    struct TQueue {
    	Node* head;
    	Node* tail;
    };
    typedef struct TQueue Queue;
    
    Queue* newQueue()
    {
    	Queue* queue = malloc(sizeof(Queue));
    	queue->head = NULL;
    	queue->tail = NULL;
    	return queue;
    }
    
    void deleteQueue(Queue* queue)
    {
    	Node* current = queue->head;
    	while (current != NULL) {
    		Node* next = current->next;
    		free(current);
    		current = next;
    	}
    	free(queue);
    }
    
    void pushBackQueue(Queue* queue, int data)
    {
    	Node* newNode = malloc(sizeof(Node));
    	newNode->data = data;
    	newNode->next = NULL;
    
    	if (queue->tail == NULL) {
    		queue->head = newNode;
    		queue->tail = newNode;
    	}
    	else {
    		queue->tail->next = newNode;
    		queue->tail = newNode;
    	}
    }
    
    void splitQueue(Queue* source, Queue* even, Queue* odd)
    {
    	for (Node* current = source->head; current != NULL; current = current->next) {
    		int data = current->data;
    		pushBackQueue((data % 2 == 0) ? even : odd, data);
    	}
    }
    
    void printQueue(Queue* queue)
    {
    	for (Node* current = queue->head; current != NULL; current = current->next) {
    		printf("%d ", current->data);
    	}
    	printf("\n");
    }
    
    int main()
    {
    	Queue* source = newQueue();
    	for (int i = 0; i < 20; i++) {
    		pushBackQueue(source, i + 1);
    	}
    	printQueue(source);
    
    	Queue* even = newQueue();
    	Queue* odd = newQueue();
    	splitQueue(source, even, odd);
    	printQueue(even);
    	printQueue(odd);
    
    	deleteQueue(source);
    	deleteQueue(even);
    	deleteQueue(odd);
    
    	system("pause");  // not needed in Linux
    	return 1;
    }


    И лучше убрать C++ из заголовка, иначе возникают вопросы типа "почему без классов" и "почему не std::linked_list".
    Ответ написан
    2 комментария
  • Как правильно построить структуру программы?

    Поиграйтесь с cv::rectangle, cv::addWeighted и cv::putText.
    Вот код прямиком из рабочего проекта, рисует полупрозрачный прямоугольник и пишет строки текста:

    cv::Mat writeOnImage(const cv::Mat& source, const std::vector<std::string>& lines, int width)
    {
    	auto rect = source.clone();
    	cv::rectangle(rect, { 10, 10 }, { width, 20 + 50 * static_cast<int>(lines.size()) }, cv::Scalar(0, 0, 0), cv::FILLED);
    
    	auto result = cv::Mat();
    	cv::addWeighted(source, 0.6, rect, 0.4, 0.0, result);
    
    	for (size_t i = 0; i < lines.size(); ++i) {
    		cv::putText(result, lines[i], { 20, 50 + 50 * static_cast<int>(i) }, cv::FONT_HERSHEY_PLAIN, 3, cv::Scalar(10, 255, 255), 3, cv::LINE_8);
    	}
    
    	return result;
    }
    Ответ написан
    1 комментарий