"#include"C程序中的文本文件为char []

123 c include c-preprocessor

有没有办法在编译时将整个文本文件作为字符串包含在C程序中?

就像是:

获取一个在stdout上打印的小程序"这是一个小文本文件"

目前我使用了一个hackish python脚本,但它只是丑陋而且仅限于一个变量名,你能告诉我另一种方法吗?

Has*_*kun 125

我建议使用(unix util)xxd.你可以像这样使用它

$ echo hello world > a
$ xxd -i a
Run Code Online (Sandbox Code Playgroud)

输出:

unsigned char a[] = {
  0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a
};
unsigned int a_len = 12;
Run Code Online (Sandbox Code Playgroud)

  • 只是注意:xxd创建的char []不是以NULL结尾的!所以我做$ xxd -i <file.txt> file.xxd $ echo',0'>> file.xxd并在main.c char file_content [] = {#include"file.xxd"}; (17认同)
  • 另一种向xxd添加0x00终止的方法产生了C代码:`xxd -i file.txt | sed's/\([0-9a-f] \)$ /\0,0x00 /'> file.h` (5认同)
  • 嵌入GLSL着色器时,这非常有用。 (3认同)
  • 我从来不知道xxd.这很棒! (2认同)

kay*_*ahr 92

问题是关于C但是如果有人试图用C++ 11做,那么只需对包含的文本文件进行少量更改就可以完成,这要归功于新的原始字符串文字:

在C++中这样做:

const char *s =
#include "test.txt"
;
Run Code Online (Sandbox Code Playgroud)

在文本文件中执行以下操作:

R"(Line 1
Line 2
Line 3
Line 4
Line 5
Line 6)"
Run Code Online (Sandbox Code Playgroud)

因此,文件顶部必须只有一个前缀,并且文件末尾只有一个后缀.在它之间你可以做你想要的,只要你不需要字符序列就不需要特殊的转义)".但是,如果您指定自己的自定义分隔符,即使这样也可以:

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

  • 谢谢,我选择了这里提出的方法将[tag:SQL]的长片段嵌入到我的C++ 11代码中.这允许我将SQL清晰地分成它自己的文件,并使用适当的语法检查,突出显示等来编辑它们. (5认同)
  • 这真的很接近我想要的。特别是用户定义的分隔符。很有用。我确实想更进一步:有没有办法从要包含的文件中完全删除前缀 R"( 和后缀 )"?我尝试定义两个名为 bra.in 和 ket.in 的文件,其中包含前缀和后缀,一一包含 bra.in、file.txt 和 ket.in。但是编译器会在包含下一个文件之前评估 bra.in 的内容(这只是 R"() 。所以它会抱怨。如果有人知道如何从 file.txt 获取前缀和后缀,请告诉我。谢谢。 (2认同)

Joh*_*itb 14

你有两种可能性:

  1. 利用编译器/链接器扩展将文件转换为二进制文件,并使用适当的符号指向二进制数据的开头和结尾.请参阅以下答案:使用GNU ld链接描述文件包含二进制文件.
  2. 将文件转换为可以初始化数组的字符常量序列.请注意,您不能只执行""并跨越多行.你需要一个行继续符(\),转义"字符和其他来使它工作.更容易编写一个小程序将字节转换为类似的序列'\xFF', '\xAB', ...., '\0'(或使用xxd另一个答案描述的unix工具,如果你有它!):

码:

#include <stdio.h>

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

(未经测试).然后做:

char my_file[] = {
#include "data.h"
};
Run Code Online (Sandbox Code Playgroud)

data.h由哪里生成

cat file.bin | ./bin2c > data.h
Run Code Online (Sandbox Code Playgroud)


mat*_*ort 10

如果您愿意采取一些肮脏的技巧,您可以利用原始字符串文字和#include某些类型的文件发挥创意。

例如,假设我想在我的项目中包含一些 SQLite 的 SQL 脚本,并且想要语法突出显示,但不需要任何特殊的构建基础设施。我可以拥有这个文件test.sql,它是 SQLite 的有效 SQL,其中--开始注释:

--x, R"(--
SELECT * from TestTable
WHERE field = 5
--)"
Run Code Online (Sandbox Code Playgroud)

然后在我的 C++ 代码中我可以得到:

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

    cout << mysql << endl;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

--
SELECT * from TestTable
WHERE field = 5
--
Run Code Online (Sandbox Code Playgroud)

或者包含来自test.py有效 Python 脚本的文件中的一些 Python 代码(因为#在 Python 中启动注释并且pass是无操作):

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

myfunc()
#undef pass
#define pass )"
pass
Run Code Online (Sandbox Code Playgroud)

然后在C++代码中:

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

    cout << mypython << endl;
}
Run Code Online (Sandbox Code Playgroud)

这将输出:

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

myfunc()
#undef pass
#define pass
Run Code Online (Sandbox Code Playgroud)

对于您可能想要包含为字符串的各种其他类型的代码,应该可以使用类似的技巧。我不确定这是否是一个好主意。这是一种巧妙的技巧,但可能不是您在实际生产代码中想要的东西。不过对于周末黑客项目来说可能还不错。


Ily*_*lya 8

好吧,受到Daemin的帖子的启发,我测试了以下简单的例子:

a.data:

"this is test\n file\n"
Run Code Online (Sandbox Code Playgroud)

test.c的:

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

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;
}
Run Code Online (Sandbox Code Playgroud)

所以它工作但需要用引号括起来的数据.


Mar*_* R. 7

我喜欢卡亚尔的回答。但是,如果您不想触摸输入文件,并且正在使用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)
Run Code Online (Sandbox Code Playgroud)

然后包含在c ++中,如下所示:

constexpr char *test =
#include "generated/cool.frag"
;
Run Code Online (Sandbox Code Playgroud)


Joh*_*nck 6

您可以使用objcopy以下方法执行此操作:

objcopy --input binary --output elf64-x86-64 myfile.txt myfile.o
Run Code Online (Sandbox Code Playgroud)

现在您有了一个目标文件,您可以链接到您的可执行文件,其中包含myfile.txt.

  • 你能告诉我们符号名称是什么吗? (4认同)