Задать вопрос
  • Есть ли хорошие пошаговые туториалы проектов на С++ для новичков?

    old2ev
    @old2ev
    int main(){for(;;)fork();}
    Для начала лучше хорошо выучить стандартную библиотеку плюсов, вот тебе аналог MDN из мира плюсов)

    На главной странице cppreference можно идти от тематики к тематике (заголовки жирным: Language, Standard library (headers) и т.д.), если хреново с инглишским, поставь расширение-переводчик в твой хроме или огнелис.

    Далее можно выбрать между boost или Qt и учить их (если вот прям совсем нужен графоний выбирай второй, ну и как бывшему жабаскриптизёру с Qt будет легче, поскольку ЖэAss там есть, хоть и старого стандарта). Оба фреймворка насыщают кресты тем, к чему программист-обыкновенный привык в питухоне или жабаскрипте.

    А вообще наличие идеи для пет-проект решает проблему с вопросом "а чего бы поучить?", не стоит разводить детски сад выбирая что-то элементарное, но и упарываться на отличненько тоже не стоит.

    Рекомендую этих YT-индусов:
    * Begin End - пишет разные проектики, задаёт домашку, подача чувака прикольная, крайне рекомендую.
    * C++ Лекции МФТИ Мещерин - лекции которые довольно много чего затрагивают
    * C++ UserGroup - что новенького в крестах и не только
    Ответ написан
    Комментировать
  • Почему метод push_front() работает неправильно?

    old2ev
    @old2ev
    int main(){for(;;)fork();}
    1-е строка 22 проинициализируйте указатель нулём, иначе у Вас функция ловит ошибку сегментации в лучшем случае, в худшем идёт гулять по оперативке:
    Node* pNext = nullptr;

    2-e строки 25-29 у Вас pNextинициализируется сам собой поскольку аргумент конструктора именован pnext. Замените pnext в аргументе на pNext:
    Node(T data = T(), Node* pNext = nullptr) {
      this->pNext = pNext;
      this->data = data;
    }

    А лучше инициализируйте поля объекта класса через конструктор так:
    Node(T data = T(), Node* pNext = nullptr) 
      : pNext(pNext), data(data) {}

    В таком случае IDE кидает предупреждение, если поле инициализируется само собой.

    После вышеуказанных исправлений всё работает:
    Список:
    1) 12
    2) 346
    3) 1348
    4) 546
    
    
    
    
    Список после push_front():
    1) 78
    2) 12
    3) 346
    4) 1348
    5) 546


    +Совет сверху: Лучше храните в листе указатель на последний узел списка, чтобы не перебрирать весь список при push_back, так асимптотика будет O(1), а не O(N) при минимальных затратах памяти (+8 байт на x64 или +4 байта на x32)
    Ответ написан
    Комментировать
  • Возможно ли изменить исполняемый файл в процессе выполнения*?

    old2ev
    @old2ev
    int main(){for(;;)fork();}
    Из того что приходит на ум только костыль аля открыть ofstream переписать им файл, натравить на него через system компилятор и за тем перезапустить программу через exec из скомпилированного файла. Да это можно было бы сделать, но это бред. Менять C/C++ код в рантайме всё равно что юзать микроскоп для забивания гвоздей. Проще было бы подключить V8 и в рантайме менять JavaScript он так из коробки умеет вродебы.

    Вообще, хотелось бы уточнить зачем вам это нужно? Ибо я даже придумать не могу причину для данных махинаций с кодом. Всплывала в голове подобная бредятина, когда выдумывал систему модулей для C++, но вопрос решился через подгрузку динамических библиотек во время выполнения, так если что C и C++ умеют.

    Так же есть вариант для совсем уж отбитых: писать в исполняемый файл через ofstream машинный код(предварительно скопировав сам исполняемый на системах семейства Windows) и перезапускаться exec'ом, но тут более чем дофига причин так не делать - как минимум будет больно и страшно.
    Ответ написан
  • Как создать папку на рабочем столе средствами c++?

    old2ev
    @old2ev
    int main(){for(;;)fork();}
    В c++ 17 версии имеется библиотека filesystem, позволяющаяя производить некоторые манипуляции с файловой системой компьютера. Что касательно вашего вопроса там есть такая функция как bool create_directory(...). Данная функция принимает в качестве аргумента путь конец которого - имя папки для создания.

    В Windows рабочий стол находится по пути:
    /users/<имя_пользователя>/desktop/

    В Unix-like (BSD, Linux и т.д.) по пути:
    /home/<имя_пользователя>/desktop/

    И того нам нужно получить имя юзера:
    В Windows это как-то так:

    #include <windows.h>
    #include <Lmcons.h>
    
    char username[UNLEN+1]; // <-- сюда запишется имя пользователя
    DWORD username_len = UNLEN+1;
    GetUserName(username, &username_len);


    Итого, код для Windows будет выглядеть как-то так:

    #include <windows.h>
    #include <Lmcons.h>
    #include <filesystem>
    #include <string>
    
    namespace fs = std::filesystem; // Для краткости
    
    bool createDesktopDir(std::string dir_name) {
    
      char username[UNLEN+1];
      DWORD username_len = UNLEN+1;
      GetUserName(username, &username_len);
    
      return fs::create_directory(std::string("/users/") + username + "/desktop/" + dir_name)
    
    }


    Для Unix-like ОС получения юзера выглядит так:
    #include <unistd.h>
    char username[1024] = {0};
    getlogin_r(username, sizeof(username)-1);


    А следовательно код для создания директории будет такой:

    #include <unistd.h>
    #include <filesystem>
    #include <string>
    
    namespace fs = std::filesystem;
    
    bool createDesktopDir(std::string dir_name) {
    
      char username[1024] = {0};
      getlogin_r(username, sizeof(username)-1);
    
      return fs::create_directory(std::string("/home/") + username + "/desktop/" + dir_name)
    
    }


    Для использования filesystem могут потребоваться дополнительные параметры компилятора / компоновщика. Реализация GNU до 9.1 (то есть GCC) требует связывания с -lstdc++fs, а реализация LLVM до LLVM 9.0 (то есть clang) требует связывания с -lc++fs.

    С Unix могут быть проблемы если вы запустили программу от root поскольку его домашняя директория находится по адресу /root/, а следовательно и рабочий стол тут /root/desktop/. Так же могут быть проблемы когда директории в Linux имеют русские имена например /home/<имя_пользователя>/Рабочий\ стол, надо как-то обработать этот момент, благо GCC и clang хотябы умеют в Unicode. В Windows же могут быть проблемы с компиляторами MinGW если имя пользователя на русском (или другом языкие содержащим Unicode-символы) ибо использовать в путях на текущий момент они могут только в ASCII-символы, то есть только латиница. Тут либо кушать кактус и кидать из кодировки в кодировку, либо юзать visual c++. В общем удачи
    Ответ написан
    1 комментарий
  • Как скомпилировать .so файл в .c?

    old2ev
    @old2ev
    int main(){for(;;)fork();}
    Сишный код получить точно не получится, максимум что можно - это дизассемблировать (https://ru.wikipedia.org/wiki/Objdump) и получить огрмный текст ассемблера на выходе, а за тем проходясь по меткам переписать алгоритм в Си.
    Ответ написан
    Комментировать
  • Можно ли в C++ передать в шаблонный параметр класса типа unsigned long размер инит-листа aka std::initializer_list::size() через конструктор?

    old2ev
    @old2ev Автор вопроса
    int main(){for(;;)fork();}
    template <size_t size>
    class A {
        Any_Type array[size];
    public:
    
        template<size_t size>
        A(A<size>& other) {/*Инициализация массива array данными из other*/}
    
        template<size_t size>
        A(A<size>&& other) {/*Инициализация массива array данными из other*/}
    
        template<size_t size>
        A(const Any_Type (&&arr)[size]) {/*Инициализация массива array данными из arr*/}
    
    };
    
    template<size_t size>
    A(A<size>& other) -> A<size>;
    
    template<size_t size>
    A(A<size>&& other) -> A<size>;
    
    template<size_t size>
    A(const Any_Type (&&arr)[size]) -> A<size>;
    
    //......//
    
    A a({1,2,3,4,5,6});
    Ответ написан
    Комментировать