Задать вопрос
  • Почему после вызова Message Box, GetKeyState() не считывает состояние клавиши?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Диалоговое окно-то появляется?

    Я подозреваю, что MessageBox возвращает 0, что происходит происходит при ошибке:
    If the function fails, the return value is zero.


    Поэтому цикл while завершается. Т.е. проблема не с GetKeyState, а логикой программы.
    Ответ написан
  • Как реализовать copy on write class?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Сам класс хранит умный указатель на буфер данных.

    Нужен счетчик ссылок на буфер. Перед записью проверяйте, что счетчик равен 1. Иначе копируете данные и в текущем объекте заменяете указатель на новый буфер.

    Счетчик должен храниться где-то вместе с буфером и является частью умного указателя.

    Можно использовать std::shared_ptr - там уже этот счетчик реализован (use_count).
    Ответ написан
    Комментировать
  • Как копировать список в си (C)?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Пройтись по списку, добавляя элементы в конец нового списка.
    Только не надо использовать вашу функцию add - она каждый раз проходится по всему списку. Заведите отдельную переменную, которая будет указывать на конец создаваемого списка и добавляйте новый элемент к ней.
    Ответ написан
    Комментировать
  • Как распределить документы среди людей по ключевым словам?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Определите какую-то метрику. Или количество общих слов у человека и документа или как-то оно нормализованное, вроде какая часть их слов у них общая. После построения матрицы растояния уже можно решать вашу задачу.

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

    Если надо как-то нормировать нагрузку, то тут возникает задача назначения, которая может решаться алгоритмом максимального потока минимальной стоимости. Можно вводить штрафы на перегрузку каждого человека и тогда алгоритм может выдавать документы не ближайшим людям, у которых мало работы.
    Ответ написан
    Комментировать
  • Какой паттерн, как организовать структуру проекта для разных форматов пикселей RGB и YUV?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Я бы посоветовал делать абстракцию не на уровне пикселя, а на уровне картинки. Ибо так можно оптимальнее организовывать расположение пикселей в памяти да и обрабатывать изображение быстрее. Вместо функции, которая для каждого пикселя проверяет, а что там у него брать R или Y, используют функции, которым передается plane - один канал. Что там конкретно R, G, Y, V - обычно не важно. Если вы ищете контур или сглаживаете изображение, то работа идет абсолютно одинаково в каждом канале.

    В качестве примера можно посмортреть вот тут или тут.
    Ответ написан
    Комментировать
  • Что делать если при отладке сработала точка останова по исключению?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    char str = 0, *pStr = &str;

    Очень, очень не правильно так делать. Строка - это массив char в памяти. Указатель указывает на начало этого куска в пямяти. Вы же берете одну переменную, и потом работаете с ней как с массивом.

    Надо выделять память под строку. Или статический массив, или malloc.
    Ответ написан
    Комментировать
  • Как вырезать область изображения под контуром, Алгоритм?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    FillPolygon работает через обход в ширину.

    Сначала одним циклом покрасьте все точки контура.
    Потом берите любую точку внутри полигона, красьте ее и кладите в очередь. Пока очередь не пуста берете точку оттуда, берете 4 или 8 ее соседей и если они не покрашены еще - красите их и кладете в очередь.

    Может быть сложность с выбором самой первой точки внутри полигона. Но тут можно аккуратно пройтись вдоль полигона против часовой стрелки и взять первую непокрашенную точку слева относительно обхода. Тут можно для каждой точки найти вектора на двух соседей по контуру, потом перебрать 4-8 соседних пиксилей и взять тот непокрашенный, вектор на который лежит между двумя векторами вдоль контура.
    Ответ написан
    Комментировать
  • Почему в массив записываются числа не и указанного диапазона?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    *p = (rand( )%100 - 50);
    for (int i = 1; i < k; i++) {
      *(p + 1) = -i * * (p + i - 1);
    }


    Можете вообще объяснить, что этот код делает? Зачем он это делает? Что вы хотели, чтобы он делал?

    Помимо этого, вместо *(p+X) можно писать p[X]. Так понятнее. У вас тут явно не к месту арифметика указателей приплетена.

    А так, код работает так, как написан. Первое число в массиве заполняется случайным от -50 до 49, второе число много раз переписывается чем-то умноженным на какое-то другое число массива, остальные числа не заполняются вообще.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    В деструкторе удаляйте, только если память не nullptr или длина не 0.
    Ответ написан
    Комментировать
  • Из-за чего может быть access violation при решении этой задачи?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    access violation явно говорит о проблеме работы с памятью.

    Единственное спорное место - это ввод. Может в файле есть лишние переводы строк или кривые тесты (пропущено какое-то число). Ваша программа, похоже, в этом случае попытается обратиться к N[1] и упадет, потому что в строке только 1 или вообще 0 чисел.

    Перепишите ввод. Сделайте класс, который хранит текущий массив токенов. При запросе следующего - возвращает следующий, если токенов больше нет - читает еще строку, пока в ней не окажутся токены.

    Ну или читайте тупо функциями чтения чисел. В этой задаче входной файл маленький - можно спокойно читать по одному числу, даже если это будет медленнее.
    Ответ написан
  • Из за чего появляется ошибка ошибка ld returned 1 exit status?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Выше написанно undefined reference to 'processingArray(int*, int)'


    Ну вот. У вас функция processingArray объявлена, но нигде не реализована. Тело функции где? Поскольку вы ее объявили, компилятор это безобразие проглатил и понадеялся, что эта функция реализована в другом файле и на этапе линковки она найдется. Но линкер ее не нашел, потому что ее нигде и нет.

    Вы, видимо, не все из учебника переписали. Там после функции main скорее всего идет реализация функции processingArray.
    Ответ написан
    7 комментариев
  • Как решить проблему Segmention Fault?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Segmentation fault - это ошибка работы с памятью. Или выход за границы массива, или что-то не так с указателями.

    Я подозреваю, что в файле у вас не 50 строк (мне лень считать). Вот вы и вылезаете за границу массива.

    Ну или там какие-то лишние переводы строк, пробелы имеются. поэтому fin.eof() не выполняется после считывания последней строки. Потом вы пытаетесь что-то еще прочитать, но получаете назад пустую строку. Это бы не было проблемой, но вы потом пытаетесь это все запихать в 51-ый элемент массива.

    Советую вместо define N и статического массива использовать std::vector. В цикле считывания файла делайте push_back нового объекта в вектор (а еще лучше, emplace_back для экономии лишнего копирования).

    При выводе берите size() у вашего вектора.

    Если вы в выводе заметите лишнюю книгу в конце с пустыми данными, то можно добавить проверку при вводе - если хоть одна из 5 строк пустая - то не надо создавать новую книгу.
    Ответ написан
    Комментировать
  • Как составлять header файл для статической библиотеки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    А зачем это делать? Чем вас 8 хедеров не устраивают? Если уж так хочется сэкономить строчки в коде пользователей библиотеки, то можно воспользоваться рекурсивностью препроцессора и сделать хедер с 8 инклудами. Копипастить код точно не надо.
    Ответ написан
    1 комментарий
  • Перебрать все комбинации массивов строк?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Рекурсивная функция должна принимать текущий набор строк и номер следующего массива. Функция циклом перебирает строку из следующего массива, добавляет эту строку к текущему набору и вызывается рекурсивно. После вызова последнюю строку надо из текущего набора удалить. Если в начале функции вы видите, что обработаны уже все массивы - выводите текущий набор в ответ и возвращайтесь из функции.

    Еще, естественно, надо передавать в функцию массив массивов строк - ваши исходные данные.
    Ответ написан
    Комментировать
  • Нужно ли строго проверять if?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    А почему не рассматривается третий вариант? Что-нибудь вроде
    if (ToString(exampleVar)[0].length() == 4) alert(1)


    Умышленно писать === true, конечно может быть иногда оправданно в языках без строгой типизации, но в целом это довольно редко оправданная вещь.
    Ответ написан
    Комментировать
  • В чём ошибка реализации алгоритма Прима?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if ((matrix[i][j] < minValue[j]) && (isPartOfOutputTree[j] == false))


    Вот тут ошибка. Ведь i - это номер итерации,а совсем не только что включенная в дерево вершина, относительно которой надо сделать релаксацию.
    Ответ написан
  • Почему при копировании файлов получаются битые файлы?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Аккуратно выведите куда-нибудь параметры, которые вы передаете в функцию создания symlink.

    Похоже, проблема в том, что вы передаете относительные, а не абсолютные пути в качестве цели для линка.
    При использовании функции копирования это, возможно, и не будет проблемой.
    Ответ написан
    8 комментариев
  • Как обвести множество точек на карте?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вот алгоритм выделения граней планарного графа: https://e-maxx.ru/algo/facets

    Сначала вам придется попересекать отрезки друг с другом и получить граф: вершины - точки пересечения и концы отрезков, ребра - куски отрезков. Потом выделяете алгоритмом выше внешнюю и внутренние грани.

    Потом их сглаживаете. Внешнюю грань - наружу, внутренние - внутрь. Тут придется как-то эвристически действовать. Например, берете любую точку на контуре, если две ее соседние достаточно близки, то выкидываете текущую точку. Если внутренняя грань становится достаточно маленькой по площади - выкидываете ее целиком.

    Upd: Дополнение - выбрасывать можно только точки, "вогнутые" внутрь полигона, такие, что их удаление только сделает внешнюю часть больше, а внутреннюю меньше.

    В итоге, если удачно подобрать границы в алгоритме выше, то получится примерно как у вас на картинке.
    Ответ написан
    Комментировать
  • Как удалить первый элемент однонаправленного списка в с++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С односвязными списками сложно - надо знать предыдущий элемент, чтобы у него поменять ссылку на следующий через удаляемый элемент. Можно или поддерживать 2 указателя на 2 соседних элемента, или смореть на следующий элемент через next, пока у вас есть указатель на предыдущий к нему.

    Еще отдельная проблема с удалением первого элемента, потому что там менятся должна не ссылка next у предыдущего элемента, а ссылка на начало списка. Эту проблему можно решить по разному. Например, можно вместо указателя head держать один элемент списка без значения. Тогда указатель на начало списка будет менятся также как и любой другой. Фактически, в любом списке всегда будет один фиктивный элемент. Этот способ также предподчителен для работы с двусвязными списками. Тогда список как бы замыкается в кольцо и не надо разбирать отдельно ни случай первого, ни случай последнего элемента. Мне больше нравится другой метод - можно помнить не предыдущий элемент, а указатель-на-указатель, который надо будет поменять.

    node** prev_link = &head;
    node* cur = head;
    for  (node* cur = head; cur != nullptr; cur = cur->next) {
      if (cur->val == to_del) {
        *prev_link = cur->next;
        delete cur;
        break;
      }
      prev_link = &cur->next;
    }
    Ответ написан
    1 комментарий
  • Возможен ли треугольник по стороне, углу и пропорциональным сторонам?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Треугольник можно составить из любых трех отрезков, пока выпонляется неравенство труегольника a+b > c, a+c > b, b+c > a. достаточно проверять только одно из них - максимальное число должно быть меньше суммы остальных. Но если не очевидно, какое из них максимальное, то можно проверять все три.

    Итак, дано только A и k, так?

    Чтобы как-то угол связать со сторонами надо воспользоваться теоремой косинусов:

    c^2 = a^2+b^2-2*a*b*cosA.
    подставив суда b=ck, получим
    с^2 = a^2+k^2c^2-2*k*a*c*cosA

    Это квадратное уравнение, связывающее C и A. Можно решить его относительно a (c - параметр) и вы получите а, выраженное через с.

    Ну и в конце надо проверить, что a+b > c, a+c > b, b+c > a, подставив туда найденные формулы для b и a через c. В этих неравенствах будут известные cosA, sinA, k и неизвестная с. Поскольку тругольник по углу и соотношению сторон можно масшабировать, то неравнество должно выполнятся для всех c. Но на самом деле в этих неравенствах все c можно будет тупо сократить. Какие-то из них можно сразу же выкинуть, если рассмотреть 2 случая k>1 и k<=1. Ну а как их дальше решать - думайте сами.
    Ответ написан
    3 комментария