“#Include” file teks dalam program C sebagai char []

130

Apakah ada cara untuk memasukkan seluruh file teks sebagai string dalam program C pada waktu kompilasi?

sesuatu seperti:

  • 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);
    }

mendapatkan program kecil yang dicetak di stdout "Ini adalah file teks kecil"

Saat ini saya menggunakan skrip python peretasan, tapi itu jelek dan hanya terbatas pada satu nama variabel, dapatkah Anda memberi tahu saya cara lain untuk melakukannya?

Brian Tompsett - 汤 莱恩
sumber
Lihatlah di sini untuk membaca file menjadi char []. /programming/410943/reading-a-text-file-into-an-array-in-c Berikut adalah beberapa tips untuk menggunakan macro preprocessor C. http://gcc.gnu.org/onlinedocs/cpp/Macros.html
Daniel A. White
3
Mengapa Anda ingin melakukan ini? Mengapa tidak membaca file saat runtime? (Jawab: mungkin karena sulit untuk mengetahui di mana file itu pada saat runtime, atau mungkin karena hanya ada satu file untuk menginstal.)
Jonathan Leffler
atau, mungkin file teks hanya tersedia pada waktu kompilasi, seperti kode sumber.
TMS
1
Kadang-kadang Anda ingin mengakses data sebagai file terpisah pada waktu pengembangan tetapi konten dikompilasi ke dalam biner Anda. Contohnya adalah menjalankan server web pada Arduino yang tidak memiliki akses ke penyimpanan lokal. Anda ingin menjaga file html Anda terpisah untuk mengeditnya tetapi pada waktu kompilasi mereka harus ada sebagai string di sumber Anda.
Geordie

Jawaban:

134

Saya sarankan menggunakan (unix util) xxd untuk ini. Anda bisa menggunakannya seperti itu

$ echo hello world > a
$ xxd -i a

output:

unsigned char a[] = {
  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;
Hasturkun
sumber
18
Hanya sebuah catatan: char [] yang dibuat oleh xxd tidak diakhiri dengan NULL! jadi saya melakukan $ xxd -i <file.txt> file.xxd $ echo ', 0' >> file.xxd dan di file_content main.c char [] = {#include "file.xxd"};
2
Saya tidak pernah tahu tentang xxd. Itu mengagumkan!
1
@ eSKay: yang datang langsung dari output xxd, seperti jawabannya. nama array adalah nama file input. jika Anda memipipkan data alih-alih menggunakan file input, Anda akan mendapatkan daftar nilai heksadesimal sebagai gantinya (tanpa deklarasi array atau variabel len).
Hasturkun
4
Itu sangat berguna saat menanamkan shader GLSL.
linello
5
Cara lain untuk menambahkan 0x00 terminasi ke xxd menghasilkan kode C:xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
vleo
104

Pertanyaannya adalah tentang C tetapi jika seseorang mencoba melakukannya dengan C ++ 11 maka itu dapat dilakukan dengan hanya sedikit perubahan pada file teks yang dimasukkan berkat literal string mentah yang baru :

Di C ++ lakukan ini:

const char *s =
#include "test.txt"
;

Dalam file teks lakukan ini:

R"(Line 1
Line 2
Line 3
Line 4
Line 5
Line 6)"

Jadi hanya ada awalan di bagian atas file dan akhiran di akhir file. Di antara itu Anda dapat melakukan apa yang Anda inginkan, tidak ada pelarian khusus diperlukan selama Anda tidak memerlukan urutan karakter )". Tetapi bahkan ini dapat bekerja jika Anda menentukan pembatas khusus Anda sendiri:

R"=====(Line 1
Line 2
Line 3
Now you can use "( and )" in the text file, too.
Line 5
Line 6)====="
kayahr
sumber
5
Terima kasih, saya memilih metode yang diusulkan di sini untuk menanamkan fragmen panjang sql ke dalam kode C ++ 11 saya. Ini memungkinkan saya untuk menjaga SQL dipisahkan dengan rapi ke dalam file sendiri, dan mengeditnya dengan memeriksa sintaks yang sesuai, menyoroti dll.
YitzikC
1
Ini sangat dekat dengan apa yang saya inginkan. Terutama pemisah yang ditentukan pengguna. Sangat berguna. Saya ingin melangkah lebih jauh: apakah ada cara untuk menghapus awalan R "(dan suffix)" dari file yang ingin Anda sertakan? Saya mencoba mendefinisikan dua file yang disebut bra.in dan ket.in dengan awalan dan sufiks di dalamnya, termasuk bra.in, file.txt, dan ket.in satu per satu. Tetapi kompiler mengevaluasi konten bra.in (yang hanya R "() sebelum memasukkan file berikutnya. Jadi akan mengeluh. Tolong beri tahu saya jika ada yang tahu cara mendapatkan awalan dan akhiran dari file.txt. Terima kasih.
TMS
Saya menduga C ++ tidak akan mengizinkan R "(<newline> #include ...)"? Akan menyenangkan untuk memiliki file yang dikompilasi-waktu untuk tidak memerlukan pengkodean apa pun .... yaitu json lurus atau xml atau csv atau apa yang tidak ..
Brian Chrisman
Anda dapat membuat teks literal mentah sedikit lebih mudah dibaca jika Anda menggunakan 1+R"...sebagai pembatas awal alih-alih R"..., dan kemudian menambahkan baris baru sebelumnya Line 1. Ini akan mengubah ekspresi dari sebuah array ke sebuah pointer, tapi itu bukan masalah di sini, karena Anda menginisialisasi pointer, bukan sebuah array.
Ruslan
14

Anda memiliki dua kemungkinan:

  1. Manfaatkan ekstensi kompiler / penghubung untuk mengkonversi file menjadi file biner, dengan simbol yang tepat menunjuk ke awal dan akhir data biner. Lihat jawaban ini: Sertakan file biner dengan skrip linker GNU .
  2. Konversikan file Anda menjadi urutan konstanta karakter yang dapat menginisialisasi array. Perhatikan Anda tidak bisa hanya melakukan "" dan merentang beberapa baris. Anda membutuhkan karakter kelanjutan garis ( \), "karakter melarikan diri dan lainnya untuk membuatnya bekerja. Lebih mudah untuk hanya menulis program kecil untuk mengubah byte menjadi urutan seperti '\xFF', '\xAB', ...., '\0'(atau gunakan alat unix yang xxddijelaskan oleh jawaban lain, jika Anda memilikinya tersedia!):

Kode:

#include <stdio.h>

int main() {
    int c;
    while((c = fgetc(stdin)) != EOF) {
        printf("'\\x%X',", (unsigned)c);
    }
    printf("'\\0'"); // put terminating zero
}

(tidak diuji). Kemudian lakukan:

char my_file[] = {
#include "data.h"
};

Di mana data.h dihasilkan oleh

cat file.bin | ./bin2c > data.h
Johannes Schaub - litb
sumber
1
baris terakhir mungkin harus membaca "cat file.bin | ./bin2c> data.h" atau "./bin2c <file.bin> data.h"
Hasturkun
Saya menggunakan codeproject.com/Tips/845393/... untuk membuat file hex (pada Windows) dari biner dan kemudian menggunakan saran Anda tentang char my_file[] = { #include my_large_file.h };Terima kasih!
Seseorang di suatu tempat
bin2cadalah tidak yang bin2c sama dari ini debian hxtools, berhati-hatilah
ThorSummoner
atau jika ya, pemanggilannya jauh lebih aneh sekarang:bin2c -H myoutput.h myinput1.txt myinputN.txt
ThorSummoner
9

ok, terinspirasi oleh posting Daemin saya menguji contoh sederhana berikut:

a.data:

"this is test\n file\n"

test.c:

int main(void)
{
    char *test = 
#include "a.data"
    ;
    return 0;
}

gcc -E test.c output:

# 1 "test.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test.c"

int main(void)
{
    char *test =
# 1 "a.data" 1
"this is test\n file\n"
# 6 "test.c" 2
    ;
    return 0;
}

Jadi ini berfungsi tetapi membutuhkan data yang dikelilingi dengan tanda kutip.

Ilya
sumber
Itulah yang saya singgung di bagian terakhir dari jawaban saya.
Daemin
kutipan, atau apa pun namanya, maafkan bahasa Inggris saya
Ilya
Ini membutuhkan data yang akan di-C melarikan diri. Saya tidak berpikir itulah yang dicari pos tersebut. Jika ini memiliki semacam menyertakan makro yang C-lolos isi file, itu akan baik-baik saja.
Brian Chrisman
8

Saya suka jawaban kayahr. Jika Anda tidak ingin menyentuh file input , dan jika Anda menggunakan CMake , Anda dapat menambahkan urutan karakter delimeter pada file. Kode CMake berikut, misalnya, menyalin file input dan membungkus isinya sesuai:

function(make_includable input_file output_file)
    file(READ ${input_file} content)
    set(delim "for_c++_include")
    set(content "R\"${delim}(\n${content})${delim}\"")
    file(WRITE ${output_file} "${content}")
endfunction(make_includable)

# Use like
make_includable(external/shaders/cool.frag generated/cool.frag)

Kemudian sertakan dalam c ++ seperti ini:

constexpr char *test =
#include "generated/cool.frag"
;
Martin R.
sumber
5

Anda dapat melakukan ini menggunakan objcopy:

objcopy --input binary --output elf64-x86-64 myfile.txt myfile.o

Sekarang Anda memiliki file objek yang dapat Anda tautkan ke executable Anda yang berisi simbol untuk awal, akhir, dan ukuran konten myfile.txt.

John Zwinck
sumber
1
apakah Anda dapat memberi tahu kami apa nama simbolnya?
Mark Ch
@ MarkCh: Sesuai dokumen, nama simbol dihasilkan dari nama file input.
John Zwinck
Saya menduga ini tidak akan bekerja pada mesin non x86-64, kan?
ThorSummoner
2

Anda memerlukan xtrutilitas saya tetapi Anda dapat melakukannya dengan bash script. Ini adalah skrip yang saya panggil bin2inc. Parameter pertama adalah nama yang dihasilkan char[] variable. Parameter kedua adalah nama file. Outputnya adalah C include filedengan konten file yang dikodekan (dalam huruf kecil hex) sebagai nama variabel yang diberikan. The char arrayadalah zero terminated, dan panjang data disimpan di$variableName_length

#!/bin/bash

fileSize ()

{

    [ -e "$1" ]  && {

        set -- `ls -l "$1"`;

        echo $5;

    }

}

echo unsigned char $1'[] = {'
./xtr -fhex -p 0x -s ', ' < "$2";
echo '0x00'
echo '};';
echo '';
echo unsigned long int ${1}_length = $(fileSize "$2")';'

ANDA BISA DAPATKAN XTR DI SINI xtr (karakter eXTRapolator) adalah GPLV3


sumber
2

Jika Anda mau menggunakan beberapa trik kotor Anda bisa berkreasi dengan literal string mentah dan #includeuntuk jenis file tertentu.

Sebagai contoh, katakan saya ingin memasukkan beberapa skrip SQL untuk SQLite dalam proyek saya dan saya ingin mendapatkan penyorotan sintaksis tetapi tidak ingin infrastruktur pembangunan khusus. Saya dapat memiliki file ini test.sqlyang merupakan SQL untuk SQLite yang valid tempat --memulai komentar:

--x, R"(--
SELECT * from TestTable
WHERE field = 5
--)"

Dan kemudian dalam kode C ++ saya, saya dapat memiliki:

int main()
{
    auto x = 0;
    const char* mysql = (
#include "test.sql"
    );

    cout << mysql << endl;
}

Outputnya adalah:

--
SELECT * from TestTable
WHERE field = 5
--

Atau untuk memasukkan beberapa kode Python dari file test.pyyang merupakan skrip Python yang valid (karena #memulai komentar dalam Python dan passmerupakan no-op):

#define pass R"(
pass
def myfunc():
    print("Some Python code")

myfunc()
#undef pass
#define pass )"
pass

Dan kemudian dalam kode C ++:

int main()
{
    const char* mypython = (
#include "test.py"
    );

    cout << mypython << endl;
}

Yang akan menghasilkan:

pass
def myfunc():
    print("Some Python code")

myfunc()
#undef pass
#define pass

Seharusnya dimungkinkan untuk memainkan trik serupa untuk berbagai jenis kode lain yang mungkin ingin Anda sertakan sebagai string. Apakah itu ide yang bagus atau tidak, saya tidak yakin. Ini semacam peretasan yang rapi tetapi mungkin bukan sesuatu yang Anda inginkan dalam kode produksi nyata. Mungkin ok untuk proyek hack akhir pekan.

mattnewport
sumber
Saya telah menggunakan pendekatan ini untuk menempatkan OpenGL Shaders dalam file teks juga!
yano
1

Saya mengimplementasikan ulang xxd di python3, memperbaiki semua gangguan xxd:

  • Kebenaran Const
  • datatype panjang string: int → size_t
  • Pengakhiran nol (jika Anda menginginkannya)
  • Kompatibel dengan string C: Jatuhkan unsignedpada array.
  • Output yang lebih kecil dan mudah dibaca, seperti yang Anda tulis: Printable ascii adalah output apa adanya; byte lain dikodekan dengan hex.

Ini skripnya, difilter dengan sendirinya, sehingga Anda dapat melihat fungsinya:

pyxxd.c

#include <stddef.h>

extern const char pyxxd[];
extern const size_t pyxxd_len;

const char pyxxd[] =
"#!/usr/bin/env python3\n"
"\n"
"import sys\n"
"import re\n"
"\n"
"def is_printable_ascii(byte):\n"
"    return byte >= ord(' ') and byte <= ord('~')\n"
"\n"
"def needs_escaping(byte):\n"
"    return byte == ord('\\\"') or byte == ord('\\\\')\n"
"\n"
"def stringify_nibble(nibble):\n"
"    if nibble < 10:\n"
"        return chr(nibble + ord('0'))\n"
"    return chr(nibble - 10 + ord('a'))\n"
"\n"
"def write_byte(of, byte):\n"
"    if is_printable_ascii(byte):\n"
"        if needs_escaping(byte):\n"
"            of.write('\\\\')\n"
"        of.write(chr(byte))\n"
"    elif byte == ord('\\n'):\n"
"        of.write('\\\\n\"\\n\"')\n"
"    else:\n"
"        of.write('\\\\x')\n"
"        of.write(stringify_nibble(byte >> 4))\n"
"        of.write(stringify_nibble(byte & 0xf))\n"
"\n"
"def mk_valid_identifier(s):\n"
"    s = re.sub('^[^_a-z]', '_', s)\n"
"    s = re.sub('[^_a-z0-9]', '_', s)\n"
"    return s\n"
"\n"
"def main():\n"
"    # `xxd -i` compatibility\n"
"    if len(sys.argv) != 4 or sys.argv[1] != \"-i\":\n"
"        print(\"Usage: xxd -i infile outfile\")\n"
"        exit(2)\n"
"\n"
"    with open(sys.argv[2], \"rb\") as infile:\n"
"        with open(sys.argv[3], \"w\") as outfile:\n"
"\n"
"            identifier = mk_valid_identifier(sys.argv[2]);\n"
"            outfile.write('#include <stddef.h>\\n\\n');\n"
"            outfile.write('extern const char {}[];\\n'.format(identifier));\n"
"            outfile.write('extern const size_t {}_len;\\n\\n'.format(identifier));\n"
"            outfile.write('const char {}[] =\\n\"'.format(identifier));\n"
"\n"
"            while True:\n"
"                byte = infile.read(1)\n"
"                if byte == b\"\":\n"
"                    break\n"
"                write_byte(outfile, ord(byte))\n"
"\n"
"            outfile.write('\";\\n\\n');\n"
"            outfile.write('const size_t {}_len = sizeof({}) - 1;\\n'.format(identifier, identifier));\n"
"\n"
"if __name__ == '__main__':\n"
"    main()\n"
"";

const size_t pyxxd_len = sizeof(pyxxd) - 1;

Penggunaan (ini mengekstrak skrip):

#include <stdio.h>

extern const char pyxxd[];
extern const size_t pyxxd_len;

int main()
{
    fwrite(pyxxd, 1, pyxxd_len, stdout);
}
pengguna2394284
sumber
1

Apa yang mungkin berhasil adalah jika Anda melakukan sesuatu seperti:

int main()
{
    const char* text = "
#include "file.txt"
";
    printf("%s", text);
    return 0;
}

Tentu saja Anda harus berhati-hati dengan apa yang sebenarnya ada di file , memastikan tidak ada tanda kutip ganda, bahwa semua karakter yang sesuai lolos, dll.

Oleh karena itu mungkin lebih mudah jika Anda hanya memuat teks dari file saat runtime , atau menanamkan teks langsung ke dalam kode.

Jika Anda masih menginginkan teks dalam file lain, Anda dapat memilikinya di sana, tetapi harus direpresentasikan di sana sebagai string. Anda akan menggunakan kode seperti di atas tetapi tanpa tanda kutip ganda di dalamnya. Sebagai contoh:

file.txt

"Something evil\n"\
"this way comes!"

main.cpp

int main()
{
    const char* text =
#include "file.txt"
;
    printf("%s", text);
    return 0;
}

Jadi pada dasarnya memiliki string gaya C atau C ++ dalam file teks yang Anda sertakan. Itu akan membuat kode lebih rapi karena tidak ada banyak teks pada awal file.

Daemin
sumber
3
Ide bagus tapi itu tidak akan berfungsi, baik Anda memiliki kesalahan karena literal termasuk baris baru atau bagian #include akan dibaca sebagai string dan tidak dieksekusi, terkutuk jika Anda melakukannya dan terkutuk jika Anda tidak .. .
Motti
1
@Motti: setuju - seperti yang tertulis, secara sintaks tidak valid C. Idenya menarik - C Pra-Prosesor secara logis merupakan fase yang terpisah - tetapi praktiknya adalah ia tidak turun karena setiap baris dalam file yang disertakan akan memiliki diakhiri dengan backslash, dll.
Jonathan Leffler
2
Humm. Menurut saya bahwa Anda tidak perlu backslash karena sebagian besar kompiler akan menyatukan string adjecent bersama
EvilTeach
masalahnya dengan jawaban ini adalah ... jika sesederhana itu, saya tidak berpikir OP akan pernah mengajukan pertanyaan! -1 karena kehadiran jawaban ini sedikit mendorong orang untuk membuang waktu mereka mencoba sesuatu yang tidak berhasil. Saya pikir kami dapat menghapus downvote jika Anda mengubah "Apa yang mungkin berhasil" menjadi "Untuk referensi, ini tidak berfungsi"
Mark Ch
@JonathanLeffler Setelah preprocessor berjalan, itu harus valid C atau C ++ tergantung pada bagaimana file.txt diformat.
Daemin
0

Bahkan jika itu dapat dilakukan pada waktu kompilasi (saya tidak berpikir itu bisa secara umum), teks kemungkinan akan menjadi header preprocessed daripada isi file kata demi kata. Saya berharap Anda harus memuat teks dari file saat runtime atau melakukan pekerjaan cut-n-paste jahat.

Daniel Paull
sumber
0

Jawaban Hasturkun menggunakan opsi xxd -i sangat bagus. Jika Anda ingin memasukkan proses konversi (teks -> hex include file) langsung ke build Anda hexdump.c alat / pustaka baru-baru ini menambahkan kemampuan yang mirip dengan opsi xxd's -i (itu tidak memberi Anda header lengkap - Anda perlu untuk memberikan definisi array char - tetapi memiliki keuntungan membiarkan Anda memilih nama array char):

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

Lisensi itu jauh lebih "standar" daripada xxd dan sangat liberal - contoh menggunakannya untuk menanamkan file init dalam sebuah program dapat dilihat di file CMakeLists.txt dan file sche.c di sini:

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

Ada pro dan kontra baik untuk memasukkan file yang dihasilkan di pohon sumber dan utilitas bundling - cara mengatasinya akan tergantung pada tujuan dan kebutuhan spesifik proyek Anda. hexdump.c membuka opsi bundling untuk aplikasi ini.

starseeker
sumber
0

Saya pikir itu tidak mungkin dengan kompiler dan preprosesor saja. gcc memungkinkan ini:

#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" );

Tapi sayangnya bukan ini:

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

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

Kesalahannya adalah:

/etc/hostname: In function init_module’:
/etc/hostname:1:0: error: unterminated argument list invoking macro "STRGF"
bukan pengguna
sumber
Saya telah melihat, saat Anda menawar saya melihat. Saya tidak melihat informasi baru dalam jawaban Anda (informasi yang tidak ada dalam jawaban lain), di luar referensi /etc/hostnamesebagai cara untuk menyematkan nama mesin pembuat dalam string, yang (meskipun berfungsi) tidak akan portabel karena Mac OS X tidak memiliki file /etc/hostname. Perhatikan bahwa menggunakan nama makro yang dimulai dengan garis bawah diikuti dengan huruf kapital menggunakan nama yang disediakan untuk implementasi, yaitu A Bad Thing ™.
Jonathan Leffler
0

Mengapa tidak menautkan teks ke dalam program dan menggunakannya sebagai variabel global! Berikut ini sebuah contoh. Saya sedang mempertimbangkan untuk menggunakan ini untuk memasukkan file Open GL shader ke dalam executable karena GL shaders perlu dikompilasi untuk GPU saat runtime.

TechDragon
sumber
0

Saya memiliki masalah yang serupa, dan untuk file-file kecil solusi Johannes Schaub yang disebutkan di atas bekerja seperti pesona bagi saya.

Namun, untuk file yang sedikit lebih besar, itu mengalami masalah dengan batas array karakter dari kompiler. Oleh karena itu, saya menulis aplikasi encoder kecil yang mengubah konten file menjadi array karakter 2D dari potongan berukuran sama (dan mungkin padding nol). Ini menghasilkan file teks keluaran dengan data array 2D seperti ini:

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'}};

di mana 4 sebenarnya adalah variabel MAX_CHARS_PER_ARRAY di pembuat enkode. File dengan kode C yang dihasilkan, disebut, misalnya "main_js_file_data.h" kemudian dapat dengan mudah dimasukkan ke dalam aplikasi C ++, misalnya seperti ini:

#include "main_js_file_data.h"

Berikut adalah kode sumber pembuat enkode:

#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;
}
volzotan
sumber
0

Masalah ini menjengkelkan saya dan xxd tidak berfungsi untuk kasus penggunaan saya karena itu membuat variabel bernama __home_myname_build_prog_cmakelists_src_autogen ketika saya mencoba skrip, jadi saya membuat utilitas untuk menyelesaikan masalah yang tepat ini:

https://github.com/Exaeta/brcc

Ini menghasilkan file sumber dan header dan memungkinkan Anda untuk secara eksplisit mengatur nama masing-masing variabel sehingga Anda dapat menggunakannya melalui std :: begin (arrayname) dan std :: end (arrayname).

Saya memasukkannya ke dalam proyek cmake saya seperti:

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/binary_resources.hpp ${CMAKE_CURRENT_BINARY_DIR}/binary_resources.cpp
  COMMAND brcc ${CMAKE_CURRENT_BINARY_DIR}/binary_resources RGAME_BINARY_RESOURCES_HH txt_vertex_shader ${CMAKE_CURRENT_BINARY_DIR}/src/vertex_shader1.glsl
  DEPENDS src/vertex_shader1.glsl)

Dengan tweak kecil saya kira itu bisa dibuat untuk bekerja untuk C juga.

Exaeta
sumber
-1

dalam xh

"this is a "
"buncha text"

di main.c

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

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

    return 0
}

seharusnya melakukan pekerjaan itu.

EvilTeach
sumber
Untuk beberapa baris, Anda perlu menambahkan \ n jadi: "line 1 \ n" "line 2 \ n"
Superfly Jon
ini agak menyesatkan, jelas ini membutuhkan persiapan file teks untuk menambahkan tanda kutip dan \ n karakter, tidak berfungsi dalam kasus umum
Mark Ch