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?
c
include
c-preprocessor
Brian Tompsett - 汤 莱恩
sumber
sumber
Jawaban:
Saya sarankan menggunakan (unix util) xxd untuk ini. Anda bisa menggunakannya seperti itu
output:
sumber
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).xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
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:
Dalam file teks lakukan ini:
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:sumber
1+R"...
sebagai pembatas awal alih-alihR"...
, dan kemudian menambahkan baris baru sebelumnyaLine 1
. Ini akan mengubah ekspresi dari sebuah array ke sebuah pointer, tapi itu bukan masalah di sini, karena Anda menginisialisasi pointer, bukan sebuah array.Anda memiliki dua kemungkinan:
\
),"
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 yangxxd
dijelaskan oleh jawaban lain, jika Anda memilikinya tersedia!):Kode:
(tidak diuji). Kemudian lakukan:
Di mana data.h dihasilkan oleh
sumber
char my_file[] = { #include my_large_file.h };
Terima kasih!bin2c
adalah tidak yang bin2c sama dari ini debianhxtools
, berhati-hatilahbin2c -H myoutput.h myinput1.txt myinputN.txt
ok, terinspirasi oleh posting Daemin saya menguji contoh sederhana berikut:
a.data:
test.c:
gcc -E test.c output:
Jadi ini berfungsi tetapi membutuhkan data yang dikelilingi dengan tanda kutip.
sumber
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:
Kemudian sertakan dalam c ++ seperti ini:
sumber
Anda dapat melakukan ini menggunakan
objcopy
:Sekarang Anda memiliki file objek yang dapat Anda tautkan ke executable Anda yang berisi simbol untuk awal, akhir, dan ukuran konten
myfile.txt
.sumber
Anda memerlukan
xtr
utilitas saya tetapi Anda dapat melakukannya denganbash script
. Ini adalah skrip yang saya panggilbin2inc
. Parameter pertama adalah nama yang dihasilkanchar[] variable
. Parameter kedua adalah namafile
. Outputnya adalah Cinclude file
dengan konten file yang dikodekan (dalam huruf kecilhex
) sebagai nama variabel yang diberikan. Thechar array
adalahzero terminated
, dan panjang data disimpan di$variableName_length
ANDA BISA DAPATKAN XTR DI SINI xtr (karakter eXTRapolator) adalah GPLV3
sumber
Jika Anda mau menggunakan beberapa trik kotor Anda bisa berkreasi dengan literal string mentah dan
#include
untuk 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.sql
yang merupakan SQL untuk SQLite yang valid tempat--
memulai komentar:Dan kemudian dalam kode C ++ saya, saya dapat memiliki:
Outputnya adalah:
Atau untuk memasukkan beberapa kode Python dari file
test.py
yang merupakan skrip Python yang valid (karena#
memulai komentar dalam Python danpass
merupakan no-op):Dan kemudian dalam kode C ++:
Yang akan menghasilkan:
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.
sumber
Saya mengimplementasikan ulang xxd di python3, memperbaiki semua gangguan xxd:
unsigned
pada array.Ini skripnya, difilter dengan sendirinya, sehingga Anda dapat melihat fungsinya:
pyxxd.c
Penggunaan (ini mengekstrak skrip):
sumber
Apa yang mungkin berhasil adalah jika Anda melakukan sesuatu seperti:
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
main.cpp
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.
sumber
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.
sumber
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.
sumber
Saya pikir itu tidak mungkin dengan kompiler dan preprosesor saja. gcc memungkinkan ini:
Tapi sayangnya bukan ini:
Kesalahannya adalah:
sumber
/etc/hostname
sebagai 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 ™.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.
sumber
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:
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:
Berikut adalah kode sumber pembuat enkode:
sumber
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:
Dengan tweak kecil saya kira itu bisa dibuat untuk bekerja untuk C juga.
sumber
dalam xh
di main.c
seharusnya melakukan pekerjaan itu.
sumber