123 c include c-preprocessor
有没有办法在编译时将整个文本文件作为字符串包含在C程序中?
就像是:
file.txt的:
This is
a little
text file
Run Code Online (Sandbox Code Playgroud)main.c中:
#include <stdio.h>
int main(void) {
#blackmagicinclude("file.txt", content)
/*
equiv: char[] content = "This is\na little\ntext file";
*/
printf("%s", content);
}
Run Code Online (Sandbox Code Playgroud)获取一个在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)
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)
Joh*_*itb 14
你有两种可能性:
\),转义"字符和其他来使它工作.更容易编写一个小程序将字节转换为类似的序列'\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)
对于您可能想要包含为字符串的各种其他类型的代码,应该可以使用类似的技巧。我不确定这是否是一个好主意。这是一种巧妙的技巧,但可能不是您在实际生产代码中想要的东西。不过对于周末黑客项目来说可能还不错。
好吧,受到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)
所以它工作但需要用引号括起来的数据.
我喜欢卡亚尔的回答。但是,如果您不想触摸输入文件,并且正在使用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)
您可以使用objcopy以下方法执行此操作:
objcopy --input binary --output elf64-x86-64 myfile.txt myfile.o
Run Code Online (Sandbox Code Playgroud)
现在您有了一个目标文件,您可以链接到您的可执行文件,其中包含myfile.txt.