你在找什麼是本地化,讀些關於它的東西here。如果您使用的是posix系統,那麼可以使用gettext()
,請參閱manpage。如果你使用Windows,你可以看看GetText for Windows。
不過,我寫了一個C++程序來生成你想要的文件,看下面的代碼。 您可以通過myProg filename logFunction
來調用它,其中filename
是要輸入的源文件,logFunction
是例如LOG
。
您將得到一個名爲filename_map
的地圖文件和一個新的源文件filename_new
。新的源文件將包含一個新的宏LOG
和一個函數readLocaleStrings()
,該函數將從filename_map
文件讀取程序開始處的所有字符串。新的宏LOG
將自動使用正確的字符串。
在你的榜樣,你會被myProg test.c LOG
調用它,並且將獲得:
test_map.txt
:
7: "Hello, my name %s, my age %d\n"
8: "I have wife and %d kids\n"
和test_new.c
:
// test.c
#include <stdio.h>
#define LOG(filename,line,...) printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)
/* Beginning: Generated code for localization */
#include <stdlib.h>
#include <string.h>
typedef struct {
size_t count;
size_t lastIdx;
char ** strings;
} stringArray_t;
stringArray_t localeStrings = { 0, 0, NULL };
int readLocaleStrings (const char * const filename)
{
FILE * file = NULL;
char * line = NULL;
char * str = NULL;
size_t len = 0;
ssize_t read;
file = fopen(filename, "r");
if (file == NULL)
{
return -1;
}
localeStrings.strings = malloc (sizeof (char *));
localeStrings.count = 0;
while (-1 != (read = getline(&line, &len, file)))
{
size_t curIdx = localeStrings.count++;
localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));
str = strstr(line, "\"");
localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));
strcpy (localeStrings.strings[curIdx], str);
}
fclose(file);
if (line)
{
free(line);
}
return 0;
}
void freeLocaleStrings()
{
size_t idx;
for (idx = 0; idx < localeStrings.count; ++idx)
{
free(localeStrings.strings[idx]);
}
free(localeStrings.strings);
}
/* End: Generated code for localization */
int main(int argc, char *argv[])
{
readLocaleStrings("test_map.txt");
LOG("test_map.txt", "7", "John", 30);
LOG("test_map.txt", "8", 2);
freeLocaleStrings();
return 0;
}
C++程序:
的C++程序有侷限性,它只會找到LOG("
如果你想也找到LOG
與空間的任何地方,如:LOG ("
,你必須改變這種代碼。此外,還有一些情況,比如多行消息,已被註釋掉的消息等。然後,您必須爲您的需求擴展代碼。也沒有很好的參數解析處理或錯誤檢查。此外,爲了編寫幫助代碼,需要找到主要功能。但是對於你給定的輸入文件,它可以很好地工作,並且應該指向正確的方向。使用正則表達式庫來擴展它更加簡單並且使其更加靈活將是明智的。
代碼:
#include <iostream>
#include <fstream>
/* Function definition is under main function */
const char * getNextHelperFunctionLine();
std::string getExtension (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract extension */
std::string extension;
if (std::string::npos != posDot)
{
/* extension found */
extension = filename.substr(posDot);
}
return extension;
}
std::string getFilename (const std::string filename)
{
/* get dot of e.g. foo.c */
size_t posDot = filename.rfind('.');
/* extract filename */
std::string name = filename;
if (std::string::npos != posDot)
{
name = name.substr(0, posDot);
}
return name;
}
int main (int argc, char* argv[])
{
if (argc < 3)
{
std::cerr << "Usage: "
<< " " << argv[0] << " filename logFunction"
<< std::endl;
return 0;
}
std::string infileName (argv[1]);
/* extract filename and extension */
std::string filename = getFilename(infileName);
std::string extension = getExtension(infileName);;
/* names for generated files */
std::string mapfileName = filename + "_map.txt";
std::string mappedfileName = filename + "_new" + extension;
/* open streams for input and output */
std::ifstream infile(infileName.c_str());
std::ofstream fileMap(mapfileName.c_str());
std::ofstream fileMapped(mappedfileName.c_str());
/* string for log function e.g. "LOG(" */
std::string logFun = std::string(argv[2]);
std::string logFunOpen = logFun + "(\"";
std::string lineRead;
size_t lineNr = 1;
size_t mainParanthesis = 0;
bool mainReturnFound = false;
/* Loop through whole input file */
while (std::getline(infile, lineRead))
{
/* position of log function opening e.g. "LOG(" */
size_t posLogOpen = lineRead.find(logFunOpen);
/* opening found? */
bool foundOpen = std::string::npos != posLogOpen;
if (foundOpen)
{
bool foundClose = false;
/* position of the string beginning */
size_t posLogStringBeg = posLogOpen + logFunOpen.length();
size_t posLogClose = posLogStringBeg;
/* find closing of the log function e.g. "LOG(...)" */
while (!foundClose)
{
/* search for '"' and skip these if they are in the string */
posLogClose = lineRead.find("\"", posLogClose + 1);
if (std::string::npos != posLogClose)
{
foundClose = (0 != lineRead.compare(posLogClose - 1, 1, "\\"));
}
}
/* closing found write map file and new source file */
if (foundClose)
{
size_t len = posLogClose - posLogStringBeg;
fileMap << lineNr << ": \""
<< lineRead.substr(posLogStringBeg, len) << "\""
<< std::endl;
fileMapped << lineRead.substr(0, posLogStringBeg - 1)
<< '"' << mapfileName << "\", "
<< '"' << lineNr
<< lineRead.substr(posLogClose)
<< std::endl;
}
}
/* not a log function write normal code */
else
{
if ( std::string::npos != lineRead.find("#define")
&& std::string::npos != lineRead.find(logFun))
{
/* log functions needs to be changed */
fileMapped << "#define "
<< logFun << "(filename,line,...) "
<< "printf(localeStrings.strings[localeStrings.lastIdx++], __VA_ARGS__)" << std::endl;
}
else if ( 0 == mainParanthesis
&& std::string::npos != lineRead.find(" main")
&& std::string::npos != lineRead.find("(")
&& std::string::npos != lineRead.find(")"))
{
/* found main function write all helper functions in front of it */
const char * helperLine;
while ((helperLine = getNextHelperFunctionLine()))
{
fileMapped << helperLine << std::endl;
}
/* write main function part */
fileMapped << lineRead << std::endl;
/* is there an opening parenthesis? */
if (std::string::npos != lineRead.find("{"))
{
++mainParanthesis;
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
}
else
{
/* in main function write first part */
if (std::string::npos != lineRead.find("{"))
{
/* write opening */
fileMapped << lineRead << std::endl;
if (0 == mainParanthesis)
{
fileMapped << " readLocaleStrings(\"" << mapfileName << "\");" << std::endl;
}
++mainParanthesis;
}
/* return statement? */
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("return"))
{
mainReturnFound = true;
fileMapped << " freeLocaleStrings();" << std::endl;
/* write return */
fileMapped << lineRead << std::endl;
}
else if ( 1 == mainParanthesis
&& std::string::npos != lineRead.find("}"))
{
--mainParanthesis;
if (!mainReturnFound)
{
fileMapped << " freeLocaleStrings();" << std::endl;
}
/* write closing */
fileMapped << lineRead << std::endl;
}
else
{
/* write other code */
fileMapped << lineRead << std::endl;
}
}
}
++lineNr;
}
return 0;
}
const char * getNextHelperFunctionLine()
{
static size_t idx = 0;
static const char * helperFunLines[] =
{
"",
"/* Beginning: Generated code for localization */",
"#include <stdlib.h>",
"#include <string.h>",
"",
"typedef struct {",
" size_t count;",
" size_t lastIdx;",
" char ** strings;",
"} stringArray_t;",
"",
"stringArray_t localeStrings = { 0, 0, NULL };",
"",
"int readLocaleStrings (const char * const filename)",
"{",
" FILE * file = NULL;",
" char * line = NULL;",
" char * str = NULL;",
" size_t len = 0;",
" ssize_t read;",
"",
" file = fopen(filename, \"r\");",
" if (file == NULL)",
" {",
" return -1;",
" }",
"",
" localeStrings.strings = malloc (sizeof (char *));",
" localeStrings.count = 0;",
"",
" while (-1 != (read = getline(&line, &len, file)))",
" {",
" size_t curIdx = localeStrings.count++;",
" localeStrings.strings = realloc(localeStrings.strings, localeStrings.count * sizeof (char *));",
"",
" str = strstr(line, \"\\\"\");",
" localeStrings.strings[curIdx] = malloc(sizeof (char) * (size_t)(1 + read));",
" strcpy (localeStrings.strings[curIdx], str);",
" }",
"",
" fclose(file);",
" if (line)",
" {",
" free(line);",
" }",
"",
" return 0;",
"}",
"",
"void freeLocaleStrings()",
"{",
" size_t idx;",
" for (idx = 0; idx < localeStrings.count; ++idx)",
" {",
" free(localeStrings.strings[idx]);",
" }",
" free(localeStrings.strings);",
"}",
"/* End: Generated code for localization */",
""
};
if (idx < (sizeof (helperFunLines)/sizeof (helperFunLines[0])))
{
return helperFunLines[idx++];
}
else
{
return nullptr; /* use NULL if compiler doesn't support nullptr */
}
}
我有點不確定你實際上問...你只是想搜索的地方LOG'使用'所有源文件?或者你是否真的想要實現一個日誌系統? –
所以你說你想記錄原始格式字符串?爲什麼? – dbush
不知道預處理器和Make,但肯定可以用腳本來完成。或者你可以寫一個'c'程序:-) – 4386427