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

    Хорошо сформулированный вопрос - половина ответа.
    Что значит "ничего не рисуется"? Нет никаких точек?
    Тогда проверяйте, а рисуется ли просто точка хоть где-нибудь. Если нет - ищите, почему.
    К тому же, кривую лучше рисовать из маленьких отрезков, а не из точек. Т.е. надо считать "предыдущую точку" и "текущую точку", проводить (рисовать) отрезок; затем переходить к новой точке, сохраняя "текущую" в "предыдущую", и так далее.
    Попробуйте нарисовать отрезки P0-P1, P1-P2, чтобы вообще оценить опорные точки безье на картинке, а затем уже проводите какие-то рассчёты, может, проблема в рассчётах.
    Ну и так далее, потом видно будет, в чем проблема.
    Ответ написан
    Комментировать
  • Как вернуть массив?

    Зачем вам его возвращать?
    В Си++ нельзя передать массив по значению (только если он не составная часть структуры), вместо этого передают указатель на первый элемент массива, как у вас. Соответственно, все изменения, который вы проводите над int * minArr внутри search_min_elements_of_array отражаются на массиве int minArr[m/2], и отдельно что-то возвращать не надо.

    Также стоит перенести определение (тело) функции search_min_elements_of_array за пределы (перед) main, ну и вызов у вас неверный:
    // int minArray[m/2] = search_min_element_of_array(int array[][3], int *minArr); // больше похоже на объявление функции
    search_min_element_of_array(array, minArr);
    Ответ написан
    Комментировать
  • Как исправить Stack Overflow при рекурсии с использованием std::thread и templates?

    Не вчитывался в алгоритм, но, если верно понимаю, чем меньше N, тем больше глубина рекурсии, оттуда и stack overflow. Дело не во входной последовательности, а в локальных переменных и аргументах функции. Так что меняйте на цикл.

    Что касается Access Denied и прочих, скорее всего другие ошибки есть.
    Ответ написан
    Комментировать
  • Сможете объяснить решение олимпиадной задачи?

    Задача сводится к выяснению того, сколькими кубиками (не способами, а именно кубиками) может быть задана исходная сумма (нижних граней).
    Например, 1 может быть задано только 1-м кубиком, ответ - 1
    2 может быть задано как 1-м, так и 2-мя кубиками, ответ - 2
    3 может быть задано 1-м, 2-мя или 3-мя кубиками, ответ - 3.
    Рассмотрим 4. Может быть задано от 1-го до 4-х кубиками. Т.е. ответ - 4. Рассмотрим случай 2-х кубиков. Это могут быть комбинации 2 + 2 или 1 + 3, но оба они дадут одну и ту же сумму верхних граней: 6 + 6 - (2+2) или 6 + 6 - (1+3), что явно одно и то же.
    У разных же количеств кубиков сумма разная, так как разное кол-во 6-к (самых больших чисел).

    Итак, надо выяснить, сколькими кубиками можно задать сумму s. Понятно, что если s ≤ 6, то любым кол-вом от 1 до s. Но если s > 6, то одним кубиком уже не задать. Если s > 12 (6 * 2), то не задать уже и двумя.
    Т.е. если s > 6, надо вычесть 1, если s > 12, надо вычесть 2, если s > 18, то вычесть 3.
    Или, иначе говоря, если s > 6k, надо вычесть k. k можно посчитать как (s - 1) / 6 (целочисленное деление). Как только s становится больше 6k, то есть становится 6k + 1, получаем (6k + 1 - 1) / 6 = k. Если же s = 6k, то (6k - 1) / 6 = k - 1, что нам и надо.
    Т.о. результат: s - (s - 1) / 6, что эквивалентно вашей формуле, так как
    (s + 5) / 6 = (s - 1) / 6 - 1
    (s + 5) / 6 - 1 = (s - 1) / 6
    Ответ написан
    5 комментариев
  • Когда допустимо возвращение ссылки в функции? Когда ссылки на константу?

    Отличаются тем, что во втором случае объект по ссылке изменять нельзя. От возврата по значению отличаются тем, что при возврате по значению происходит копирование объекта со всеми вытекающими:
    1. Это может быть накладно
    2. Результат - это копия, поэтому изменения, внесённый в неё - это изменения в копии, а не в том объекте, который возвращался. По этой причине, например, operator [] у класса-массива должен возвращать ссылку, чтобы изменяя полученную ссылку, изменялось бы значение, которое лежит в массиве.

    Ссылка в этом смысле не отличается от указателя, кроме того, что не может быть null. Поэтому нельзя, например, возвращать ссылку на какую-то временную переменную:
    int & foo()
    {
      int x = 100;
      return x;
    }
    int main()
    {
      int & y = foo();
      y = 10; // UB
    }

    Переменная x тут умрёт по выходе из foo, и y будет ссылаться на уже мёртвую переменную. Но можно возвращать ссылку на член класса, если объект класса будет жить дольше, чем ссылка. Т.е. так можно:
    class Test
    {
      int x;
    public:
      int & getx() { return x; }
    };
    int main()
    {
      Test t;
      int & y = t.getx();
      y = 10; // t.x будет равен 10
    }

    А вот так опять нет:
    class Test
    {
      int x;
    public:
      int & getx() { return x; }
    };
    int main()
    {
      int * y;
      {
        Test t;
        y = &t.getx();
      }
      *y = 10; // UB, t умирает в конце блока, x тоже, а обращение идёт уже после
    }
    Ответ написан
    1 комментарий
  • Как найти ошибку в коде (Игра "Жизнь")?

    1. Минимизируйте неправильный пример. Что именно неправильно? Полоска, квадрат?
    2. Создайте как можно меньший пример, который работает некорректно, а с ним уже работайте отладчиком.
    Ответ написан
    Комментировать
  • Когда неявно вызывается деструктор?

    Драфт стандарта n3337:

    Destructors are invoked implicitly
    — for constructed objects with static storage duration (3.7.1) at program termination (3.6.3),
    — for constructed objects with thread storage duration (3.7.2) at thread exit,
    — for constructed objects with automatic storage duration (3.7.3) when the block in which an object is created exits (6.7),
    — for constructed temporary objects when the lifetime of a temporary object ends (12.2),
    — for constructed objects allocated by a new-expression (5.3.4), through use of a delete-expression (5.3.5),
    — in several situations due to the handling of exceptions (15.3).
    Ответ написан
    Комментировать
  • Как написать интерфейс и реализацию шаблонного класса в c++?

    Реализацию тоже в hpp.
    Для каждого параметра T генерируется своя функция, а потому их потенциально бесконечно много, поэтому они должны быть доступны в исходном коде, а не линковаться отдельно.
    Конечно, можно явно инстанцировать для нужных типов, но в вашем случае ни к чему.
    Ответ написан
    Комментировать
  • Как исправить ошибку?

    Вообще говоря C++ строки так не сортируют, так как они - не-POD. По факту в данном случае qsort меняет местами внутренности std::string, что напрямую делать нельзя (UB).
    Сортировать не-POD типы надо при помощи std::sort.
    Да и вообще, std::sort - шаблонная функция; лучше инлайнится, чем qsort, а посему лучше использовать его в C++ коде.

    #include <string>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    
    int str_compare(std::string const & l, std::string const & r)
    {
    	if (l == r)
    		return 0;
    	return l < r ? -1 : 1;
    }
    int str_compare(void const * l, void const * r) { return str_compare(*static_cast<std::string const *>(l), *static_cast<std::string const *>(r)); }
    
    int main()
    {
    	std::string strs[3] = { "foo", "bar", "baz" };
    	std::qsort(strs, 3, sizeof(std::string), str_compare); // В общем, работает, но UB
    	// std::sort(&strs[0], &strs[0] + 3); // вот так - лучше
    	for (auto & s : strs)
    		std::cout << s << std::endl;
        return 0;
    }
    Ответ написан
  • Чем отличается синхронный сервер от асинхронного сервера в boost?

    Сразу оговорюсь, могу ошибаться, я boost asio не использовал

    С синхронным всё верно. При этом клиенты обрабатываются по очереди.
    С асинхронным иначе.

    1. В конструкторе tcp_server зовётся start_accept, который зовёт async_accept и возвращается управление обратно.
    2. Затем зовется io_service.run(), судя по всему, где-то внутри он-таки принимает подключение и вызывает handle_accept, который был забинжен при start_accept и пункта 1.
    3. handle_accept зовёт start, который зовёт async_write, т.е. не дожидается отправки данных, а опять же сразу возвращает управление. По окончании отправки вызовется handle_write
    4. затем снова start_accept -> async_accept и возврат

    Т.е. в синхронном случае второй клиент не подключится, пока первому полностью не ответят
    В асинхронном случае вызывается async_write, и до окончания ответа первому клиенту, в принципе может уже подключиться второй.

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

    Вопрос не имеет смысла, так как map хранит сортированно по ключу (возможен кастомный компаратор) и не позволяет менять этот порядок. Так что по значению - никак. Доставайте оттуда пары, да сортируйте. Какая задача вообще решается?
    Ответ написан
    1 комментарий
  • Как динамически создать n-ое количество потоков в с++ std::thread?

    #include "stdafx.h"
    #include <thread>
    #include <vector>
    #include <iostream>
    
    void foo(std::size_t i)
    {
    	// nothing to do
    }
    
    int main()
    {
    	std::vector<std::thread> ths;
    	std::size_t n;
    	std::cin >> n;
    	for (std::size_t i = 0; i < n; ++i)
    		ths.push_back(std::thread(&foo, i));
    	for (auto & th : ths)
    		th.join();
    	return 0;
    }
    Ответ написан
    6 комментариев
  • Как получить указатель на метод объекта?

    Можно
    Если напрямую, то надо использовать тип "указатель на функцию член" вида Ret (Class::*)(Args...) [const]. Сам указатель получать &Class::Fun, а вызывать операторами .* или ->*
    Или использовать std::function (boost::function), std::bind (boost::bind) или std::mem_fun, std::mem_fn для более унифицированного подхода:

    struct some
    {
    	some() : value(0) {}
    
    	int inc() { return ++value; }
    	int dec() { return --value; }
    	int get() const { return value; }
    
    	int value;
    };
    
    int main()
    {
    	some s;
    
    	int (some::*inc_f)() = &some::inc; // inc_f - указатель на функцию
    	std::cout << "(s.*inc_f)() = " << (s.*inc_f)() << std::endl; // оператор .* - оператор вызова по указателю на функцию
    	int (some::*val_ptr) = &some::value; // val_ptr - указатель на член
    	s.*val_ptr = 10;
    	std::cout << "s.*val_ptr = " << s.*val_ptr << std::endl;
    
    	int (some::*const_f)() const = &some::get; // const-функция
    	std::cout << "s.*const_f() = " << (s.*const_f)() << std::endl;
    
    	using namespace std::placeholders;
    	std::function<int (some&)> mem_f;
    	
    	mem_f = std::bind(&some::inc, _1); // биндим на функцию-член, _1 - placeholder для объекта
    	std::cout << "mem_f(s) = " << mem_f(s) << std::endl; // s.inc();
    	mem_f = std::mem_fn(&some::dec); // другой способ через mem_fn
    	std::cout << "mem_f(s) = " << mem_f(s) << std::endl; // s.dec();
    
    	std::function<int()> mem_f_ = std::bind(&some::inc, &s); // биндим на функцию член и сразу указываем объект, получаем функцию без аргументов
    	std::cout << "mem_f_() = " << mem_f_() << std::endl; /// s.inc();
    
    	std::function<int(some const &)> const_fn = std::mem_fn(&some::get); // some const &
    	std::cout << "const_fn(s) = " << const_fn(s) << std::endl;
    
        return 0;
    }
    Ответ написан
    Комментировать
  • Как отбросить выбивающиеся элементы из потока схожих (фильтрация входных данных)?

    Могу предложить тупое решение.
    Накапливайте кол-во встречающихся чисел, например, в std::map<int, std::size_t>
    std::map<int, std::size_t> m;
    for (int v : vals) { ++m[v]; }
    std::vector<std::pair<int, std::size_t> > v(m.begin(), m.end());
    std::sort(v.begin(), v.end(), [] (std::pair<int, std::size_t> const & l, std::pair<int, std::size_t> const & r) { return l.second > r.second; });
    // в v пары "число - кол-во таких чисел", отсортированы по убыванию
    // можно откинуть нижнюю часть (те, которые встречаются реже, чем какой-то процент, например, 10%)
    v.erase(
      std::find_if(v.begin(), v.end(), [] (std::pair<int, std::size_t> const & x) { return x.second < (v.size() / 10); }),
      v.end());
    // а сверху взять часто встречающиеся
    int row_value = v.front().first;
    Ответ написан
    Комментировать
  • Валидно ли передавать ссылку по ссылке в C++?

    1. UB нет
    2. Может
    3. inline не влияет
    4. Насколько я знаю, нет

    Запрет существования ссылок на ссылки - это отсутствие типа (T &) &. Сравни с указателем: тип (T *) * вполне допустим.

    Проблема со ссылками может быть, если объект, на который ссылаются, помирает раньше, чем ссылка, например
    struct foo { foo(int const & x) : x_(x) {}; int const & x_; };
    
    int bar() { return 42; }
    void baz() { foo f(bar()); ... } // здесь в foo передается ссылка на временный объект, который умирает в конце выражения, однако ссылка сохраняется в объекте f.


    Или проще
    struct foo { foo(int & x) : x_(x) {}; int & x_; };
    
    void foo()
    {
      std::shared_ptr<foo> f;
      {
        int x;
        f.reset(new foo(x));
      } // тут x помирает, ссылка на него невалидна
      f->x_ = 10; // UB
    }
    Ответ написан
    4 комментария
  • Возможно ли экспортировать шаблоны из dll?

    Можно, если инстанцировать шаблоны явно для заранее определённых типов, например:

    template <typename T> struct Vector { ... };
    template <typename T> void foo(Vector<T> &); // definition in cpp
    
    template struct Vector<Point2d>;
    template struct Vector<Point3d>;
    
    template void foo<Point2d>(Vector<Point2d> &);
    template void foo<Point3d>(Vector<Point3d> &);


    Структуры Vector<Point2d> и Vector<Point3d> будут экпортированы.
    Ответ написан
    Комментировать
  • Что не так с кодом?

    Нет реализации соответствующих методов.
    Допишите их, например, так:
    class car {
     public :
         void Start () { ... }
         void Accelerate() { ... }
         void Brake() { ... }
         void setYear(int year) { this->year = year; }
         int getYear() { return year; }
    
     private :
        int year;
        char model [255];
     };
    Ответ написан
    1 комментарий
  • Почему не работает код с++?

    in.seekg (ios::end);
    Чтобы прочесть последний символ, стоять надо не в конце, а на один символ раньше. В вашем случае читать уже нечего.

    in.seekg (-1, ios::cur);
    Этим вы только отшагнёте обратно на один символ, который только что прочли.

    Если файлы невелики, проще будет прочесть его весь прочесть в std::vector, а потом просто скопировать в выходной файл:

    std::vector<char> cts;
    in.seekg(0, in.end);
    cts.resize(in.tellg());
    in.seekg(0, in.beg);
    
    in.read(&ctr[0], ctr.size());
    
    std::ostream_iterator<char> out_it(out);
    std::copy(cts.rbegin(), cts.rend(), out);
    Ответ написан
    5 комментариев