4

如果您对 Python 一无所知,我深表歉意,但是,以下代码段应该对任何人都非常易读。唯一需要注意的技巧 - 索引列表[-1]会为您提供最后一个元素(如果有的话),或者引发异常。

>>> fileName = 'TheFileName.Something.xMl'
>>> fileNameList = fileName.split('.')
>>> assert(len(fileNameList) > 1) # Must have at least one period in it
>>> assert(fileNameList[-1].lower() == 'xml')
>>> fileNameList[-1] = 'bak'
>>> fileName = '.'.join(fileNameList)
>>> print(fileName)
TheFileName.Something.bak

我需要将此逻辑转换为具有以下签名的 C++(我实际使用的语言,但到目前为止很烂)函数:void PopulateBackupFileNameOrDie(CAtlString& strBackupFileName, CAtlString& strXmlFileName);. 这里strXmlFileName是“输入”,strBackupFileName是“输出”(我应该颠倒两者的操作吗?)。棘手的部分是(如果我错了,请纠正我)我正在使用 Unicode 字符串,所以寻找这些字符:.xmlXML不是那么直截了当。最新的 Python 没有这些问题,因为'.'两者都是长度为 1"."的 Unicode 字符串(不是"char"类型),都只包含一个点。

请注意,返回类型是void- 不要太担心。我不想让您厌烦我们如何将错误传达给用户的细节。在我的 Python 示例中,我只使用了一个断言。您可以执行类似的操作,也可以只添加评论,例如// ERROR: [REASON].

请询问是否有不清楚的地方。使用std::string等而不是CAtlString函数参数的建议不是我想要的。如果必须,您可以在函数内转换它们,但我不希望在一个函数中混合不同的字符串类型。我正在使用 VS2010 在 Windows 上编译这个 C++。这意味着我不会安装BOOSTQTString其他开箱即用的库。窃取一个boost或其他标题以启用一些魔法也不是正确的解决方案。

谢谢。

4

2 回答 2

6

如果您使用 ATL,为什么不直接使用CAtlString's 方法?

CAtlString filename = _T("TheFileName.Something.xMl");

//search for '.' from the end
int dotIdx = filename.ReverseFind( _T('.') );

if( dotIdx != -1 ) {
  //extract the file extension
  CAtlString ext = filename.Right( filename.GetLength() - dotIdx );

  if( ext.CompareNoCase( _T(".xml" ) ) == 0 ) {
    filename.Delete( dotIdx, ext.GetLength() ); //remove extension
    filename += _T(".bak");
  }
}
于 2010-07-12T05:32:51.670 回答
3

我没有像您的代码那样拆分字符串,因为这在 C++ 中需要做更多的工作而实际上没有任何好处(它更慢,而且对于这项任务,您真的不需要这样做)。

string filename = "TheFileName.Something.xMl";
size_t pos = filename.rfind('.');
assert(pos > 0 && pos == filename.length()-4); // the -4 here is for length of ".xml"
for(size_t i = pos+1; i < filename.length(); ++i)
    filename[i] = tolower(filename[i]);
assert(filename.substr(pos+1) == "xml");
filename = filename.substr(0,pos+1) + "bak";
std::cout << filename << std::endl;
于 2010-07-09T22:12:28.767 回答