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

    @Mercury13
    Программист на «си с крестами» и не только
    1. Что принимает система: PCHAR или PCHAR*?
    2. Если версии Delphi достаточно новые, PCHAR — это, скорее всего, wchar_t* и надо просто передавать «широкую» строчку L"usb3000".
    3. Постарайся, чтобы reinterpret_cast не было; это признак того, что ты делаешь что-то неверно. Единственное, где он в подобных API допустим — это в callback’ах для передачи замыкания (информации о том, какая подпрограмма и при каких обстоятельствах запустила функцию, вызвавшую callback). P.S. Надумал и второе назначение reinterpret_cast — функция, которая может принимать данные разных типов (вроде SendMessage из Win32).
    Ответ написан
    Комментировать
  • Как построить N-дерево и найти самую длинную ветвь без ветвлений?

    @Mercury13
    Программист на «си с крестами» и не только
    Что-то типа

    максРазмер : целое
    началоМаксВетви: узел
    
    проц максВетвь(узел : Узел, началоВетви: Узел, текРазмер: целое)
      в зависимости от степени узла «узел»
        если 0:
          если текРазмер > максРазмер
            максРазмер = текРазмер
            началоМаксВетви = началоВетви
        если 1: максВетвь(единственныйCын, началоВетви, текРазмер + 1)
        если 2+:
          для всех сыновей
            максВетвь(сын, сын, 1)
    
    максВетвь(корень, корень, 1)


    Считает макс. ветвь, кончающуюся листом; если может кончаться и развилкой — оставляю как домашнее задание.
    Ответ написан
    Комментировать
  • Как устранить коллизии?

    @Mercury13
    Программист на «си с крестами» и не только
    Первое. Заводи массив, в простейшем случае (таблица ограниченного размера) — как минимум вдвое больше, чем желаемая ёмкость. В каждом гнезде или пара (ключ, значение), или «ничего». То ли какое-то спец.значение ключа отведи на «ничего», то ли храни указатели на элементы (не забудь наладить управление памятью), то ли сделай два параллельных массива, один Entry[], второй bool[] (можно добавить bool в Entry, так лучше с прогерской точки зрения, но перерасход памяти).

    Второе. Вычисляем хэш, берём остаток от деления на n, заглядываем в таблицу. Если там что-то есть, но у этого «чего-то» другой ключ, перескакиваем на 1 вперёд. Если снова неправильный ключ — то ещё на два, если снова — то ещё на три… Надеюсь, поймёшь, как делать цикл…

    Третье. Зачем тебе map, если задача — сделать свою хэш-таблицу, а не пользоваться чужим самобалансирующимся деревом.

    Такая таблица может только расширяться, удаление если и можно наладить, то тяжело. Википедия рекомендует второе спец.значение (кроме «ничего») — «тут когда-то что-то было». При поиске «тут когда-то что-то было» считаются занятыми, а при добавлении — свободными. Дурость в общем — удаление не упрощает поиск.
    Ответ написан
    Комментировать
  • Какую библиотеку по работе с POP/IMAP можно выбрать?

    @Mercury13
    Программист на «си с крестами» и не только
    cURL?
    Кроссплатформенная, кстати.
    Ответ написан
  • Как правильно переопределить оператор присваивания с инициализацией методов классов-родителей?

    @Mercury13
    Программист на «си с крестами» и не только
    Попытайтесь выяснить, кто не терпит тупого поэлементного копирования, и изолировать их. Либо в один маленький объектик, либо в один маленький уровень наследования.

    Вариант 1. Сделать промежуточный уровень наследования, в который вносим некопируемые части.

    class LevelObject
    {
    private:
       Level& level;  // Сцылка на уровень, по определению неизменная
       int x, y;           // Присваивать.
    }


    Разбиваем на две части (внимание! — конструктор копирования для простоты не прописан, вероятно, потребуется и он):
    #include <iostream>
    
    class Level
    {
    public:
        int value;
        Level(int aValue) : value(aValue) {}
    };
    
    class LevelChild
    {
    protected:
        Level& level;  // не присваивать
    public:
        LevelChild(Level& aLevel) : level(aLevel) {}
        LevelChild operator=(LevelChild&) { return *this; }   // ничего не делающая операция «присвоить»
    };
    
    class LevelObject: public LevelChild
    {
    protected:
        int x, y;
    public:
        LevelObject(Level& aLevel, int aX, int aY) : LevelChild(aLevel), x(aX), y(aY) {}
        void print();
    };
    
    void LevelObject::print()
    {
        std::cout << "(" << x << ", " << y << ") at level " << level.value << std::endl;
    }
    
    int main()
    {
        Level l1(1);  LevelObject o1(l1, 1, 2);
        Level l2(2);  LevelObject o2(l2, 3, 4);
        o1.print();
        o2.print();
        o2 = o1;
        o2.print();
    }


    Вариант 2. Сделать маленькие объекты-функции со своими операциями присваивания.

    class LevelObject
    {
    private:
       Level* level;  // На сей раз уже копируется
       Array3 pos;    // Какой-то инкапсулированный объект-массив
       std::wstring name;   // тоже инкапсулированный объект
    }


    И всё, когда для std::wstring и Array3 корректно прописаны операции присваивания, для LevelObject всё будет работать корректно без единой строчки.

    P. S. А точно ваш объект страдает от поэлементного копирования и нужна своя операция?
    Ответ написан
    Комментировать
  • Почему срабатывает конструктор копирования?

    @Mercury13
    Программист на «си с крестами» и не только
    Операция присваивания, по договорённости, должна возвращать Pol&.
    Ответ написан
    Комментировать
  • Как в CBuilder организовать объявление свойства?

    @Mercury13
    Программист на «си с крестами» и не только
    Вот, допустим, подсказка по XE2.
    Data.Win.ADODB.TADOQuery
    
    Type  | Visibility | Source             | Unit           | Parent 
    class | public     | Data.Win.ADODB.pas | Data.Win.ADODB | Data.Win.ADODB 
                       | Data.Win.ADODB.hpp |


    Вот и подключаешь <Data.Win.ADODB.hpp>. В более ранних версиях Builder придётся подключать просто <ADODB.hpp>.
    Ответ написан
    1 комментарий
  • NIL в красно-черном дереве?

    @Mercury13
    Программист на «си с крестами» и не только
    Исходник, конечно, дай — посмотрим, что там можно сделать. Как вариант, можно сделать так.

    Node nullNode = { NULL, NULL, NULL, BLACK };
    class NodeHandle {
    private:
      Node* data;
      Node* getData() const { return data ?data : &nullNode; }
    public:
      NodeHandle() : data(&nullNode) {}
      NodeHandle(Node* x) : data(x) {}
      NodeHandle& operator=(Node* x) { data = x; return *this; }
      bool operator == (const Node* x) const { return (data == x); }
      bool operator != (const Node* x) const { return (data != x); }
      bool operator == (const NodeHandle& x) const { return (data == x.data); }
      bool operator != (const NodeHandle& x) const { return (data != x.data); }
      Node* operator ->() const { return getData(); }
      Node& operator *() const { return *getData(); }
      operator Node*() const { return getData(); }
    }


    Но, думаю, всё же где-то вкралась ошибка.
    Ответ написан
    Комментировать
  • Почему происходит ошибка при обращении к полю статического класса?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело в том, что static-член в теле класса — это только заголовок, говорящий, что такое есть, но не создающий ни кода, ни данных. Эквивалент extern. Где-то в CPP (т.е. в одной и только в одной единице компиляции — не в .h!) нужны…

    std::vector LogVoting::RegisteredDeputy;

    И так далее.

    Если этим полям нужен нестандартный конструктор — пожалуйста…
    std::vector LogVoting::RegisteredDeputy(42);
    Ответ написан
  • Что такое нарушения принципов ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Нарушение инкапсуляции. Наружу (т.е. public) торчат какие-то данные, которые можно изменить, и объект уходит в противоречивое состояние.

    Инверсия абстракции. Простые вещи, которые, вероятно, понадобятся потомкам, недоступны даже через protected.

    Нарушение принципа Лисков (ломаная абстракция). Для отца вы сделали некое предположение, которое неверно для сыновей. Классический пример — прямоугольник и квадрат — предполагается, что отец может произвольно масштабироваться, что неверно для сына.

    Класс вместо интерфейса. Если можно, родителя делайте классом без данных с двумя видами функций: public virtual = 0, и protected/public не-virtual (т.н. интерфейс с утилитами). Наследоваться от нескольких классов с данными очень некузяво (а во многих языках вообще невозможно).

    Всемогущий родитель. Слишком много функциональности придумали родительскому классу.

    В общем, покажите интерфейсы (protected/public, без точных реализаций) ваших классов, и погоняем, что там неверного.
    Ответ написан
    Комментировать
  • В чем разница int mas[], int mas[0], int mas[100]?

    @Mercury13
    Программист на «си с крестами» и не только
    int mas[] используется в трёх местах.

    1. Когда размер определяется инициализатором: int mas[] = { 1, 2, 3, 4, 5 };
    2. Чтобы задать параметр вида «массив неопределённой длины»: double vecLen(double a[], int size) {}
    Си не может жёстко задавать размер массива в параметре, чтобы больший или меньший не подходил; даже если напишешь напишешь double vecLen(double a[3]) {}, всё равно другой массив подойдёт. Си++ задаёт так: double vecLen(double (&a)[3]) {})
    3. Подсказал jcmvbkbc, реально мало на что нужно: extern int a[].

    int mas[0] создаёт массив нулевой длины, надобности в котором, понятное дело, никакой. Зато этот код используется, чтобы накладывать структуру данных, которая заканчивается массивом неизвестной длины, на какой-то буфер в памяти — как указатель: тут массив (C++ не проверяет выход за границу).

    struct Packet {
      unsigned short length;
      unsigned char data[0];
    }
    
    void processPacket(void* data, unsigned length)
    {
       // Простите уж, что перешёл на C++
       const Packet& packet = *reinterpret_cast<Packet*>(data);
       if (length != sizeof(Packet) + packet.length)
         throw std::logic_error("Packet size mismatch");
       for (unsigned i = 0; i < packet.length; ++i) {}
    }
    Ответ написан
    8 комментариев
  • Как понять заголовочные файлы?

    @Mercury13
    Программист на «си с крестами» и не только
    #include — как ни странно.

    Вы так и не поняли такой вещи, как «единица компиляции». Дело в том, что в Си c-файлы компилируются независимо друг от друга (в единую программу всё собирает линкер). А чтобы сказать «оно есть, только в другой единице компиляции», используют прототипы и extern’ы.

    А если вы хотите просто внести код в ту же единицу компиляции, просто пишите его в хедере, да и всё. Только в большинстве компиляторов это исключает предкомпилированные хедеры — а ТАКИЕ хедеры вам предкомпилировать, скорее всего, и не нужно.

    <брюзга mode on>
    Не создают кода (а значит, в традиционной системе с кучей единиц компиляции находится именно в хедерах)
    • extern и прототипы
    • inline
    • не до конца специфицированные шаблоны
    • static-поля в классе (но потом это static-поле придётся повторить в какой-нибудь одной единице компиляции)
    • может, ещё что-то, только я забыл…
    <брюзга mode off>
    Ответ написан
    1 комментарий
  • Как дополнить топологическую сортировку?

    @Mercury13
    Программист на «си с крестами» и не только
    С двузначными метками посещения (bool used[]) — никак.

    Надо перейти на трёхзначные метки (UNVISITED, PARTLY_VISITED, VISITED).

    void dfs (int v) {
      state[v] = PARTLY_VISITED;
        .....
      state[v] = VISITED;
      ans.push_back (v);
    }


    Неплохой пример есть в вашем предыдущем вопросе.
    Ответ написан
    Комментировать
  • Как применить топологическую сортировку?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно переписать под матрицу смежности вот этот участок кода.
    for(int i = 0;i < Edges[v].size();i ++){
              if(dfs(Edges[v].get(i)))return true;
          }

    Что-то типа этого.
    цикл (i : все вершины)
       если матрица_смежности[v, i]
             если dfs(i)
                 return true;

    Ещё мне не нравятся константы 0, 1 и 2. Объявить бы их как
    UNVISITED = 0;
    PARTLY_VISITED = 1;
    VISITED = 2;

    Или WHITE, GRAY и BLACK, если хотите — в учебниках по алгоритмам их красят в три цвета.
    Ответ написан
    Комментировать
  • Как правильно написать MutexLocker?

    @Mercury13
    Программист на «си с крестами» и не только
    pthread_mutex_locker locker(&mutex);

    Назови его как-нибудь, и всё будет окей.
    Ответ написан
    Комментировать
  • Зачем нужен ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Я хотел спросить: вы что, студент? Потом посмотрел: нет, вебист. Вебистам действительно ООП нужно крайне редко; если не связывался с хитрой поддержкой сложных протоколов или со сложными моделями данных — в памяти, не в БД — можно писать без ООП и быть успешным вебистом.

    Я и сам долгое время не понимал, на что нужны эти объекты. Главный вопрос: ДЛЯ ЧЕГО?

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

    Предлагаю начать с простого.

    1. Объектный синтаксис. Было…
    iDog : integer;
    iDog := SpawnMonster(world, mtDog, x, y);
    ChargeAtPlayer(iDog);


    Стало…
    dog : TMonster;
    dog := world.SpawnMonster(mtDog, x, y);
    dog.ChargeAtPlayer;


    Уже стало красивее. Да и номер собаки можно случайно передать, например, вместо номера оружия; с типом TMonster такой фокус не пройдёт.

    2. Инкапсуляция.
    Это мы уже думаем над тем, чтобы вызовы функций не могли привести объект в «ненадлежащее» состояние, а всё, что может объект подпортить,— засунуто в private.

    3. Абстракция и наследование. Это уже «сложный пилотаж». Не высший — это неотъемлемая часть навыков хорошего программиста, да и для 80% задач это не нужно, зато в остальных 20-и очень улучшает жизнь. Самый простой пример. В какой-нибудь 2D-игре есть некий TGameObject, у которого виртуальные функции Live и Render. Первая прокручивает такт «жизни» объекта, вторая рисует его на экране. TGameObject можно разбить на TPlayer, TProjectile, TEnemy и TBonus, и т.д.

    Ах да. Для ООП не нужен объектно-ориентированный язык и объектный синтаксис, нужно объектно-ориентированное мышление. Например, Doom был написан на Си, но в очень-очень объектном стиле.
    Ответ написан
    Комментировать
  • Какой аналог php функции is_string() в ЯП С++?

    @Mercury13
    Программист на «си с крестами» и не только
    C++ — язык со статической типизацией, и если x объявлено как string, то он всегда string. А если как int, то он никогда не string. Поэтому функция is_string в C++ просто не имеет смысла.

    Правда, существуют островки динамической типизации наподобие VARIANT из OLE — это уже смотрите по месту (msdn.microsoft.com/en-us/library/cc237865.aspx) и, скорее всего, это не ваш вопрос.

    Да, вы хотели проверять корректность ввода. Например, для проверки, будет ли строка числом, можно использовать www.cplusplus.com/reference/cstdlib/strtod (не забудьте потом проверить endptr!)
    Ответ написан
    Комментировать
  • Вопрос специалистам по GCC и темплейтам C++

    @Mercury13
    Программист на «си с крестами» и не только
    Всё, что я знаю: GCC — самый «въедливый» компилятор. После Intel и Embarcadero (про M$ не знаю) на «зашаблоненном» коде GCC найдёт ещё два десятка ошибок.
    Ответ написан
    Комментировать
  • Возможно ли создать "универсальный" драйвер для исполнения произвольного кода в Ring0?

    @Mercury13
    Программист на «си с крестами» и не только
    Это к Sony или StarForce. И те, и другие делали заSHITу и прокалывались на подобном.
    Ответ написан
  • Можно ли создавать в рантайме объект в C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Разрешите вставить и свои 5e−2 Р

    Известно ли что-то о том, какой тип будет иметь наш auto? Если известно, то может, сработает просто

    dynamic_cast<Type>(object).field1.field2 = NULL;
    Ответ написан
    Комментировать