"#include" текстовый файл в программе на C как символ [] - PullRequest
117 голосов
/ 04 января 2009

Есть ли способ включить весь текстовый файл в виде строки в программу на C во время компиляции?

что-то вроде:

  • file.txt:

    This is
    a little
    text file
    
  • main.c:

    #include <stdio.h>
    int main(void) {
       #blackmagicinclude("file.txt", content)
       /*
       equiv: char[] content = "This is\na little\ntext file";
       */
       printf("%s", content);
    }
    

получение маленькой программы, которая печатает на стандартный вывод "Это немного текстовый файл "

В данный момент я использовал хакерский скрипт на python, но он довольно уродлив и ограничен только одним именем переменной, можете ли вы сказать мне другой способ сделать это?

Ответы [ 16 ]

0 голосов
/ 31 марта 2017

У меня были похожие проблемы, и для небольших файлов вышеупомянутое решение Йоханнеса Шауба сработало для меня как шарм.

Однако, для файлов, которые немного больше, он столкнулся с проблемами с ограничением массива символов компилятора. Поэтому я написал небольшое приложение-кодировщик, которое преобразует содержимое файла в двумерный массив символов одинакового размера (и, возможно, дополнения нулями). Он создает выходные текстовые файлы с данными 2D-массива, например:

const char main_js_file_data[8][4]= {
    {'\x69','\x73','\x20','\0'},
    {'\x69','\x73','\x20','\0'},
    {'\x61','\x20','\x74','\0'},
    {'\x65','\x73','\x74','\0'},
    {'\x20','\x66','\x6f','\0'},
    {'\x72','\x20','\x79','\0'},
    {'\x6f','\x75','\xd','\0'},
    {'\xa','\0','\0','\0'}};

где 4 на самом деле является переменной MAX_CHARS_PER_ARRAY в кодере. Файл с результирующим кодом C, называемый, например, main_js_file_data.h, может быть легко встроен в приложение C ++, например, так:

#include "main_js_file_data.h"

Вот исходный код кодера:

#include <fstream>
#include <iterator>
#include <vector>
#include <algorithm>


#define MAX_CHARS_PER_ARRAY 2048


int main(int argc, char * argv[])
{
    // three parameters: input filename, output filename, variable name
    if (argc < 4)
    {
        return 1;
    }

    // buffer data, packaged into chunks
    std::vector<char> bufferedData;

    // open input file, in binary mode
    {    
        std::ifstream fStr(argv[1], std::ios::binary);
        if (!fStr.is_open())
        {
            return 1;
        }

        bufferedData.assign(std::istreambuf_iterator<char>(fStr), 
                            std::istreambuf_iterator<char>()     );
    }

    // write output text file, containing a variable declaration,
    // which will be a fixed-size two-dimensional plain array
    {
        std::ofstream fStr(argv[2]);
        if (!fStr.is_open())
        {
            return 1;
        }
        const std::size_t numChunks = std::size_t(std::ceil(double(bufferedData.size()) / (MAX_CHARS_PER_ARRAY - 1)));
        fStr << "const char " << argv[3] << "[" << numChunks           << "]"    <<
                                            "[" << MAX_CHARS_PER_ARRAY << "]= {" << std::endl;
        std::size_t count = 0;
        fStr << std::hex;
        while (count < bufferedData.size())
        {
            std::size_t n = 0;
            fStr << "{";
            for (; n < MAX_CHARS_PER_ARRAY - 1 && count < bufferedData.size(); ++n)
            {
                fStr << "'\\x" << int(unsigned char(bufferedData[count++])) << "',";
            }
            // fill missing part to reach fixed chunk size with zero entries
            for (std::size_t j = 0; j < (MAX_CHARS_PER_ARRAY - 1) - n; ++j)
            {
                fStr << "'\\0',";
            }
            fStr << "'\\0'}";
            if (count < bufferedData.size())
            {
                fStr << ",\n";
            }
        }
        fStr << "};\n";
    }

    return 0;
}
0 голосов
/ 11 сентября 2014

Почему бы не связать текст с программой и не использовать его как глобальную переменную! Вот пример. Я рассматриваю возможность использования этого для включения файлов шейдеров Open GL в исполняемый файл, поскольку шейдеры GL должны быть скомпилированы для GPU во время выполнения.

0 голосов
/ 15 апреля 2014

Я думаю, что это невозможно только с помощью компилятора и препроцессора. GCC позволяет это:

#define _STRGF(x) # x
#define STRGF(x) _STRGF(x)

    printk ( MODULE_NAME " built " __DATE__ " at " __TIME__ " on host "
            STRGF(
#               define hostname my_dear_hostname
                hostname
            )
            "\n" );

Но, к сожалению, не это:

#define _STRGF(x) # x
#define STRGF(x) _STRGF(x)

    printk ( MODULE_NAME " built " __DATE__ " at " __TIME__ " on host "
            STRGF(
#               include "/etc/hostname"
            )
            "\n" );

Ошибка:

/etc/hostname: In function ‘init_module’:
/etc/hostname:1:0: error: unterminated argument list invoking macro "STRGF"
0 голосов
/ 13 апреля 2013

Ответ Хастуркуна с опцией xxd -i превосходен. Если вы хотите включить процесс преобразования (текст -> шестнадцатеричный включаемый файл) непосредственно в вашу сборку, инструмент / библиотека hexdump.c недавно добавил возможность, аналогичную опции -i в xxd (она не дает вам полный заголовок - вам нужно предоставить определение массива char - но у этого есть преимущество, позволяющее вам выбрать имя массива char):

http://25thandclement.com/~william/projects/hexdump.c.html

Эта лицензия гораздо более "стандартная", чем xxd, и очень либеральная - пример использования ее для встраивания файла инициализации в программу можно увидеть в файлах CMakeLists.txt и sche.c здесь:

https://github.com/starseeker/tinyscheme-cmake

Есть плюсы и минусы как в отношении включения сгенерированных файлов в деревья исходного кода, так и в утилиты компоновки - как их обрабатывать, будет зависеть от конкретных целей и потребностей вашего проекта. hexdump.c открывает опцию комплектации для этого приложения.

0 голосов
/ 05 января 2009

в х.ч

"this is a "
"buncha text"

в main.c

#include <stdio.h>
int main(void)
{
    char *textFileContents =
#include "x.h"
    ;

    printf("%s\n", textFileContents);

    return 0
}

должен сделать работу.

0 голосов
/ 04 января 2009

Даже если это можно сделать во время компиляции (я не думаю, что это возможно вообще), текст, скорее всего, будет предварительно обработанным заголовком, а не дословным содержимым файлов. Я ожидаю, что вам придется загрузить текст из файла во время выполнения или выполнить неприятное задание «вырезать и вставить».

...