簡體   English   中英

使用#include指令(預處理器)打印文件的內容

[英]Printing the contents of a file using the #include directive (preprocessor)

假設我有一個文件t.txt,其中包含以下兩行:

one    
two

現在,我想編寫一個程序,它將以某種方式#include該文件並打印其內容,僅此而已。 也就是說,我希望該文件的內容在編譯時以靜態文本的形式出現在我的代碼中。

有任何想法嗎?


我問的原因是這樣的:

我想通過包含我自己的文件(使用ifndefs來防止在前兩個之后包含遞歸包含)來創建一個quine: http : //en.wikipedia.org/wiki/Quine_ ( ifndefs 所以我仍然很想得到答案。

另一種解決方案(因為原來的人會並非沒有限制的工作,如在評論中提到的):作為構建過程的一部分,使用腳本(Perl或Python很容易做到這一點)來生成staticstring.hstaticstring.txt ,根據需要添加引號和\\n ,然后使用其他解決方案。 這樣,您的原始文件不會更改。

你想改變

Text file with text
on multiple
lines

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

我認為僅靠預處理器是不可能的。

這是要執行此操作的Microsoft教程: http : //support.microsoft.com/kb/816181/en-us

它不是在解釋如何以編程方式或通過預處理器嵌入文件,而是通過Visual Studio 2005+菜單。 並說明如何從資源部門讀回它。

Borland Delphi是通過預處理器完成的,我不了解C ++。 但是我知道可以像VS一樣手動編輯資源並將其包含在內。

xxd -i

看到這里: 以前的答案

這樣的事情對您有用嗎?

example.c

static const char *var = 
#include "staticstring.txt"
;

int main() {
    printf( "%s\n" var );
    return 0;
}

staticstring.txt

"Some string that gets included at compile time"

我敢肯定有一種方法可以在文本文件中不加引號的情況下完成此操作,但是現在什么都沒想到。

您可以在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.
> 

我所做的是:

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它。

您可以使用objcopy從源文件中創建一個目標文件,並將其與實際目標文件鏈接。 它創建符號_binary_objfile_start, _binary_objfile_end and _binary_objfile_size ,您可以將其作為char數組進行訪問。

據我所知,C語言中最短的quine是這樣的:

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''"' ),就可以避免不得不轉義的麻煩。

我不相信這是有可能的,因為您無法#在C中包含任意文本文件。原因是C中沒有多行常量(盡管您可以連接多個單行字符串)常量)。

我能看到的唯一選項是要求文本文件的每一行都加引號,或者在構建時生成一個臨時文件(如其他建議)。

TT:

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

TC

int main () {
#include <t.t>
}


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

更新:如果您不是追求純粹的奎因,而是僅僅吐出包含文件內容的東西,則可以執行以下操作:

TC:

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

TT:

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

這很簡單:

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

嚴重的是,不可能“ #include”任意文件。 (如果需要,請使用其他答案中給出的預處理建議之一。)

如果文件的內容不是任意的,而是包含對編譯器有意義的內容,則您可以將某些內容結合在一起。 為了使內容有意義,您可以使用C代碼和/或定義上面的代碼。

  • 將資源文件添加到您的項目。
  • 雙擊資源文件({projectname} .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);

就是這樣

槽我看不到Quine(計算)中的任何內容。 多態是另一個故事;)玩得開心。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM