Bir C programındaki bir metin dosyasını karakter olarak "#include" []


130

Derleme sırasında bir C programına tüm bir metin dosyasını bir dize olarak eklemenin bir yolu var mı?

gibi bir şey:

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

stdout "Bu küçük bir metin dosyasıdır" yazdıran küçük bir program elde etmek

Şu anda hackish bir python betiği kullandım, ancak çok çirkin ve sadece bir değişken adıyla sınırlı, bunu yapmanın başka bir yolunu söyleyebilir misiniz?


Bir dosyayı bir karaktere [] okumak için buraya bakın. /programming/410943/reading-a-text-file-into-an-array-in-c Burada C ön işlemcisinin makrolarını kullanmak için bazı ipuçları verilmiştir. http://gcc.gnu.org/onlinedocs/cpp/Macros.html
Daniel A. White

3
Bunu neden yapmak istiyorsun? Dosyayı neden çalışma zamanında okumuyorsunuz? (Cevap: belki de dosyanın çalışma zamanında nerede olduğunu bilmenin zor olmasından ya da kurulacak tek bir dosyanın olması gerektiğinden olabilir.)
Jonathan Leffler

veya belki metin dosyası, kaynak kodu gibi yalnızca derleme zamanında kullanılabilir.
TMS

1
Bazen, geliştirme sırasında verilere ayrı dosyalar olarak erişmek, ancak içeriğin ikili dosyanızda derlenmesini istersiniz. Örnek, yerel depolamaya erişimi olmayan bir Arduino'da bir web sunucusu çalıştırıyor. Html dosyalarınızı düzenlemek için ayrı tutmak istiyorsunuz, ancak derleme sırasında kaynağınızda dizeler olarak bulunmaları gerekir.
Geordie

Yanıtlar:


134

Bunun için (unix util) xxd kullanmanızı öneririm . onu böyle kullanabilirsin

$ echo hello world > a
$ xxd -i a

çıktılar:

unsigned char a[] = {
  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;

18
Sadece bir not: xxd tarafından oluşturulan char [] NULL ile sonlandırılmamış! bu yüzden $ xxd -i <file.txt> file.xxd $ echo ', 0' >> file.xxd ve main.c char file_content [] = {#include "file.xxd"};

2
Xxd'yi hiç bilmiyordum. Bu harika!

1
@eSKay: Bu xxd, cevabın dediği gibi, doğrudan çıkışından geliyor . dizinin adı girdi dosya adıdır. Bir girdi dosyası kullanmak yerine veri aktarıyorsanız, bunun yerine onaltılık değerlerin bir listesini alırsınız (dizi bildirimi veya len değişkeni olmadan).
Hasturkun

4
Bu, GLSL gölgelendiricileri yerleştirirken son derece kullanışlıdır.
linello

5
xxd -i file.txt | sed 's/\([0-9a-f]\)$/\0, 0x00/' > file.h
Xxd tarafından

104

Soru C hakkındaydı, ancak birisinin bunu C ++ 11 ile yapmaya çalışması durumunda, yeni ham dize değişmezleri sayesinde dahil edilen metin dosyasında yalnızca küçük değişikliklerle yapılabilir :

C ++ 'da şunu yapın:

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

Metin dosyasında şunu yapın:

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

Bu nedenle, dosyanın sadece üstünde bir önek ve sonunda bir sonek olmalıdır. Aralarında istediğinizi yapabilirsiniz, karakter dizisine ihtiyacınız olmadığı sürece özel bir kaçışa gerek yoktur )". Ancak kendi özel sınırlayıcınızı belirtirseniz bu bile işe yarayabilir:

R"=====(Line 1
Line 2
Line 3
Now you can use "( and )" in the text file, too.
Line 5
Line 6)====="

5
Teşekkürler, uzun sql parçalarını C ++ 11 koduma yerleştirmek için burada önerilen yöntemi seçtim . Bu, SQL'i net bir şekilde kendi dosyalarına ayırmama ve bunları uygun sözdizimi kontrolü, vurgulama vb.
İle

1
Bu gerçekten istediğim şeye yakın. Özellikle kullanıcı tanımlı sınırlayıcı. Çok kullanışlı. Bir adım daha ileri gitmek istiyorum: eklemek istediğiniz dosyadan R "(ve son ek)" önekini tamamen kaldırmanın bir yolu var mı? Bra.in ve ket.in adlı iki dosyayı önek ve sonek ile tanımlamayı denedim, bunlar arasında bra.in, file.txt ve ket.in'i birer birer tanımladım. Ancak derleyici bra.in içeriğini (sadece R "() bir sonraki dosyayı eklemeden önce değerlendirir. Bu yüzden şikayet eder. Lütfen file.txt'den önek ve son ekin nasıl alınacağını bilen varsa bana bildirin. Teşekkürler.
TMS

C ++ 'nın R "(<newline> #include ...)"' e izin vermeyeceğini tahmin ediyorum? Herhangi bir kodlama gerektirmemesi için dosyanın derleme zamanı alması güzel olurdu .... yani düz json veya xml veya csv veya başka bir şey ..
Brian Chrisman

Bunun 1+R"...yerine başlangıç ​​sınırlayıcı olarak kullanırsanız ham değişmezin metnini biraz daha okunaklı hale getirebilir R"...ve ardından önüne bir satırsonu ekleyebilirsiniz Line 1. Bu, ifadeyi bir diziden bir işaretçiye dönüştürecektir, ancak bu burada bir sorun değil, çünkü bir diziyi değil, bir göstericiyi başlatıyorsunuz.
Ruslan

14

İki seçeneğiniz var:

  1. Bir dosyayı ikili bir dosyaya dönüştürmek için derleyici / bağlayıcı uzantılarını kullanın; uygun semboller ikili verilerin başlangıcını ve sonunu gösterir. Bu yanıta bakın: GNU ld linker komut dosyasıyla ikili dosyayı dahil edin .
  2. Dosyanızı, bir diziyi başlatabilen bir dizi karakter sabitine dönüştürün. Yalnızca "" yapıp birden çok satıra yayılamayacağınızı unutmayın. Bunun çalışması için bir satır devam karakterine ( \), kaçış "karakterlerine ve diğerlerine ihtiyacınız olacaktır. Baytları bir diziye dönüştürmek için küçük bir program yazmak daha kolaydır '\xFF', '\xAB', ...., '\0'(veya xxdvarsa başka bir yanıtla açıklanan unix aracını kullanın !):

Kod:

#include <stdio.h>

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

(test edilmedi). O zaman yap:

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

Data.h'nin oluşturduğu yer

cat file.bin | ./bin2c > data.h

1
son satır muhtemelen "cat file.bin | ./bin2c> data.h" veya "./bin2c <file.bin> data.h" şeklinde olmalıdır
Hasturkun

Bir ikili dosyadan (Windows'ta) bir onaltılık dosya oluşturmak için codeproject.com/Tips/845393/… kullandım ve ardından char my_file[] = { #include my_large_file.h };Teşekkürler önerinizi kullandım !
birisi Somewhere

bin2colduğu değil debian Sitesinden aynı bin2c hxtools, dikkat
ThorSummoner

ya da öyleyse, çağrı şimdi çok daha garip:bin2c -H myoutput.h myinput1.txt myinputN.txt
ThorSummoner

9

Tamam, Daemin'in gönderisinden esinlenerek aşağıdaki basit örneği test ettim:

a.data:

"this is test\n file\n"

test.c:

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

gcc -E test.c çıktısı:

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

Yani işe yarıyor, ancak tırnak işaretleriyle çevrili veriler gerektiriyor.


Cevabımın son kısmında kastettiğim buydu.
Daemin

alıntı veya adı ne olursa olsun, affedin İngilizcem
Ilya

Bu, verilerin C'den kaçmış olmasını gerektirir. Yazının aradığı şeyin bu olduğunu sanmıyorum. Bu, dosyanın içeriğinden C-kaçan bir tür içerme makrosuna sahip olsaydı, bu iyi olurdu.
Brian Chrisman

8

Kayahr'ın cevabını beğendim. Ancak giriş dosyalarına dokunmak istemiyorsanız ve CMake kullanıyorsanız , dosyaya sınırlayıcı karakter dizilerini ekleyebilirsiniz. Örneğin aşağıdaki CMake kodu, giriş dosyalarını kopyalar ve içeriklerini buna göre sarar:

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)

Sonra c ++ 'ya şu şekilde ekleyin:

constexpr char *test =
#include "generated/cool.frag"
;

5

Bunu kullanarak yapabilirsiniz objcopy:

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

Artık içeriğin başlangıcı, sonu ve boyutu için semboller içeren yürütülebilir dosyanıza bağlayabileceğiniz bir nesne dosyanız var myfile.txt.


1
sembol isimlerinin ne olacağını bize söyleyebilir misin?
Mark Ch

@MarkCh: Dokümanlara göre, sembol adları giriş dosya adından üretilir.
John Zwinck

Bunun x86-64 olmayan makinelerde çalışmayacağını tahmin ediyorum, değil mi?
ThorSummoner


2

Benim xtryardımcı programıma ihtiyacın var ama bunu bir bash script. Bu benim aradığım bir senaryo bin2inc. İlk parametre, sonucun adıdır char[] variable. İkinci parametre file,. Çıktı, değişken adı olarak include filedosya içeriği kodlanmış (küçük harfle hex) C'dir . char arrayOlduğu zero terminatedve verilerin uzunluğu saklanır$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")';'

XTR'yi BURADAN ALABİLİRSİNİZ xtr (karakter eXTRapolator) GPLV3'tür


2

Bazı kirli numaralara başvurmaya istekliysen, ham dize değişmezleri ile yaratıcı olabilirsin ve #include belirli dosya türleri için .

Örneğin, projeme SQLite için bazı SQL betikleri dahil etmek istediğimi ve sözdizimi vurgulamak istediğimi ancak herhangi bir özel yapı altyapısı istemediğimi varsayalım. Bir yorumun başladığı test.sqlSQLite için geçerli SQL olan bu dosyaya sahip olabilirim --:

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

Ve sonra C ++ kodumda sahip olabilirim:

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

    cout << mysql << endl;
}

Çıktı:

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

Veya test.pygeçerli bir Python betiği olan bir dosyadan bazı Python kodunu dahil etmek için (çünkü #Python'da bir yorum başlatır ve passişlemsizdir):

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

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

Ve sonra C ++ kodunda:

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

    cout << mypython << endl;
}

Hangi çıktı:

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

myfunc()
#undef pass
#define pass

Bir dizge olarak eklemek isteyebileceğiniz diğer çeşitli kod türleri için benzer hileler oynamak mümkün olmalıdır. Bunun iyi bir fikir olup olmadığından emin değilim. Bu güzel bir hack ama muhtemelen gerçek üretim kodunda isteyeceğiniz bir şey değil. Yine de bir hafta sonu hack projesi için uygun olabilir.


Bu yaklaşımı OpenGL Gölgelendiricileri metin dosyalarına koymak için kullandım!
yano

1

Xxd'yi python3'te yeniden uygulayarak xxd'nin tüm sıkıntılarını düzelttim:

  • Sabit doğruluk
  • dize uzunluğu veri türü: int → size_t
  • Boş fesih (bunu istemeniz durumunda)
  • C string uyumlu: unsignedDiziye bırakın .
  • Yazmış olacağınız gibi daha küçük, okunabilir çıktı: Yazdırılabilir ascii olduğu gibi çıktı; diğer baytlar hex kodludur.

İşte komut dosyası, kendisi tarafından filtrelenmiştir, böylece ne yaptığını görebilirsiniz:

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;

Kullanım (bu komut dosyasını çıkarır):

#include <stdio.h>

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

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

1

Ne olabilir çalışmak gibi bir şey yaparsanız geçerli:

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

Elbette dosyada gerçekte ne olduğuna dikkat etmeli, çift tırnak olmadığından, tüm uygun karakterlerin kaçtığından vb. Emin olmalısın.

Bu nedenle , metni çalışma zamanında bir dosyadan yüklerseniz veya metni doğrudan koda gömerseniz daha kolay olabilir .

Metni hala başka bir dosyada istiyorsanız, orada bulundurabilirsiniz, ancak orada bir dizge olarak temsil edilmesi gerekir. Kodu yukarıdaki gibi ancak çift tırnak işareti olmadan kullanırsınız. Örneğin:

file.txt

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

main.cpp

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

Yani temelde eklediğiniz bir metin dosyasında C veya C ++ stil dizesine sahip olmak. Kodun daha düzgün olmasını sağlar çünkü dosyanın başlangıcında bu kadar çok metin yoktur.


3
Güzel fikir ama işe yaramayacak, ya bir hatanız var çünkü literal yeni bir satır içeriyor ya da #include kısmı bir dizge olarak okunacak ve çalıştırılmayacak, eğer yaparsanız kahretsin ve yapmazsanız lanet olsun .. .
Motti

1
@Motti: kabul etti - yazıldığı gibi, sözdizimsel olarak geçersiz C. Fikir ilginçtir - C Ön İşlemcisi mantıksal olarak ayrı bir aşamadır - ancak pratik şu ki, dahil edilen dosyadaki her satırın sahip olacağı ters eğik çizgi vb. ile bitirmek için
Jonathan Leffler

2
Umm. Bana öyle geliyor ki, çoğu derleyici bitişik dizeleri bir araya getireceği için ters eğik
çizgiye ihtiyacınız yok

bu cevabı olan şey ... eğer bu kadar basit olsaydı, OP'nin soruyu soracağını sanmıyorum! -1 çünkü bu cevabın varlığı insanları işe yaramayan bir şeyi deneyerek zamanlarını boşa harcamaya biraz cesaretlendiriyor. "Neler işe yarayabilir" seçeneğini "Başvuru için bu işe yaramaz" olarak değiştirdiyseniz, olumsuz oyu kaldırabileceğimizi düşünüyorum
Mark Ch

@JonathanLeffler Önişlemci çalıştırıldıktan sonra, file.txt'nin nasıl biçimlendirildiğine bağlı olarak geçerli C veya C ++ olmalıdır.
Daemin

0

Derleme zamanında yapılabilse bile (genel olarak yapabileceğini düşünmüyorum), metin büyük olasılıkla dosya içeriğinden ziyade önceden işlenmiş başlık olacaktır. Metni çalışma zamanında dosyadan yüklemeniz veya kötü bir kes-yapıştır işi yapmanız gerekeceğini umuyorum.


0

Hasturkun'un xxd -i seçeneğini kullanarak cevabı mükemmel. Dönüştürme sürecini (metin -> hex include dosyası) doğrudan derlemenize dahil etmek istiyorsanız hexdump.c tool / library kısa süre önce xxd'nin -i seçeneğine benzer bir özellik ekledi (size tam üstbilgiyi vermez - ihtiyacınız olan char dizisi tanımını sağlamak için - ancak bu, char dizisinin adını seçmenize izin verme avantajına sahiptir):

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

Lisansı, xxd'den çok daha "standarttır" ve çok liberaldir - bir programa bir init dosyası yerleştirmek için kullanmanın bir örneği, CMakeLists.txt ve schema.c dosyalarında burada görülebilir:

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

Oluşturulan dosyaları hem kaynak ağaçlarına hem de bir araya getiren yardımcı programlara dahil etmenin artıları ve eksileri vardır - bunun nasıl işleneceği, projenizin belirli hedeflerine ve ihtiyaçlarına bağlı olacaktır. hexdump.c, bu uygulama için paketleme seçeneğini açar.


0

Sadece derleyici ve önişlemci ile bunun mümkün olmadığını düşünüyorum. gcc buna izin verir:

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

Ama maalesef bu değil:

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

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

Hata şudur:

/etc/hostname: In function init_module’:
/etc/hostname:1:0: error: unterminated argument list invoking macro "STRGF"

Bana bakma dediğiniz gibi baktım. Cevabınızda herhangi bir yeni bilgi görmüyorum (diğer cevaplarda olmayan bilgiler), /etc/hostnameyapı makinesinin adını dizeye yerleştirmenin bir yolu olarak yapılan bir referans dışında (işe yarasa bile) Mac OS X'in bir dosyası olmadığı için taşınabilir /etc/hostname. Alt çizgiyle başlayan ve ardından büyük harfle başlayan makro adlarının, uygulamaya ayrılmış bir adı, yani A Bad Thing ™ 'i kullandığına dikkat edin.
Jonathan Leffler

0

Metni programa bağlayıp global bir değişken olarak neden kullanmayalım! İşte bir örnek. GL gölgelendiricilerinin çalışma zamanında GPU için derlenmesi gerektiğinden, bunu bir yürütülebilir dosyaya Open GL gölgelendirici dosyalarını dahil etmek için kullanmayı düşünüyorum.


0

Benzer sorunlarım vardı ve küçük dosyalar için yukarıda bahsedilen Johannes Schaub çözümü benim için bir cazibe merkezi oldu.

Ancak, biraz daha büyük dosyalar için, derleyicinin karakter dizisi sınırıyla ilgili sorunlarla karşılaştı. Bu nedenle, dosya içeriğini eşit büyüklükte parçalardan oluşan (ve muhtemelen sıfırları dolduran) bir 2D karakter dizisine dönüştüren küçük bir kodlayıcı uygulaması yazdım. Aşağıdaki gibi 2D dizi verileriyle çıktı tekstil dosyaları üretir:

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

burada 4 aslında kodlayıcıda bir MAX_CHARS_PER_ARRAY değişkendir. Örneğin "main_js_file_data.h" olarak adlandırılan, sonuçta elde edilen C kodunu içeren dosya daha sonra kolayca C ++ uygulamasına satır içi olarak yerleştirilebilir, örneğin şu şekilde:

#include "main_js_file_data.h"

Kodlayıcının kaynak kodu:

#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

Bu problem beni rahatsız ediyordu ve xxd benim kullanım durumum için çalışmıyor çünkü değişkeni komut dosyası oluşturmaya çalıştığımda __home_myname_build_prog_cmakelists_src_autogen gibi bir şey yaptı, bu yüzden bu sorunu çözmek için bir yardımcı program yaptım:

https://github.com/Exaeta/brcc

Bir kaynak ve başlık dosyası oluşturur ve her değişkenin adını açıkça belirlemenizi sağlar, böylece bunları std :: begin (dizi adı) ve std :: end (dizi adı) yoluyla kullanabilirsiniz.

Bunu cmake projeme şu şekilde dahil ettim:

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)

Küçük ayarlamalarla, C için de işe yarayabileceğini düşünüyorum.


-1

xh içinde

"this is a "
"buncha text"

main.c'de

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

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

    return 0
}

işi yapmalı.


Birden fazla satır için şunu eklemeniz gerekir \ n, dolayısıyla: "satır 1 \ n" "satır 2 \ n"
Superfly Jon

biraz yanıltıcı, tabii ki bu, alıntılar ve \ n karakterler eklemek için metin dosyasının biraz hazırlanmasını gerektirir, genel durumda çalışmaz
Mark Ch
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.