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

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Тут два выхода:
    1. использовать wchar_t вместо char.
    2. выставить локаль через std::setlocale.


    Учитывая, что это Arch, ты мог не сгенерить русскую локаль при установке: https://wiki.archlinux.org/index.php/Installation_...
    Ответ написан
    Комментировать
  • Ошибка LNK2019 и LNK2001, как их решить?

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Скорее всего инстанцирование класса находится в одной единице трансляции, а определение функции - в другой.
    Поскольку код функции генерируется во время инстанцирования класса, то на момент инстанцирования компилятор должен знать какой тип "подставить" в функцию. Если определение находится в другой единице трансляции, то у компилятора, который компилирует файл с объявлением, нет возможности сгенерировать нужную функцию.

    После компиляции, линкер пытается решить зависимости и не находит нужную функцию, потому что она не сгенерировалась.

    Чтобы избежать этого, поместите определение функции в хедер с объявлением.
    Вот похожая проблема.
    Ответ написан
    Комментировать
  • Как подключить библиотеку с GitHub в свой проект (C++)?

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Я так понял, у вас VS?
    У библиотеки инструмент сборки - make, так что вам придется либо собирать библиотеку отдельно от проекта студии (при условии, что у вас есть clang или gcc) или:

    Самый простой подход:
    Добавьте в ваш проект cpp и h файлы либы и добавьте в Include files путь к h-файлам библиотеки.

    Правильный подход:
    Соберите либу как отдельный проект:
    Добавьте в него cpp и h файлы либы, скомпилируйте как статическую библиотеку, слинкуйте с вашим проектом (нужно указать Library Directories и сами либы)
    Ответ написан
    2 комментария
  • Как получить дробное число при делении 1 на 1?

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Тип вашего выражения - double.
    Это можно проврить очень простым способом (я так сделал):

    создать объявление шаблонного класса без реализации и инстанцировать его выражением. Ошибка компиляции покажет тип:

    template <typename T>
    class TD;
    
    int main() {
        int i = 1;
        int j = 1;
    
        TD<decltype (1.0 * i / j)> td;
    }


    Ошибка:
    /home/maxim/Workspace/my/cdm/main.cpp: In function ‘int main()’:
    /home/maxim/Workspace/my/cdm/main.cpp:61:32: error: aggregate ‘TD<double> a’ has incomplete type and cannot be defined
         TD<decltype (1.0 * i / j)> a;


    Как видим, тип вывелся как double
    Ответ написан
    Комментировать
  • Как правильно переопределить функции и типы при наследовании класса?

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Мне нужно знать, зачем Вы хотите такое сделать, иначе не понятно, почему пытаетесь использовать перегрузку типов (которой нет).

    Если Вам нужно полиморфное поведение - воспользуйтесь виртуальными функциями.
    Теперь разберем Ваш код в одном месте:
    typedef float custom;
    Здесь не происходит ничего иного, кроме как объявления имени в области видимости класса B. Как я говорил выше переопределять типы нельзя, и от написанного Вами кода, тип custom в А не поменяется. Иными словами у вас будет два типа:
    A::custom = int
    B::custom = float


    Что Вам нужно сделать:
    class I
    {
    public:
        virtual void print() = 0;
    };
    
    class A : public I
    {
    public:
        virtual void print() override 
        {
            std::cout << num;
        }
    
    private:
        int num = 1;
    };
    
    class B : public I
    {
    public:
        virtual void print() override 
        {
            std::cout << num;
        }
    
    private:
        float num = 2.f;
    };


    Иерархии из трех классов можно избежать, написав простой шаблон:

    template <typename T>
    class A
    {
    public:
        void print()
        {
            std::cout << val;
        }
    
    private:
        T val;
    };
    Ответ написан
    Комментировать
  • Как понимать бинарные файлы?

    reverse_kacejot
    @reverse_kacejot
    Junior C++ Developer, bachelor of Applied Math
    Как гласит страничка википедии для того же формата .3ds - "The first two bytes of the chunk are its ID". У каждого формата - свое бинарное представление со своими чанками. Типичным примером могут быть исполнимые файлы Windows - PE и для Linux - ELF. Для ELF-файлов есть хорошая спецификация, которая объясняет какие чанки бывают, какие у них заголовки, какие поля у заголовков, какой размер у чанком (если он не переменный).
    Еще есть spool файлы принтеров - у них тоже своих заголовки.

    Из общего, что можно вынести:
    В бинарном представлении информация не хранится в голом виде, а чаще всего обернута в блоки с заголовками. У заголовков могут быть идентификаторы (как те циферки, о которых ты спросил), размер блока и другая вспомогательная информация, которая зависит от спецификации заголовка.

    Обещанные ссылки на спеки бинарей:
    ELF - Executable and Linkable format
    EMFSPL
    EMF
    PE

    Вот нашел свой парсер секций для Portable Executable
    #include <stdio.h>
    #include <windows.h>
    
    #define RTN_OK 0
    #define RTN_FAILURE 1
    
    const size_t expected_count = 1;
    
    char* read_file_name(int argc, char** argv);
    
    int main(int argc, char** argv)
    {
    	// Parsing command line args
    	char* file_name = read_file_name(argc, argv);
    	
    	// Opening our executable
    	FILE* portable_executable = fopen(file_name, "r");
    
    	// Reading dos header
    	IMAGE_DOS_HEADER dos_header_buffer;
    	fread(&dos_header_buffer, sizeof(IMAGE_DOS_HEADER), expected_count, portable_executable);
    
    	// Setting offset for reading PE header
    	fseek(portable_executable, (long)dos_header_buffer.e_lfanew, SEEK_SET)
    
    	// Reading signature field from PE header
    	DWORD signature = 0;
    	fread(&signature, sizeof(DWORD), expected_count, portable_executable);
    
    	// Reading file header
    	IMAGE_FILE_HEADER file_header_buffer;
    	fread(&file_header_buffer, sizeof(IMAGE_FILE_HEADER), expected_count, portable_executable);
    
    	// Reading optinal header
    	IMAGE_OPTIONAL_HEADER optional_header_buffer;
    	fread(&optional_header_buffer, file_header_buffer.SizeOfOptionalHeader, expected_count, portable_executable);
    
    	// Get info about all the sections
    	for (int i = 0; i < file_header_buffer.NumberOfSections; ++i)
    	{
    		// Reading each section header
    		IMAGE_SECTION_HEADER section_header_buffer;
    		fread(&section_header_buffer, sizeof(IMAGE_SECTION_HEADER), expected_count, portable_executable);
    		
    		printf("Section name: %7s, Raw data size: %10d, Pointer to raw data: %10d\n",
    			section_header_buffer.Name,
    			section_header_buffer.SizeOfRawData,
    			section_header_buffer.PointerToRawData);
    	}
    
    	fclose(portable_executable);
    }
    
    char* read_file_name(int argc, char** argv)
    {
    	if (argc != 2)
    	{
    		return NULL;
    	}
    
    	return argv[1];
    }
    Ответ написан
    Комментировать