代码之家  ›  专栏  ›  技术社区  ›  rmn

使用include指令(预处理器)打印文件内容

  •  0
  • rmn  · 技术社区  · 16 年前

    假设我有一个文件t.txt,其中包含以下两行:

    one    
    two
    

    现在,我想写一个程序 #include 那个文件不知怎么打印了它的内容。也就是说,我希望该文件的内容在编译时以静态文本的形式出现在代码中。

    有什么想法吗?


    我问的原因是:

    我想创建一个奎因,包括我自己的文件 ifndefs 要防止前两个之后的递归包含,请执行以下操作: http://en.wikipedia.org/wiki/Quine_(computing) . 所以我还是很想得到答案。

    12 回复  |  直到 9 年前
        1
  •  2
  •   Graeme Perrow    16 年前

    另一种解决方案(因为原始的解决方案没有限制就无法工作,如注释中所述):作为构建过程的一部分,使用脚本(Perl或Python很容易做到)来生成 staticstring.h staticstring.txt ,添加引号和 \n 根据需要,然后使用其他解决方案。这样原始文件就不会更改。

    你想改变

    Text file with text
    on multiple
    lines
    

    "Text file with text\n"
    "on multiple\n"
    "lines"
    

    我认为纯粹使用预处理器是不可能的。

        2
  •  1
  •   Havenard    16 年前

    这是微软的教程: http://support.microsoft.com/kb/816181/en-us

    它不是解释如何通过编程或预处理器嵌入文件,而是通过Visual Studio 2005+菜单。并解释如何从资源部门读回它。

    Borland Delphi通过预处理器实现这一点,我不知道C++。但我知道可以手动编辑资源并将其包括在内,就像vs所做的那样。

        3
  •  1
  •   Community Mohan Dere    9 年前

    xxd -i

    请参见这里: previous answer

        4
  •  0
  •   Graeme Perrow    16 年前

    你想要这个吗?

    实例C

    static const char *var = 
    #include "staticstring.txt"
    ;
    
    int main() {
        printf( "%s\n" var );
        return 0;
    }
    

    静态字符串.txt

    "Some string that gets included at compile time"
    

    我相信有一种方法可以做到这一点,而不需要在文本文件中使用引号,但是现在没有什么事情需要考虑。

        5
  •  0
  •   Loki Astari    16 年前

    您可以在makefile中执行此操作:

    all:  target
    
    TEXT_FILES  = $(wildcard *.txt)
    TEXT_OBJS   = $(patsubst %.txt,%.text.o,$(TEXT_FILES))
    
    
    target: main.o $(TEXT_OBJS)
        $(CXX) -o app $^
    
    %.text.cpp: %.txt
        @echo "Building Text Source $*"
        @echo "char const* $* =" > $@
        @awk '{print "\"" $$0 "\\n\"";}' $^ >> $@
        @echo ";" >> $@
    

    这是怎么回事。
    如果您有一个名为plop.txt的文本文件。然后它用变量'char const*plop='创建一个文件plop.text.cpp。编译后,临时文件将被删除,但如果更改plop.txt文件,它将自动神奇地重建为plop.text.o。

    然后将这些结合在一起:

    以下是我测试的示例:

    > cat main.cpp
    
    #include <iostream>
    extern char* text;
    
    int main()
    {
    std::cout << text;
    }
    
    > cat text.txt 
    
    Hi there this is a file
    with multiple lines
    we want to print out.
    > make
    g++    -c -o main.o main.cpp
    Building Text Source text
    g++    -c -o text.text.o text.text.cpp
    g++ -o app main.o text.text.o
    rm text.text.cpp
    > ./app
    
    Hi there this is a file
    with multiple lines
    we want to print out.
    > 
    
        6
  •  0
  •   Michael Krelin - hacker    16 年前

    我做的是:

    COPYING.cc: ${top_srcdir}/COPYING
        echo "const char * COPYING = " >$@ || (rm $@;exit 1)
        sed -e 's/"/\\"/g' -e 's/^/\"/' -e 's/$$/\\n\"/' $< >>$@ || (rm $@;exit 1)
        echo ';' >>$@ || (rm $@;exit 1)
    

    在我的 Makefile . 然后我称之为 extern const char *COPYING 但是一个人可以 #include 它也是如此。

        7
  •  0
  •   Ozan HELPY    16 年前

    可以使用objcopy从源文件中创建一个对象文件,并将其与实际的对象文件链接起来。它创建符号 _binary_objfile_start, _binary_objfile_end and _binary_objfile_size ,可以作为char数组访问。

        8
  •  0
  •   Adam Rosenfield    16 年前

    据我所知,C中最短的奎因是:

    main(){char*a="main(){char*a=%c%s%c;printf(a,34,a,34);}";printf(a,34,a,34);}
    

    请注意,这不是有效的C++,因为它使用隐式定义。 printf() . 要使它有效C++,你需要这样做:

    #include <stdio.h>
    main(){char*a="#include <stdio.h>%cmain(){char*a=%c%s%c;printf(a,10,34,a,34);}";printf(a,10,34,a,34);}
    

    不需要技巧——只需仔细构造一个字符串并打印两次,然后使用ASCII代码(10和34而不是 '\n' '"' )为了避免对必须逃避东西的烦恼。

        9
  •  0
  •   Martin    16 年前

    我不认为这是可能的,因为您不能在C中包含任意文本文件。原因是C中没有多行常量(尽管您可以连接多个单行字符串常量)。

    我能看到的唯一选项是要求引用文本文件的每一行,或者在构建时生成一个临时文件(如其他人建议的那样)。

        10
  •  0
  •   ezpz    16 年前

    T.T:

    printf ("int main () {\n");
    printf ("#include <t.t>\n");
    printf ("}");
    return 0;
    

    T.C

    int main () {
    #include <t.t>
    }
    
    
    $ gcc -I. t.c
    $ ./a.out
    int main () {
    #include <t.t>
    } 
    

    更新: 如果您不需要纯奎因,而只需要一些可以吐出所包含文件内容的东西,您可以执行以下操作:

    T.C:

    #include <stdio.h>
    #include "t.t"
    

    T.T:

    #define FOO(f) do { \
            FILE * ff = fopen(f, "rb"); \
            char foo[255] = {0}; \
            while (fgets (foo, 255, ff)) { \
                    printf ("%s", foo); \
            }\
            fclose(ff); \
    } while (0)
    
    int main () {
            FOO("t.t");
            return 0;
    }
    

    运行此收益率

    $ gcc t.c
    $ ./a.out
    #define FOO(f) do { \
            FILE * ff = fopen(f, "rb"); \
            char foo[255] = {0}; \
            while (fgets (foo, 255, ff)) { \
                    printf ("%s", foo); \
            }\
            fclose(ff); \
    } while (0)
    
    int main () {
            FOO("t.t");
            return 0;
    }
    
        11
  •  0
  •   Ralph    16 年前

    这很容易:

    #include <stdio.h>
    
    // include the file somehow
    #define one 
    #define two 
    #include "t.txt"
    
    int main(int argc, char* argv[])
    {
        // and print the contents of the file
        const char* static_text = "one\ntwo\n";
        printf(static_text);
    
        // nothing more ;-)
        return 0;
    }
    

    说真的,不可能“包含”任意文件。(与其中之一) 其他答案中给出的预处理建议(如果需要)。

    如果文件的内容不是任意的,而是包含某些内容 对编译器有意义的是,你也许可以破解一些东西 一起。为了使内容有意义,可以使用C代码和/或 像我上面所做的那样定义。

        12
  •  0
  •   SoLaR    12 年前
    • 将资源文件添加到项目中。
    • 双击资源文件(项目名称.rc),打开资源编辑器。
    • 在资源编辑器中添加自定义类型,例如cppcode。
    • 在该资源文件的二进制内容中输入一些二进制数据。
    • 全部保存,然后关闭资源编辑器。
    • 打开projectname.rc文件作为代码。
    • 找到cppcode并用引号将文件路径替换为projectname.cpp文件所在的文件(相对路径)。它应该是这样的:

    代码:

    IDR_FILE_DIRECTORYINFO_H    CPPCODE "DirectoryInfo.h"
    IDR_FILE_DIRECTORYINFO_CPP  CPPCODE "DirectoryInfo.cpp"
    
    • 检查resource.h是否包含IDR_file_directoryinfo_h…的正确定义,如果您添加了其他条目:

    代码:

    #define IDR_FILE_DIRECTORYINFO_H        312
    #define IDR_FILE_DIRECTORYINFO_CPP      313
    
    • 访问和打印资源内容:

    代码:

    HRSRC hRes = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_FILE_DIRECTORYINFO_CPP), _T("CPPCODE"));
    DWORD dwSize = SizeofResource(GetModuleHandle(NULL), hRes);
    HGLOBAL hGlob = LoadResource(GetModuleHandle(NULL), hRes);
    const char* pData = reinterpret_cast<const char*>(::LockResource(hGlob));
    
    MessageBoxA((HWND)0, pData, "This project source code:", MB_OK);
    

    就这样

    我看不出奎因(计算)有什么意义。 多态性是另一回事;) 玩得高兴。