C 프로그램에서 텍스트 파일을 문자로 "#include"[]


130

컴파일 타임에 전체 텍스트 파일을 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);
    }

stdout에 인쇄되는 작은 프로그램 얻기 "이것은 작은 텍스트 파일입니다"

지금은 hackish python 스크립트를 사용했지만 엉덩이가 추악하고 하나의 변수 이름으로 제한되어 있습니다. 다른 방법을 알려 주시겠습니까?


char []로 파일을 읽는 방법을 여기에서 살펴보십시오. /programming/410943/reading-a-text-file-into-an-array-in-c 다음은 C 전 처리기의 매크로를 사용하기위한 몇 가지 팁입니다. http://gcc.gnu.org/onlinedocs/cpp/Macros.html
Daniel A. White

3
왜 이러고 싶니? 런타임에 파일을 읽지 않는 이유는 무엇입니까? (답변 : 파일이 런타임에 어디에 있는지 알기 어렵거나 설치할 파일이 하나만 있어야하기 때문일 수 있습니다.)
Jonathan Leffler

또는 텍스트 파일은 소스 코드와 같은 컴파일 타임에만 사용할 수 있습니다.
TMS

1
때로는 개발시 데이터를 별도의 파일로 액세스하려고하지만 내용을 바이너리로 컴파일해야합니다. 로컬 스토리지에 액세스 할 수없는 Arduino에서 웹 서버를 실행하는 예가 있습니다. HTML 파일을 편집하기 위해 html 파일을 별도로 유지하려고하지만 컴파일 타임에 소스에 문자열로 존재해야합니다.
Geordie

답변:


134

이것을 위해 (unix util) xxd 를 사용하는 것이 좋습니다 . 당신은 그렇게 사용할 수 있습니다

$ echo hello world > a
$ xxd -i a

출력 :

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

18
xxd에 의해 작성된 char []는 NULL로 끝나지 않습니다! 그래서 나는 $ xxd -i <file.txt> file.xxd $ echo ', 0'>> file.xxd 그리고 main.c char file_content [] = {#include "file.xxd"};

2
나는 xxd에 대해 몰랐다. 그것은 굉장!

1
@ eSKay : xxd대답에서 알 수 있듯이의 출력에서 직접 가져옵니다 . 배열의 이름은 입력 파일 이름입니다. 입력 파일을 사용하는 대신 데이터를 파이핑하는 경우 대신 배열 선언 또는 len 변수없이 16 진 값 목록이 표시됩니다.
Hasturkun

4
GLSL 쉐이더를 임베드 할 때 매우 유용합니다.
linello

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

104

문제는 C에 관한 것이지만 누군가가 C ++ 11로 처리하려고하면 새로운 원시 문자열 리터럴 덕분에 포함 된 텍스트 파일을 거의 변경하지 않고도 수행 할 수 있습니다 .

C ++에서 다음을 수행하십시오.

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

텍스트 파일에서 다음을 수행하십시오.

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

따라서 파일 상단에는 접두사 만 있고 끝에는 접미사가 있어야합니다. 그 사이에 문자 시퀀스가 ​​필요하지 않으면 원하는 것을 할 수 있으며 특별한 이스케이프가 필요하지 않습니다 )". 그러나 사용자 정의 구분 기호를 지정하면이 기능을 사용할 수도 있습니다.

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

5
감사합니다. 여기에 제안 된 방법을 선택하여 긴 sql 조각 을 내 C ++ 11 코드 에 포함 시켰습니다. 이를 통해 SQL을 깨끗하게 분리하여 자체 파일로 분리하고 적절한 구문 검사, 강조 표시 등으로 편집 할 수 있습니다.
YitzikC

1
이것은 정말로 내가 원하는 것에 가깝습니다. 특히 사용자 정의 분리 문자. 굉장히 유용하다. 한 걸음 더 나아가고 싶습니다. 포함하려는 파일에서 접두사 R "(and suffix)"를 완전히 제거하는 방법이 있습니까? bra.in, ket.in이라는 두 파일을 접두사와 접미사로 묶어 정의했습니다 .bra.in, file.txt 및 ket.in을 하나씩 포함합니다. 그러나 컴파일러는 다음 파일을 포함하기 전에 bra.in (R "())의 내용을 평가하므로 불평 할 것입니다. file.txt에서 접두사 및 접미사를 얻는 방법을 알고 있다면 알려주십시오.
TMS

C ++에서 R "(<newline> #include ...)"을 허용하지 않을 것이라고 생각합니다. 어떤 인코딩도 필요로하지 않기 위해 컴파일 타임에 파일을 가져 오게하는 것이 좋을 것입니다. 예 : 곧은 json 또는 xml 또는 csv 또는 그렇지 않은 것.
Brian Chrisman

을 (를) 1+R"...대신 시작 구분 기호로 사용 R"...하고 앞에 개행을 추가 하면 원시 리터럴의 텍스트를 좀 더 읽기 쉽게 만들 수 있습니다 Line 1. 이렇게하면 식을 배열에서 포인터로 변환 할 수 있지만 배열이 아닌 포인터를 초기화하기 때문에 실제로 문제가되지 않습니다.
Ruslan

14

두 가지 가능성이 있습니다.

  1. 컴파일러 / 링커 확장을 사용하여 파일을 이진 파일로 변환하고 이진 데이터의 시작과 끝을 가리키는 적절한 기호를 사용하십시오. 이 답변을 참조하십시오 : GNU ld linker script 이진 파일 포함 .
  2. 파일을 배열을 초기화 할 수있는 일련의 문자 상수로 변환하십시오. ""만 수행 할 수 없으며 여러 줄에 걸쳐있을 수 있습니다. 행 연속 문자 ( \), 이스케이프 "문자 및 기타 문자가 필요합니다 . 바이트를 시퀀스로 변환하는 작은 프로그램을 작성하는 것이 더 쉽습니다 '\xFF', '\xAB', ...., '\0'(또는 xxd가능한 경우 다른 답변에서 설명 하는 유닉스 도구를 사용하십시오 !).

암호:

#include <stdio.h>

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

(검증되지 않은). 그런 다음 수행하십시오.

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

data.h가 생성되는 위치

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

1
마지막 줄은 "cat file.bin | ./bin2c> data.h"또는 "./bin2c <file.bin> data.h"
Hasturkun

내가 사용 codeproject.com/Tips/845393/...을 바이너리에서 (Windows의 경우) 육각 파일을 생성 한 후 당신의 제안 사용 char my_file[] = { #include my_large_file.h };감사합니다!
누군가 어딘가에

bin2cdebian와 같은 bin2c 가 아닙니다 . hxtools주의
ThorSummoner

아니면 그것이 지금보다 훨씬 더 이상하다 :bin2c -H myoutput.h myinput1.txt myinputN.txt
ThorSummoner

9

Ok, Daemin의 게시물 에서 영감을 얻은 다음 간단한 예제를 테스트했습니다.

데이터 :

"this is test\n file\n"

test.c :

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

gcc -E test.c 출력 :

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

따라서 작동하지만 따옴표로 묶인 데이터가 필요합니다.


그것이 내가 대답 한 마지막 부분에서 언급 한 것입니다.
Daemin

인용, 또는 그것이 무엇이든간에, 나의 영어를 용서하십시오
Ilya

이를 위해서는 데이터를 C 이스케이프해야합니다. 나는 그것이 게시물이 찾고있는 것이라고 생각하지 않습니다. 이것이 파일의 내용을 C 이스케이프 처리하는 일종의 포함 매크로가 있다면 괜찮습니다.
브라이언 Chrisman

8

나는 kayahr의 대답을 좋아한다. 그러나 입력 파일을 터치하지 않고 CMake 를 사용 하는 경우 파일에 델리 미터 문자 시퀀스를 추가 할 수 있습니다. 예를 들어 다음 CMake 코드는 입력 파일을 복사하고 그에 따라 내용을 래핑합니다.

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)

그런 다음 C ++에 다음과 같이 포함하십시오.

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

5

다음을 사용하여이 작업을 수행 할 수 있습니다 objcopy.

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

이제 파일의 시작, 끝 및 크기에 대한 기호가 포함 된 실행 파일에 링크 할 수있는 객체 파일이 있습니다 myfile.txt.


1
심볼 이름이 무엇인지 말씀해 주시겠습니까?
Mark Ch

@MarkCh : 문서에 따라 입력 파일 이름에서 심볼 이름이 생성됩니다.
존 즈 빙크

나는 이것이 x86-64가 아닌 머신에서 작동하지 않을 것이라고 추측하고 있습니까?
ThorSummoner


2

xtr유틸리티 가 필요 하지만으로 할 수 있습니다 bash script. 이것은 내가 부르는 스크립트 bin2inc입니다. 첫 번째 매개 변수는 결과의 이름입니다 char[] variable. 두 번째 매개 변수는의 이름입니다 file. 출력은 주어진 변수 이름으로 include file파일 컨텐츠가 인코딩 된 (소문자 hex)로 C 입니다 . 는 char array이며 zero terminated, 데이터의 길이에 저장된$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을 얻을 수 있습니다 xtr (문자 eXTRapolator)은 GPLV3입니다.


2

더러운 속임수를 사용하려는 경우 원시 문자열 리터럴과 #include특정 유형의 파일을 사용 하여 창의력을 발휘할 수 있습니다 .

예를 들어 프로젝트에 SQLite 용 SQL 스크립트를 포함하고 구문 강조를 원하지만 특별한 빌드 인프라를 원하지 않는다고 가정하십시오. 주석을 시작하는 test.sqlSQLite에 유효한 SQL 인 이 파일 을 가질 수 있습니다 --.

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

그리고 내 C ++ 코드에서 다음을 가질 수 있습니다.

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

    cout << mysql << endl;
}

출력은 다음과 같습니다.

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

또는 test.py유효한 Python 스크립트 인 파일에서 일부 Python 코드를 포함 시키려면 (Python #에서 주석을 시작하고 작동하지 않기 때문에 pass) :

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

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

그리고 C ++ 코드에서 :

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

    cout << mypython << endl;
}

어느 것이 출력 될까요?

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

myfunc()
#undef pass
#define pass

문자열로 포함시키려는 다양한 다른 유형의 코드에 대해 유사한 트릭을 재생할 수 있어야합니다. 그것이 좋은 생각인지 아닌지는 확실하지 않습니다. 깔끔한 해킹이지만 실제 프로덕션 코드에서는 원하지 않을 것입니다. 주말 핵 프로젝트에 대해서는 괜찮을 수도 있습니다.


이 방법을 사용하여 OpenGL 쉐이더를 텍스트 파일에도 넣었습니다!
yano

1

python3에서 xxd를 다시 구현하여 xxd의 모든 성가심을 수정했습니다.

  • Const 정확성
  • 문자열 길이 데이터 유형 : int → size_t
  • 널 종료 (원할 경우)
  • C 문자열 호환 가능 : unsigned어레이에서 드롭 합니다.
  • 더 작고 읽을 수있는 출력 : 작성했을 때 : 인쇄 가능한 ASCII는 그대로 출력됩니다. 다른 바이트는 16 진수로 인코딩됩니다.

다음은 스크립트 자체로 필터링되어 있으므로 스크립트의 기능을 확인할 수 있습니다.

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;

사용법 (스크립트 추출) :

#include <stdio.h>

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

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

1

무엇 수도 작동하면 같은 일을 할 경우입니다 :

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

물론 실제로 파일에있는 내용에주의를 기울여야하며 큰 따옴표가 없으며 모든 적절한 문자가 이스케이프되는지 확인해야합니다.

따라서 런타임에 파일에서 텍스트를로드하거나 텍스트를 코드에 직접 포함시키는 것이 더 쉬울 수 있습니다 .

여전히 다른 파일의 텍스트를 원한다면 거기에 넣을 수 있지만 문자열로 표시해야합니다. 위와 같이 코드를 사용하지만 큰 따옴표는 사용하지 않습니다. 예를 들면 다음과 같습니다.

file.txt

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

main.cpp

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

기본적으로 포함하는 텍스트 파일에 C 또는 C ++ 스타일 문자열이 있습니다. 파일 시작 부분에 많은 양의 텍스트가 없기 때문에 코드가 깔끔해집니다.


3
좋은 생각이지만 작동하지 않습니다. 리터럴에 줄 바꿈이 포함되어 있거나 #include 부분이 문자열로 읽히고 실행되지 않기 때문에 오류가 발생합니다. .
은 Motti

1
@Motti : 동의했다-서면으로, 구문 상 유효하지 않은 C. 아이디어는 흥미 롭다-C 전처리 기는 논리적으로 별개의 단계이다-그러나 연습은 포함 된 파일의 각 줄이 백 슬래시 등으로 끝남
Jonathan Leffler 2016 년

2
흠. 대부분의 컴파일러가 인접한 문자열을 함께 연결하므로 백 슬래시가 필요하지 않습니다.
EvilTeach

이 답변이있는 것은 ... 간단한 경우 OP가 질문을 한 적이 없다고 생각합니다! -1이 답변의 존재는 사람들이 효과가없는 것을 시도하는 데 시간을 낭비하도록 약간 격려하기 때문입니다. "작동 할 수있는 항목"을 "참조 용으로 작동하지 않음"으로 변경하면 다운 보트를 제거 할 수 있다고 생각합니다.
Mark Ch

@JonathanLeffler 프리 프로세서가 실행 된 후 file.txt의 형식에 따라 유효한 C 또는 C ++ 여야합니다.
Daemin

0

컴파일 타임에 수행 할 수 있다고하더라도 (일반적으로 할 수는 없다고 생각) 텍스트는 파일 내용이 아닌 사전 처리 된 헤더 일 것입니다. 런타임에 파일에서 텍스트를로드하거나 불쾌한 cut-n-paste 작업을 수행해야합니다.


0

xxd -i 옵션을 사용한 Hasturkun의 대답은 훌륭합니다. 변환 프로세스 (텍스트-> 16 진수 포함 파일)를 빌드에 직접 통합하려면 hexdump.c 도구 / 라이브러리가 최근에 xxd의 -i 옵션과 유사한 기능을 추가했습니다 (전체 헤더를 제공하지는 않습니다-필요합니다 char 배열 정의를 제공하지만 char 배열의 이름을 선택할 수 있다는 이점이 있습니다.

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

라이센스는 xxd보다 훨씬 "표준"이며 매우 자유 롭습니다. 프로그램에 init 파일을 포함시키기 위해이를 사용하는 예는 CMakeLists.txt 및 scheme.c 파일에서 확인할 수 있습니다.

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

소스 트리에 생성 된 파일을 포함시키는 방법과 번들링 유틸리티 모두에 대한 장단점이 있습니다. 처리 방법은 프로젝트의 특정 목표와 요구에 따라 다릅니다. hexdump.c는이 애플리케이션에 대한 번들링 옵션을 엽니 다.


0

컴파일러와 전 처리기만으로는 불가능하다고 생각합니다. 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"

당신이 나에게 입찰하는 것처럼 나는 보았다. 나는 /etc/hostname문자열에 빌드 머신의 이름을 포함시키는 방법에 대한 언급을 넘어서서 당신의 답변 (다른 답변에없는 정보)에 새로운 정보를 보지 못했습니다. ( 작동하더라도) Mac OS X에는 파일이 없으므로 휴대용 /etc/hostname. 밑줄로 시작하고 대문자로 시작하는 매크로 이름을 사용하면 구현에 예약 된 이름 인 A Bad Thing ™을 사용합니다.
Jonathan Leffler

0

텍스트를 프로그램에 링크하여 전역 변수로 사용하십시오! 다음은 예입니다. GL 셰이더를 런타임에 GPU 용으로 컴파일해야하므로이 파일을 사용하여 실행 파일 내에 Open GL 셰이더 파일을 포함하는 것을 고려하고 있습니다.


0

비슷한 문제가 있었으며 작은 파일의 경우 앞서 언급 한 Johannes Schaub의 솔루션이 저에게 매력처럼 작용했습니다.

그러나 조금 더 큰 파일의 경우 컴파일러의 문자 배열 제한에 문제가 발생했습니다. 따라서 필자는 파일 내용을 동일한 크기의 청크 (및 패딩 0)의 2D 문자 배열로 변환하는 작은 인코더 응용 프로그램을 작성했습니다. 다음과 같이 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입니다. 그런 다음 "main_js_file_data.h"와 같은 결과 C 코드가있는 파일을 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

이 문제는 나를 자극하고 xxd는 스크립트를 작성할 때 __home_myname_build_prog_cmakelists_src_autogen과 같은 변수를 만들었으므로 유스 케이스에서 작동하지 않으므로이 정확한 문제를 해결하는 유틸리티를 만들었습니다.

https://github.com/Exaeta/brcc

소스 및 헤더 파일을 생성하고 각 변수의 이름을 명시 적으로 설정하여 std :: begin (arrayname) 및 std :: end (arrayname)을 통해 사용할 수 있습니다.

나는 그것을 cmake 프로젝트에 다음과 같이 통합했다.

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)

작은 조정으로 C에서도 작동 할 수 있다고 생각합니다.


-1

xh에서

"this is a "
"buncha text"

main.c에서

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

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

    return 0
}

일을해야합니다.


여러 줄의 경우 \ n을 추가해야합니다. "line 1 \ n" "line 2 \ n"
Superfly Jon

약간 오해의 여지가 있지만, 이것은 인용 부호와 \ n 문자를 추가하기 위해 텍스트 파일을 약간 준비해야하며 일반적인 경우에는 작동하지 않습니다.
Mark Ch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.