Ответы пользователя по тегу C++
  • Иероглифы вместо кириллицы в с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Перед нами UTF-8. Перекодируйте исходник в рабочую кодировку (обычно DOS-866 или Windows-1251).

    Или работайте в широких строках. У меня на MinGW 5.3 получился вот такой исходник.
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        setlocale(LC_ALL, "rus");
        wcout << L"Превед!" << endl;
        return 0;
    }
    Ответ написан
  • Почему неправильный вывод значений в printf?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня вышло: 0 1074266112 0 1074266112
    Или, в 16-й системе, 0 40080000 0 40080000

    Связано это с такими вещами.
    1. Аргументы типа float записываются в стеке как double.
    2. На x86 порядок байтов Intel (обратный).
    3. Дробные числа хранятся без ведущего разряда (который всегда 1), в формате мантисса-порядок-знак (на порядке байтов Intel).
    4. Для единицы (xxx·20) порядок будет 011…11.

    3 = 1,10…02·2¹, и с учётом отброшенного ведущего разряда мантисса будет 10…0.
    Порядок 011…11 + 1 = 10…0.

    С учётом обратного порядка байтов double 3,0 будет выглядеть так
    • 6 нулевых байтов — мантисса
    • 0000.1000: нижние полбайта — это мантисса, верхние — уже порядок
    • 0100.0000: бит знака и ещё семь битов порядка

    Получается 00.00.00.00.00.00.08.40.
    Разбиваем на два куска памяти по 4 байта.
    [00.00.00.00] [00.00.08.40]
    Опять-таки не забудем, что у целых тоже обратный порядок байтов — и получается 0 и 40080000.
    Ответ написан
    Комментировать
  • Почему не переполняется float?

    @Mercury13
    Программист на «си с крестами» и не только
    Представьте, у нас десятичная арифметика с тремя значащими цифрами. Соответственно, сложение работает не более чем с пятью цифрами: три собственно значащих, слева на перенос и справа на округление. То, что получилось, в любом случае будет округлено до трёх.
     99900000000000
    +             1,00
     -----------------
     9990   →   9,99e13

    Если сделать второе слагаемое покрупнее, то будет
     99900000000000
    +   50000000000
     -----------------
     9995   →   1,00e14 → переполнение


    То есть вот что надо добавить, чтобы случилось переполнение: в зависимости от настроек сопроцессора или ulp(FLT_MAX) (ULP = Unit of Last Place — цена младшего разряда на данном порядке), или ulp(FLT_MAX)/2.
    Ответ написан
    Комментировать
  • Зачем std::forward иметь две сигнатуры и явно указывать тип?

    @Mercury13
    Программист на «си с крестами» и не только
    std::forward предназначен для использования в шаблонах; без шаблона можно использовать старый добрый std::move.
    Кроме того, std::forward налажен таким образом, что шаблонный параметр надо указывать явно.

    Задача std::forward — передать далее простую или временную ссылку в зависимости от того, какую ссылку передаёт пользователь.
    Ответ написан
    6 комментариев
  • Написать программу, сильно тормозящую Windows?

    @Mercury13
    Программист на «си с крестами» и не только
    Много дёргать ввод-вывод. Например, помногу, в несколько потоков, читать диск.
    Если винт механический, Windows становится абсолютно неюзабельной.
    Ответ написан
    Комментировать
  • Как установить OpenCV для C++ в QT Creator?

    @Mercury13
    Программист на «си с крестами» и не только
    LIBS += -LC:/opencv/pro/lib -lxxx

    xxx — это имя файла с расширением a, без расширения и префикса lib.
    Если он libopencv_core.a, то надо -lopencv_core
    Ответ написан
    Комментировать
  • Почему запускается первым конструктор mainwindow.cpp?

    @Mercury13
    Программист на «си с крестами» и не только
    Я бы переписал архитектуру программы.
    1. Перед вами модальное окошко. Вот его и вызывайте, как модальное — au.exec().
    2. Чтобы проверить, что авторизация верна, надо соединиться. Так что сделайте невизуальный объект «соединение» и протащите в exec. Ну или создайте в exec.
    3. А уж там собирайте основную программу.
    QApplication a(argc, argv);
    FmAutoriz au;
    std::unique_ptr<SomeConnection> connection = au.exec();   // SomeConnection и exec придётся написать
    if (connection) {
      FmMain m(connection);
      m.show();
      return a.exec();
    } else {
      return 0;
    }
    
    std::unique_ptr<SomeConnection>FmAutoriz::exec()
    {
      bool b = QDialog::exec();
      if (b) {
        return std::move(this->connection);
          // connection — поле FmAutoriz.
          // Такой же unique_ptr, в обработчиках кнопок пытаемся создать соединение.
      } else {
         return nullptr;
      }
    }
    
    void FmAutorize_on_btOk_click()
    {
       connection = new SomeConnection();
       if (connection.connect(someLogin, somePassword)) {
          accept();
       } else {
          // сообщи об ошибке
       }
    }

    Вижу побочку этого (но, может, и не надо избавляться) — на панели задач анимацией сменяется кнопка с диалогом авторизации на кнопку с главным окном.
    Ответ написан
  • Как получить кол-во записей, которые помещаются в окне QTableView?

    @Mercury13
    Программист на «си с крестами» и не только
    Это на самом деле сложная задача, и я её решил вот так.
    QHeaderView* header = ui->tableView->verticalHeader();
    QWidget* viewport = header->viewport();
    int i1 = header->logicalIndexAt(0);
    int i2 = header->logicalIndexAt(viewport->height() - 1);
    if (i2 < 0)
        i2 = header->count() - 1;
    QString s = QString::number(i1) + " - " + QString::number(i2);
    ui->lbResult->setText(s);


    Если в очень упрощённом виде — то немного не так.
    return m_tableView->viewport()->height() / m_tableView->rowHeight(0);
    Ответ написан
    Комментировать
  • Приложения корректировки форматирования кода?

    @Mercury13
    Программист на «си с крестами» и не только
    Первое. Нужен сильно упрощённый синтаксический анализ, который делит код на директивы препроцессора, лексемы, операторы и комментарии, понимающий вложенность операторных скобок.
    Второе. Все эти лексемы выкидываем в выходной поток, добавляя незначащие символы по всоему усмотрению.
    Третье. Комментарии тоже придётся переформатировать, и с этим отдельный геморрой.
    Для Си — там есть ещё #define. Идеал — развернуть каждый #define, добавив спецсимволы «тут начало #define», «тут конец #define», форматнуть код, передвинуть левый спецсимвол как можно правее по незначащим символам (а правый — как можно левее), а потом опустить всё между спецсимволами, оставив только #define в том виде, как он был.
    Ответ написан
    Комментировать
  • Variadic template c++?

    @Mercury13
    Программист на «си с крестами» и не только
    Этот шаблон вычисляет при компиляции такое:
    rbv<false, false, true, true>() = 11002.

    И состоит из двух частей.
    1. Для одного параметра у нас напрямую написан шаблон.

    2. Для false, false, true, true — у нас используется второй шаблон: a=false, b=false, d = (true, true).
    И он равняется (rbv<false, true, true> << 1) + false.

    Чтобы вычислить новый rbv, снова работает второй шаблон: a = false, b = true, d = (true).
    И он равняется (rbv<true, true> << 1) + false.

    Для третьего rbv у нас a = true, b = true, d = ().
    Внимание, список d может быть и пусттым. Потому, чтобы не было конфликта с первым шаблоном, второй пишется для двух и более параметров.
    И третье наше значение равняется (rbv<true> << 1) + true.

    Вот тут работает первый шаблон и получается 112.
    Дальше уже можно вычислить все rbv по очереди и получить 11002.
    Ответ написан
    4 комментария
  • Как запросить число через cin в C++ чтобы оно заканчивалось на цифру 5?

    @Mercury13
    Программист на «си с крестами» и не только
    Это невозможно, мэн волен ввести в консоль что угодно.
    Но ваша задача как программиста — каким-то образом не допустить некорректного ввода. То ли вывести ошибку, то ли самостийно округлить, то ли потребовать повторный ввод… Вы уж сами думайте, что требуется именно от вашей программы.
    Условие «кончается на 5» эквивалентно  «не делится на 10, но делится на 5».
    Ответ написан
  • Как работает данная программа C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Это обычная учебная программа и я за такой код бил бы по рукам. Нарекания к ней.
    1. Одновременное пользование printf и cout. Впрочем, несмотря на глючность, printf — хорошая штука, я и сам сделал более мощный аналог.
    2. Есть немного случаев, когда допустимы такие названия переменных/функций.
    • для счётчика цикла (i, j, k для переменной, it, jt, kt для итератора, u, v, w для новой фичи Си++11 — того, на что итератор указывает);
    • если мы преобразуем научную статью в код, и переменные так названы в статье.
    3. Даже название Count слишком расплывчатое — лучше что-то вроде nFound.
    UPD2. 4. Я бы переписал функцию P так, что for [0…горизонталь), при бое return false, цикл удался — return true.
    5. В музей говнокода!
    if (i == k)
        return true;
      else if (i != k)
        return false;
      else
        return !true && !false;

    Верно
    return (i==k);

    Программа проходится по 1-й горизонтали и ставит ферзя на каждую клетку. Если поместился — рекурсивно делает то же самое для 2-й горизонтали, если нет — значит, не повезло. Как только расчёт дойдёт до N-й горизонтали — мы нашли расположение ферзей, можно выводить.

    UPD. Ну, допустим, я бы переписал 2-ю функцию так (не меняя порядок параметров).
    void Backtracking(int currX, int &nFound, int boardSize, int queenY[])
    Ответ написан
    5 комментариев
  • Как правильно использовать строки в плюсах?

    @Mercury13
    Программист на «си с крестами» и не только
    • std::string — как правило, если не указано противное.

    • QString, AnsiString/UnicodeString и прочие — в соответствующих фреймворках, обычно очень близко к интерфейсным функциям.

    • char* — практически не используется в реальном коде. В основном для оптимизации, если есть собственное управление памятью. Довелось как-то в собственном разборщике XML (работает в 2,5 раза медленнее рекордсмена, pugixml. Зато даже это в разы быстрее Excel’я, пространства имён «из коробки», расход памяти мизерный и программирование простейшее.)
    Зато по-чёрному используется его const-аналог.

    • const char*. Это может быть одинокий const char* + нуль-терминированная строка, или указатель+длина, или указатель на начало + указатель за конец.
    1. Если ожидается, что в функцию будем передавать строковый литерал.
    void writeEnum(st::Stream& st, int value, const char* names[]) {}
    
    enum class Letter { A, B, C, …, Z, NN };
    const char* natoNames[static_cast<int>(Letter::NN)] = { "alpha", "bravo", "charlie", … };
    writeEnum(someStream, static_cast<int>(Letter::E), natoName);

    2. Если операцию со строкой можно произвести «на месте», не заводя новую память: (trim, как известно,— обрезка пробелов в начале и конце)
    void trim(const char*& beg, const char*& end);

    3. Если структура данных паразитирует на чужих строках, не заводя своей памяти. Особенно если конструкция строк неизвестна (например, при передаче данных из плагина в плагин).
    struct ParasiteString { const char *beg, *end; };

    4. В библиотеках, если они реально настолько компактные, что нет нужды обязательно подключать жирный STL.

    • char[] — только как оптимизация, когда предельная длина строки известна и невелика.
    wchar_t* myFtos(double value, wchar_t* buf, const FloatFormat& format) {}
    
    wchar_t buf[100];
    myFtos(100.500, buf, FloatFormat::NICE);
    Ответ написан
    Комментировать
  • Как упаковать файл в проект и затем извлечь на C++ в Visual Studio?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть три способа хранения картинки в EXE-файле.
    1. Bitmap-ресурсом. Несжатая, большинство библиотек позволяют загрузить её в одну строчку.
    2. Двоичным ресурсом. Сжатие возможно любое, загрузка пишется несколько дольше.
    3. Массивом, const unsigned char picture[] = { };

    Я не знаю, с какой библиотекой для BMP вы работаете, и надо смотреть уже по месту.

    И наконец: для чего её распаковывать? Реально нужно? (Например, мне однажды нужно было распаковывать картинки, потому что не хотел писать просмотрщик графики и пользовался штатным.)
    Если нужно — то куда-нибудь во временный каталог, который тоже нужно сначала получить.
    Ответ написан
    4 комментария
  • Как создать полностью пустое приложение на С++ в QT Creator?

    @Mercury13
    Программист на «си с крестами» и не только
    Простой способ (говорят, что есть глюки!)
    import QtQuick 2.9
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
        flags: Qt.Window | Qt.FramelessWindowHint   // <<<<<<
    
        Text {
            id: text1
            x: 77
            y: 59
            text: qsTr("Test!!!")
            font.pixelSize: 12
        }
    }


    Сложный описал Александр Таратин, и в нём эти глюки решены.
    Ответ написан
    Комментировать
  • С++ В чем отличие #include "*" и #include?

    @Mercury13
    Программист на «си с крестами» и не только
    Первое — это include собственного заголовка, то есть искать его в рабочем каталоге, в дополнение к стандартным каталогам компилятора.

    #include <file>
    This variant is used for system header files. It searches for a file named file in a standard list of system directories. You can prepend directories to this list with the -I option (see Invocation).

    #include "file"
    This variant is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the quote directories and then the same directories used for <file>. You can prepend directories to the list of quote directories with the -iquote option.
    Ответ написан
    Комментировать
  • Почему чтение не разрешено?

    @Mercury13
    Программист на «си с крестами» и не только
    Отлично, вы уже запустили какой-то код. Но соглашение вызова так и не выдержали.
    1. Используйте соглашение вызова STDCALL. Тогда функция должна будет сама подчищать за собой. Поскольку в ней нет никаких локальных переменных, и подчистка не потребуется.
    typedef uint32_t WINAPI (*SomeFunc)();
    uint32_t result = (SomeFunc)exec();

    Заодно это позволит увидеть, что функция запустилась. В любом случае возвращаемое значение будет в eax.
    2. В конце нашей функции поставьте RET (опкод CB, если я не ошибаюсь).
    3. Вычислите и впатчите в наш код адрес переменной.

    я думал тут адрес указывается относительно текущего сегмента, как тогда быть?

    Начиная с защищённого режима 386, у нас «плоская память». Сегменты используются только загрузчиками, ВМами и прочей шушерой. Просто вычислите 32-битный адрес и запишите куда надо.
    Ответ написан
    Комментировать
  • Из-за чего ошибка чтения?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы компилируете функцию в двоичный код и на месте же вызываете. Так что есть вопросы.
    1. Функции обеспечили правильное соглашение вызова?
    Мне что-то кажется, что при подобной ручной компиляции проще работать с соглашением PASCAL или STDCALL — ну, шут его знает.
    2. VirtualProtect работает с целыми страницами. Так что на куске памяти из сегмента данных (ну или из стека, полного кода не вижу) она в лучшем случае откажет, в худшем ничего не сделает. Проверьте, была ли ошибка.
    3. Первый параметр должен быть source, а не &source.
    Ответ написан
    Комментировать
  • Как исправить ошибку при чтении файла на с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Велика вероятность, что ошибка в mods[mode]. Четырнадцать значений, записанных как 4+4+3+3 — что-то странное. Вы явно хотели сделать «кубик» из четырёх флагов, от младшего к старшему — W, A (причём работает как простое W, если A без W), B, RW
    Ответ написан