Задать вопрос
Ответы пользователя по тегу C++
  • Как лечить char warning overflow при считывании с файла?

    @Mercury13
    Программист на «си с крестами» и не только
    fin.getline(pRun->sBooks.chBook, 99, static_cast<char>('»'));


    Всё у вас правильно. А в Си char почему-то (обычно) знаковый.
    Ответ написан
  • Приведение обьекта производного класса к базовому?

    @Mercury13
    Программист на «си с крестами» и не только
    Через указатели и ссылки — останется.
    По значению (как у тебя сейчас в векторе) — преобразуется в базовый.

    Главная проблема работы с указателями и ссылками — где хранить объекты и как их уничтожать. Хранят обычно в «куче», а для уничтожения используют умные указатели или что-то самописное под задачу. Вот, например, решение на умных указателях C++11:
    #include <iostream>
    #include <memory>
    #include <vector>
    
    class Base{
    public:
        // Нужен виртуальный деструктор, ведь мы будем уничтожать детей
        // через родительский ук-ль. Да и dynamic_cast требует RTTI,
        // а значит, хоть одного виртуального.
        virtual ~Base() = default;
    };
    
    class Exp: public Base
    {
    int i=0;
    public:
           int Get() const {  return i; }
           void Set(const int &num) { i=num; }
    };
    
    std::vector<std::shared_ptr<Base>> MyStack;
    Base &GetRef() { return **MyStack.begin();  }
    
    int main() {
        std::shared_ptr<Exp> a = std::make_shared<Exp>();
        a->Set(4);
        MyStack.push_back(a);
        int res=dynamic_cast<Exp&>(GetRef()).Get(); // Теперь работает
        std::cout << res << std::endl;;
    }
    Ответ написан
    Комментировать
  • Что такое normaliz.dll?

    @Mercury13
    Программист на «си с крестами» и не только
    Нормализация Юникода.
    Обычно находится в Windows\System32 (Windows\SysWOW64).
    Официальный сайт не держит библиотек cURL, он только даёт ссылки на чужие сборки. cURL (или OpenSSL) использует VC2008; вы явно скачали версию НЕ для XP. Ничего, VS2008 Redistributable можно скачать тут.
    https://www.microsoft.com/en-us/download/details.a...

    Я специально искал и нашёл сборку cURL/OpenSSL, которая не требует ничего необычного. Мы программисты, ставим кучу софта — а у одного бета-тестера не прокатило, т.к. на его рабочем ноутбуке не было VS2013, приблудил с OpenSSL.
    Ответ написан
    Комментировать
  • Как заставить сработать исключение std::bad_alloc?

    @Mercury13
    Программист на «си с крестами» и не только
    #include <iostream>
    #include <conio.h>
    
    int main()
    {
      setlocale(LC_ALL, "Russian");
      const size_t SIZE = 3000000000ul;
      char* ptr = NULL;
      try
      {
        ptr = new char[SIZE];
        std::cout << "Память используется без сбоев.\n";
      }
      catch (std::bad_alloc&)
      {
        std::cout << "Исключение bad_alloc: невозможно разместить данные в памяти.\n";
      }
      delete[] ptr;
      getch();
      return 0;
    }


    Столько кода — и столько ошибок! По пунктам.
    1. Ответ на ваш вопрос. Сделать константу побольше. Кстати, эта константа — size_t. В 64-битном коде надо ещё больше.
    2. Не проработано поведение delete[], если случится ошибка. Покатит инициализация NULL.
    3. Если случится ошибка, будут выведены оба сообщения.
    4. getch — функция из платформозависимого заголовка conio.h. Только DOS/Windows.
    5. Обработку аварий обычно делают по ссылке.
    6. Для первого параметра setlocale надо указывать ненулевую маску, на какие части ставить локаль. LC_ALL — везде. Что писать вторым параметром, зависит от библиотеки времени выполнения.
    Ответ написан
    7 комментариев
  • Undefined reference to?

    @Mercury13
    Программист на «си с крестами» и не только
    В проект не включили файл methods.cpp. Потому линкер говорит, что нет этих функций.

    Язык Си (как, впрочем, и большинство ассемблеров) собирает cpp-файлы воедино неязыковыми средствами: makefile’ами и файлами проектов. Сначала компилятор обрабатывает все единицы компиляции отдельно друг от друга, а потом линкер собирает из того, что получилось, исполняемый файл. Разумеется, если где-то какой-то функции не нашлось, это можно опознать только при линковке.
    Ответ написан
    4 комментария
  • Почему при достаточно малых значениях вещественного числа кол-во итераций при нахождении машинного эпсилон резко убывает?

    @Mercury13
    Программист на «си с крестами» и не только
    Машинный эпсилон — это минимальное число, что 1 + ε ≠ 1. Так что, в принципе, ты вычислил его правильно, хоть код и студенческий. Но есть один нюанс.

    Дело в том, что float и double бывают нормализованные и денормализованные. Что это такое?
    Любое число в двоичной системе счисления начинается с единицы. Поэтому головная единица подразумевается и не хранится — т.н. «нормализованное число». НО: когда порядок 00…00, считается, что в голове НОЛЬ, а относительная погрешность сменяется абсолютной — это денормализованное число.

    0 1010…00 00000001 = +0,11012×2−127 — нормализованное число
    0 1010…00 00000000 = +0,01012×2−127 — денормализованное
    0 0000…00 00000000 = +0,00002×2−127. Ноль — тоже денормализованное число.

    10−38 — минимальное нормализованное число. 10−45 — минимальное денормализованное, с мантиссой 0,00…001. Помнишь, я говорил, что в денормализованных числах относительная погрешность сменяется абсолютной в эти самые 10−45 — потому чем меньше число, тем больше «типа-эпсилон».

    10-байтовый extended, он же long double, насколько мне известно, не нормализован, т.е. головная единица там хранится явно. Но такая точность редко нужна, появляется перерасход памяти (2 или 6 байтов, в зависимости от процессора и его настроек), да и не слишком оптимизируют сопроцессоры под такие числа.
    Ответ написан
    Комментировать
  • Использование функций из Dll бибилеотеки?

    @Mercury13
    Программист на «си с крестами» и не только
    Возникает вопрос. Это простой DLL с торчащими наружу функциями или COM?
    • QLibrary — для DLL.
    • regsvr32 — это для COM.
    • Первый раз не загрузилось и второй раз загрузилось, потому что 32-битные программы со стандартным манифестом принимают каталог «SysWOW64» за «System32». Когда DLL не найден, программа отыскивает его в некоторых стандартных местах и таковыми, возможно, являются и активные COM-серверы.
    • OpenConnection мог не найтись по адовой куче причин. Может оказаться, что имя OpenConnection «покозявлено» и надо что-то типа «OpenConnection@4». Может оказаться, что библиотека — действительно COM-сервер и QLibrary тут бесполезен.
    Ответ написан
    9 комментариев
  • Почему не отрабатывает перегруженный конструктор класса?

    @Mercury13
    Программист на «си с крестами» и не только
    Попробую рассказать об этом же более простыми словами.

    Текст String s3 = "Нас обманули, расходимся."; означает вот что. Мы создаёт временную строку «Нас обманули, расходимся», а затем присваиваем её нашему s3. Конечно, компилятор это потом заоптимизирует, но это семантика языка, и ей надо следовать.

    Есть два способа передать временный объект в функцию. Любую: хоть простую, хоть конструктор, хоть операцию =.
    Первый — константная ссылка: String(const String &S).
    Второй способ из C++11 — временная ссылка: String(String &&S).

    Из-за этих временных объектов конструктор копирования и операция «присвоить», по-хорошему, должны брать const-ссылку. Вот вам аналогичный пример с операцией «присвоить».

    class String
    {
    public:
        String() {}
        String& operator= (String& s) { return *this; }
    };
    String operator+ (String a, String b) { return String(); }
    
    int main()
    {
        String s1;
        String s2 = s1;
        String s4;
        s4 = s1 + s2;
    }


    Решается String& operator= (const String& s).
    Ответ написан
    Комментировать
  • Как хранить записи со стены ВК?

    @Mercury13
    Программист на «си с крестами» и не только
    Не громоздко и не ресурсоёмко (особенно в C++11 — кстати, скоро Qt вообще откажется от 03).
    Однако я бы в таких нагромождениях делал struct’ы из одного элемента. Что-то типа
    struct Comment {
      QMap<QString, QString> objects;
    };
    
    struct Post {
       QList<Comment> comments;
    };

    Так код проще будет разобрать.

    Только одно непонятно. Что собой представляют эти objects и на что тебе эта «строкотипизированность»?
    Ответ написан
    Комментировать
  • Как конвертировать list в string[]?

    @Mercury13
    Программист на «си с крестами» и не только
    Итератор — это объект с семантикой указателя, который может указывать на N+1 точку в объекте.
    5f40aef227644b9ca57224ffeb571a97.png
    Раз он с семантикой указателя, у него есть операции «унарная звезда» и −> (разыменование и разыменование+взятие поля). Также у итератора есть операция ++ (сдвинуться на следующую позицию). Если это т.н. «однонаправленный итератор» — всё, больше ничего.

    Также бывают т.н. двунаправленные итераторы (есть операция −−), и итераторы произвольного доступа (их можно свободно складывать с числами — ну совсем как указатели). В частности, у std::list итераторы двунаправленные.

    У итераторов неопределённое поведение…
    • при попытке выйти за начало или конец;
    • при попытке разыменовать, если он смотрит на последнюю позицию (отмеченную как «конец»).

    Конкретно о задаче.
    1. std::vector предпочтительнее std::list.
    2. Не нужно возвращать string*, хватает какого-нибудь контейнера (std::vector<std::string> или std::list<std::string>).
    3. Если функциональности и скорости istringstream хватает, флаг в руки! Я бы написал по хардкору, с нуля. Вот мой код, выдранный из моего проекта, наверно, будет несложно переделать его в учебный.

    void parseCommaList(
            const char *aStart,   // указатель на начало
            const char *aEnd,    // указатель на символ за концом
            char aComma,        // символ-разделитель
            bool aSkipEmpty,   // true, если пустые подстроки пропускать
            ProcParseCommaList aCallback,   // функция-нагрузка
            void *aData)   // этот параметр нужен, чтобы передавать какие хочешь данные в функцию-нагрузку, удаляй его смело!
    {
        str::trim(aStart, aEnd);    // моя функция; пододвигает aStart вперёд и aEnd назад, убирая пробелы.
                                    // Если удаление пробелов не нужно — удаляй! Если нужно — пиши сам.
        if (aStart == aEnd) return;
        const char *sstart = aStart;
        for (const char *p = aStart; p != aEnd; ++p)
        {
            if (*p != aComma) continue;
            const char *send = p;
            str::trim(sstart, send);   // то же самое, можно убрать
            if (p != sstart || !aSkipEmpty)
                aCallback(sstart, send, aData);    // замени на боевую нагрузку
            sstart = p + 1;
        }
        str::trim(sstart, aEnd);   // то же самое, можно убрать
        if (sstart != aEnd || !aSkipEmpty)
            aCallback(sstart, aEnd, aData);    // замени на боевую нагрузку
    }


    И, соответственно, версия для std::string.

    inline void parseCommaList(
            const std::string &aIn,
            char aComma,
            bool aSkipEmpty,
            ProcParseCommaList aCallback,
            void *aData)
    {
        parseCommaList(aIn.data(), aIn.data() + aIn.length(), aComma, aSkipEmpty,
                aCallback, aData);
    }
    Ответ написан
    Комментировать
  • Как добавить все элементы из вектора в контейнер multimap под определенный ключ?

    @Mercury13
    Программист на «си с крестами» и не только
    Если вам нужен именно multimap, другого способа я не вижу. Но если элементов много, стоит задействовать хинт (параметр position, где примерно элемент будет стоять). Что-то типа (в компиляторе не проверял, код почти гарантированно неверный).
    if (!names.empty()) {
        Users::const_iterator hint = users.upper_bound(1);
        for (auto &i :  names) {
          users.insert(hint, {1, i});
        }
    }

    Учтите, что при переходе с 03 в 11 поменялся смысл хинта, тут версия для 11.
    P.S. Извините, код для хинта можно сделать и проще. После вставки и ++ хинт останется тем же.
    Ответ написан
    Комментировать
  • Как корректно обрезать строку тип string в utf8 на с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Символов Юникода или байтов UTF-8?

    В любом случае байты UTF-8 делятся на три категории…
    • Начальные: 0x00…0x79, и 0xC0…0xF4
    • Дополнительные (не бывают в начале): 0x80…0xBF
    • Запрещённые: 0xF5…0xFF. В наших целях тоже можно отнести к начальным.

    Если задача — получить 10 символов, то находим 11-й начальный символ и обрезаем перед ним.

    Если задача — получить 10 байт и 11-й (s[10], если таковой есть, разумеется) — не начальный, начинаем урезать строку, пока не отрежем начальный символ.
    Ответ написан
  • Qt. Как передавать данные между формами?

    @Mercury13
    Программист на «си с крестами» и не только
    Вариантов много, в зависимости от того, форма модальная или нет, и нужно ли каким-то моделям передавать сообщение «обновись».

    Вариант 1.
    class AddItem : public QWidget
    {
    public:
      AddItem(QWidget* aParent, QList<Institution>& aInstitutions)
          : QWidget(aParent), institutions(aInstitutions) {}
    private:
      QList<Institution>& institutions;
    };


    Во втором варианте у нас модальная форма, но редактировать можно только копию (например, институции первой формы задействованы в какой-то модели, или нужны каскадные удаления, или что-то ещё).
    class AddItem : public QDialog
    {
    public:
      int exec(QList<Institution>& aInstitutions);
    private:
      QList<Institution> institutions;
    };
    
    int AddItem::exec(QList<Institution>& aInstitutions)
    {
      institutions = aInstitutions;
      int r = QDialog::exec();
      if (r) {
         aInstitutions = std::move(institutions);
      }
      return r;
    }


    И много-много других вариантов.
    Ответ написан
    Комментировать
  • Qt как создать много окон внутри одного?

    @Mercury13
    Программист на «си с крестами» и не только
    Сам не работал с этим под Qt, но называется это «многодокументный интерфейс» и простейший пример тут.
    doc.qt.io/qt-5/qtwidgets-mainwindows-mdi-example.html

    Также можно погуглить «Qt MDI».
    Ответ написан
    1 комментарий
  • Почему возникает ошибка "Нет такого слота"?

    @Mercury13
    Программист на «си с крестами» и не только
    Иногда Qt Creator проглючивает и требуется полная перекомпиляция проекта.
    Почему-то не запустился MOC.
    Ответ написан
  • Зачем нужны матрицы в Direct3D?

    @Mercury13
    Программист на «си с крестами» и не только
    Начнём с того, что вектор имеет три координаты: x, y и z. Все повороты системы координат (x, y, z) → (x', y', z'), масштабирования и их комбинации можно записать в виде

    x' = a11·x + a12·y + a13·z
    y' = a21·x + a22·y + a23·z
    z' = a31·x + a32·y + a33·z

    А теперь прочитайте, что такое «умножить матрицу на вектор». Узнаёте? — матрицу {aij} размером 3×3 умножаем на вектор-столбец (x, y, z)T и получаем вектор-столбец (x', y', z')T. Здесь буква T — это операция «транспонировать матрицу», заменить строки столбцами, а столбцы — строками.

    А теперь сделаем финт ушами. Возьмём 4-векторы (r, s, t, d) и обозначим x=r/d, y = s/d, z = t/d (так называемые однородные координаты). Преобразование в однородные координаты неоднозначно: декартовы координаты (1, 2, 3) можно обозначить как четвёркой (1, 2, 3, 1), так и четвёркой (10, 20, 30, 10). Для чего нам однородные? Матрицы 4×4, работающие над однородными координатами, позволяют записать и такие преобразования, как «сдвинуть» или «центральная проекция». Например, «сдвинуть» записывается как

    r' = 1·r + shiftx·d
    s' = 1·s + shifty·d
    t' = 1·t + shiftz·d
    d' = d

    или, в терминах матриц
    [r']   ( 1 0 0 shiftx )   [r]
    [s'] = ( 0 1 0 shifty ) · [s]
    [t']   ( 0 0 1 shiftz )   [t]
    [d']   ( 0 0 0 1      )   [d]

    (тут я не поленился собрать тэгом code нечто похожее на вектор-столбец, так что знак транспонирования не нужен :)
    Ответ написан
    Комментировать
  • Для чего нужна рантайм-библиотека?

    @Mercury13
    Программист на «си с крестами» и не только
    В рантайм-библиотеке хранятся стандартные функции языка программирования. И malloc/new тоже.

    P.S. Также хранятся внутренние функции для обслуживания точки входа (int main).
    Ответ написан
  • Qt: как сделать, чтобы редактор в таблице вёл себя по-другому при нажатии Tab?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    QModelIndex EditableTable::moveCursor(
            CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
    {
        switch (cursorAction) {
        case QAbstractItemView::MoveNext:
        case QAbstractItemView::MovePrevious:
            return QModelIndex();
            break;
        default:
            return Super::moveCursor(cursorAction, modifiers);
        }
    }


    Чтобы протолкнуть такую функциональность в Qt Creator, использовать функцию «Promote To…»
    Ответ написан
    Комментировать
  • Почему не советуют использовать технологии Borland?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Очень долгое время был устаревший компилятор C++. Насколько мне известно, в XE10, совсем недавно, решилось (не проверял). Слоупоки!
    2. А почему? Где-то с 2001 года Borland натурально начхал на Delphi. Delphi 7 долгое время был самым лучшим — пока не появился 2010. Новые владельцы восстанавливают упущенное, но не всё идёт как надо (XE4 реально глючнее XE2, буду ещё думать, что лучше держать под Win10, чтобы работало с тамошней средой .NET).
    3. Кажется, они поставили не на тот кроссплатформенный фреймворк. FireMonkey — имитация стандартных элементов управления. Медленно и глючно. А если ради чего-то решил выключить ClearType — вообще атас!
    4. Бесплатный WinForms отобрал немалую аудиторию у тех, кому надо быстренько написать программу только под Windows. Но это скорее аналог VCL, чем FireMonkey.
    5. Embarcadero — фактически единственные, кто поддерживает хороший Паскаль.
    Ответ написан
    Комментировать
  • Есть бинарные дерево поиска в С++?

    @Mercury13
    Программист на «си с крестами» и не только
    Именно так работает стандартный контейнер std::map.
    Ответ написан
    Комментировать