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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ошибки какой-то в коде не вижу.

    Попробуйте переписать с помощью std::next_permutation для перебора всех перестановок. Просто для сравнения и проверки теста - вдруг там опечатка.

    Оно будет работать медленнее рекурсивного перебора из-за отсутствия отсечений, да и одно и то же решение с циклическим сдвигом будет получатся n раз, но для 10 городов должно быстро отработать. Но зато код будет совсем простой: один цикл, как в примере из документации перебирает все перестановки от 0 до n-1. Внутри вы циклом эти числа берете как индексы городов и суммируете расстояния между ними + расстояние между последним до начального. И запоминаете, если сумма меньше известного минимума. Если и там 168 получится - в тесте опечатка.
    Ответ написан
  • Segmentation fault c++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Чему равно n, когда вы заводите массив a[n]?
    Ответ написан
    7 комментариев
  • Как оптимизировать мой код?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Передайте лямбду, которая вызывает перегруженный оператор вызова у вашей структуры:
    [](const man& item) { item(); }

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ошибка в push: prev предпоследнего элемента указывает на него же, а prev у последнего всегда null.

    Ошибка в result: вы переписываете значение последнего элемента зачем-то.

    Потом в цикле вы сначала удаляете элемент p, а потом переходите по p->next, читая уже удаленную память. Но это не беда, потому что второй цикл ни разу не выполняется (почему, догадаетесь?).

    В main вы зачем-то выделяете h и t, только чтобы сразу же устроить утечку этой памяти.
    Ответ написан
    2 комментария
  • Почему не работают заголовочные файлы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что так работает система "модулей" в СИ++ (никакие это не модули, а атавизм времен C без плюсов. От этого куча проблем, но по нормальному сделать никак не могут).

    Каждый cpp файл подключает объявления из остальных "модулей" через include хедеров. Потом каждый "модуль" собирается в объектный файл в котором есть реализации каких-то методов, а каких-то - нет, но они там используются. А потом линковщик собирает все объектные файлы в один исполняемый файл, где все-все-все реализованно.

    Вы же пытаетесь скомпилировать только один модуль сразу в исполняемый файл. Компилятор не находит реализацию класса A (она же в A.cpp. В A.h - только декларация).

    Если в проекте больше одного cpp файла - используйте систему сборки, вроде Cmake (есть и под windows).

    Или если хотите руками - тогда надо сначала собрать все объектные файлы и потом из них исполняемый:
    g++ -c a.cpp -o a.o
    g++ -c main.cpp -o main.o
    g++ a.o main.o -o main.exe
    Ответ написан
    4 комментария
  • Как перевести бинарную строчку в символ?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вряд ли. Есть, где из строки "00010100" в число. Но чтобы из такого формата - вряд ли. Можно руками элементарно же сделать:
    unsigned char ans = 0;
    for (i = 0; i < 8; ++i) {
      ans |= static_cast<unsigned int>(tableCombinationSymbol[i]) << i; // или (7-i), если порядок бит другой.
    }
    Ответ написан
    Комментировать
  • Как решить эту ошибку?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Перепишите этот ужас с нуля. Там невозможно найти ошибку.

    Советую воспользоваться тем, что условные операторы вычисляются лениво: Если написать A && B и A окажется false, то B даже не будет вычисляться.

    Так, проверка на клетку сверху может быть написана так:
    if (i > 0 && a[i-1][j] - мина)

    Так вся ваша простыня выродится в 8 последовательных проверок. Если меняются обе координаты, то надо через && объединить 3 условия - 2 на проверку невыхода за границы массива, и последнее - проверка значения массива.

    Еще можно завести массив на SIZE+2 x SIZE+2 и заполнять его с (1, 1). Фактически, создается каемка вокруг исходного массива. И пробегаться по нему надо от 1 до SIZE. Так, вокруг всегда будут все 8 соседей. В этом подходе не придется проверять на выход за границы массива.

    А еще можно вместо 8 if-ов сделать цикл на 8 итераций, если завести константы для приращений:
    const int kDx[] = {1, 1, 1, 0, -1, -1, -1, 0};
    const int kDy[] = {1, 0, -1, -1, -1, 0, 1, 1};


    Теперь всех соседей можно перебрать как (i + kDx[k], j + kDy[k])
    Ответ написан
    Комментировать
  • Как решить задачу?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если тут произвольная длина в смысле не "вам надо считать ровно 5 символов", то можно читать в std::string. Оно само выделит достаточно памяти.

    Вот так прочтется одно слово до пробела (или конца файла):
    std::string s;
    std::cin >> s;


    Вот так прочтется строка целиком до перевода строки (или конца файла):
    std::getline(cin, s);

    Потом можно по string проходится как по массиву, от 0 до s.length()-1.
    Ответ написан
    Комментировать
  • Ошибка xmemory при return, как пофиксить?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Скорее всего, тип User нельзя вот так вот читать и писать в файл. Подозреваю, что там содержатся std::string, которые сами в себе хранят лишь указатели на символы в строке. Поэтому, если std::string записать в файл как набор байт, то вы запишете в файл указатели. Прочитав их назад из файла, вы получите случайне адреса, не указывающие ни на что.

    Вам придется писать руками ввод и вывод типа из файла.
    Ответ написан
    1 комментарий
  • Как передать в лямбда функцию два аргумента?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам поможет std::bind.

    Передавайте в partition
    std::bind(predicate, item.first, std::placeholders::_1)
    в качестве предиката.

    Edit:

    Но тут у вас будет другая проблема. set - не vector. Вы не сможете его передать stable_partition. Вместо ручного применения stable_partition, используйте erase_if. Предикат туда также через std::bind передавайте.
    Ответ написан
    2 комментария
  • Как сделать вектор char беззнаковым числом?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Похоже практически все встроенные функции ожидают '\0' на конце входного буфера, что не ваш случай.

    Единственное исключение, которое я нашел - std::from_chars. Только оно далеко не везде доступно и надо подключать charconv.

    Еще можно руками, если точно известно, что никаких ошибок в числе нет:
    unsigned int vtoi(const std::vector<char> &a) {
      unsigned int res = 0;
      for (const auto& c: a) {
        res = 10*res + static_cast<unsigned int>(c) - static_cast<unsigned int>('0');
      }
      return res;
    }


    Проверки на переполнение и левые символы добавьте сами, если надо.
    Ответ написан
    Комментировать
  • Можно ли объявить и реализовать шаблонный метод класса в исходном файле в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Нет, все методы класса надо объявить в хедере (тем более публичные): иначе как пользователи класса смогут к нему обращаться? С простыми функциями так можно, если они не используются где-то извне. Или с классном можно, только если он весь целиком объявлен в cpp файле и, соответственно, его нельзя использовать вне этого файла.

    Можно еще перенести в cpp файл определение шаблонных классов/методов/функций, но для этого надо в хедере указать через forward declaration все используемые специализации шаблона. Например так:
    template <>
    int Database::RemoveIf<bool>(bool predicate);


    Конечно, там должен быть не bool а тип вашего предиката. И надо такие штуки воткнуть в хедер для ВСЕХ типов, которые в других файлах пихаются в шаблон.

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

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

    Вот пример: уже обновленная и отсортированная часть {1, 2, 3, 5, 6, 7}. Только что обновленный элемент имеет значение 4. lower_bound вернет итератор на 5. Вы поменяете 5 и 4 и получите {1, 2, 3, 4, 6, 7, 5} - не отсортировано уже.

    Можно удалить элемент в it и вставить на новое место через insert, но тогда могут быть проблемы с итератором цикла. Можно ручками через swap сдвигать элементы в цикле:
    T tmp = it->value;
    for (auto cur = std::lower_bound(vector.begin(), it, (*it)); cur < it; ++cur) {
       swap(tmp, cur->value);
    }
    it->value = tmp;


    Это, фактически, будет сортировкой вставкой за O(N^2). lower_bound за логарифм тут на самом деле даже лишнее и только замедляет сортировку. Лучше одним циклом сразу и swap-ать и сравнивать элементы.

    Но еще быстрее будет отдельно пройтись по массиву и обновить его целиком и потом вызвать std::sort для сортировки по value.
    Ответ написан
    Комментировать
  • Массив: Повернуть массив V на 90° и занести в массив Н все парные элементы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ну нарисуйте на бумажке матрцу, скажем 4x4, заполните числами от 1 до 16 и рядом нарисуйте ее же повернутую на 90 градусов. Посмотрите внимательно, куда попадают числа. Возьмите произвольную ячейку [i][j] и подумайте, куда она в итоге попадает. Если не можете так сообразить, выпишите для чисел 1,2,5,7,13 их индексы в первой и второй матрице в 4 столбика и посмотрите на закономерности между индексами.
    Ответ написан
    Комментировать
  • Как оптимизировать поиск в ширину?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Мне в третий раз повторить?
    Ответ написан
    Комментировать
  • Как передать массив в конструктор класса?

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

    Вместо SegmentTree tree = new SegmentTree(a, n);
    надо
    SegmentTree tree(a, n); или SegmentTree *tree = new SegmentTree(a, n);

    new - создает указатель. Инициализировать им нужно, соответственно, указатель.
    Ответ написан
  • В чем причина возникновения ошибки std::bad_alloc при поиске в графе?

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

    Вы там еще очередь pop-аете раньше времени.
    Ответ написан