在C++; 我有一个C++程序,代码中有成千上万个字符串文字,需要翻译,例如: statusBar->Print( "My Message" );
我使用一个函数包装字符串文本,该函数在字典中查找值并返回翻译版本:在C++; 我有一个C++程序,代码中有成千上万个字符串文字,需要翻译,例如: statusBar->Print( "My Message" );,c++,C++,我使用一个函数包装字符串文本,该函数在字典中查找值并返回翻译版本: statusBar->Print( Translated( "My Message" ) ); 问题是,在分析之后,我发现在整个代码中进行这种查找是一个性能问题。我想做的是将这样的行更改为: static const char * translatedMessage5 = Translated( "My Message" ); statusBar->Print( translatedMessage5 ); 但是由
statusBar->Print( Translated( "My Message" ) );
问题是,在分析之后,我发现在整个代码中进行这种查找是一个性能问题。我想做的是将这样的行更改为:
static const char * translatedMessage5 = Translated( "My Message" );
statusBar->Print( translatedMessage5 );
但是由于代码中有数千个这样的实例,它很容易出错(并且有点像维护噩梦)。我希望我能把
翻译成一个宏,它可以在线声明静态变量。这显然行不通。有谁有更好的主意吗?您能转换为唯一的错误代码并将其索引到向量中吗?这简化了代码和查找,添加额外的错误消息变得微不足道。此外,还可以确保以这种方式添加的错误消息更加可见(例如,在该应用程序外部,可以轻松地发布到“用户指南”或类似文件中)
#包括
#包括
枚举错误消息
{
我的留言,
我的另一条信息,
...
味精高
};
std::向量错误消息;
void init()
{
错误消息。调整大小(消息高);
错误消息[我的消息]=“我的消息”;
错误消息[我的其他消息]=“我的其他消息”;
...
}
常量字符*常量翻译(常量错误消息消息消息)
{
返回错误消息[msg].c_str();
}
void f()
{
状态栏->打印(翻译为my_msg);
}
这可能对您没有帮助,但您可以做的是声明一个std::map,它将保存一个哈希->文本对的映射。这里的问题是,在字符串上计算哈希代码是否与翻译它的工作量相同,这我不知道
char * Translate(char *source)
{
static std::map<int, char*> sources;
static std::map<int, char*> results;
int hashcode = CalculateHashCode(source);
std::map<int, char*>::const_iterator it = sources.find( source );
if ( it != sources.end() )
{
return results[ hashcode ];
}
... code to translate ...
results[ hashcode ] = translated;
}
char*翻译(char*源)
{
静态std::映射源;
静态std::映射结果;
int hashcode=CalculateHashCode(源代码);
std::map::const_迭代器it=sources.find(source);
if(it!=sources.end())
{
返回结果[哈希代码];
}
…要翻译的代码。。。
结果[哈希代码]=已翻译;
}
打印邮件所需的I/O时间应该比任何字典查找时间多几个数量级。如果不是这样,你就做错了
经过测试的软件可以满足您的需求。我建议你要么学习,这是每个其他自由和开放源码软件项目使用的,要么只是在你的程序中使用它,而不是自制的解决方案
<> > >编辑:用C++ 0x可以做你想做的,但是仍然要考虑使用你真正的L10N引擎。下面是一些概念验证小代码:
#include <iostream>
const char* realTranslate(const char* txt)
{
std::cout << "*** translated " << txt << std::endl;
return txt; // use a real translation here such as gnu gettext
}
#define Translate(txt) \
(([]()->const char* \
{static const char* out = realTranslate(txt); return out;})())
int main ()
{
for (int i = 0; i < 10; ++i)
{
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is another message") << std::endl;
}
}
#包括
const char*realTranslate(const char*txt)
{
std::cout是如何翻译的
的?您使用的是高效的哈希表实现吗?@Brian-我不说这是一个解决方案,但您是如何实现字典的?它是否使用最合适的数据结构进行查找(例如boost::unorded_map),因为Translated()显然,需要一个字符串,即使是高效的哈希也必须对整个字符串进行哈希,这是非常昂贵的。是的,这是我尝试的第一件事。因为表的大小是固定的,所以我将其分配为一个带有键字符串、值字符串和“next”的单个大数组索引。然后是一个哈希数组,它指向每个哈希键的第一个索引。大部分时间都花在实际计算哈希键上。你的应用程序支持在运行时更改语言,还是在启动时固定?如果是前者,在第一次调用函数时缓存翻译后的字符串是一个非常糟糕的主意(tm)!enum
值没有名称空间,您可能需要修复最后一行。@安德烈:它们在MSVC和C++0x中有效。这很可能是我必须要做的。我试图避免这样做,因为必须转换成千上万行已经存在的代码(不仅工作量很大,而且还容易出错)。此外,很难确定和删除未使用的消息。将其视为一种好处--您可以合理化所有现有错误消息,并将它们放在一个易于导出的位置。此外,如果需要进行“翻译”(如语言翻译支持),则,只需更改错误消息并保持其余代码原样就可以支持其他语言。@DeadMG:除非另有说明,否则我假设C++03。+1,如果OP希望自己的程序使用i18n,gettext是可以使用的工具。即使他想编写自己的解决方案,他也应该研究gettext手册,以在某些方面看到这一点cases(复数形式)仅仅做一个简单的字典查找是不够的。C++0x lambda版本非常棒。我还没有意识到这是可能的。FWIW真正的问题不是本地化,但我用它作为我的例子,因为它更容易摸索。
#include <iostream>
const char* realTranslate(const char* txt)
{
std::cout << "*** translated " << txt << std::endl;
return txt; // use a real translation here such as gnu gettext
}
#define Translate(txt) \
(([]()->const char* \
{static const char* out = realTranslate(txt); return out;})())
int main ()
{
for (int i = 0; i < 10; ++i)
{
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is a message") << std::endl;
std::cout << Translate("This is another message") << std::endl;
}
}