【问题标题】:Help me translate Python code which replaces an extension in file name to C++帮我将替换文件名扩展名的 Python 代码翻译成 C++
【发布时间】:2010-07-09 21:57:34
【问题描述】:

如果您对 Python 一无所知,我深表歉意,但是,下面的 sn-p 应该对任何人都非常易读。唯一需要注意的技巧 - 使用 [-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 或其他标题以启用一些魔法也不是正确的解决方案。

谢谢。

【问题讨论】:

  • 谁对我投了反对票 - 请告诉我为什么我的问题很愚蠢。
  • 我没有对你投反对票,但他们可能是因为你要求其他人简单地完成你的工作而不是给你提示。
  • 看来我可能不得不在这个上放赏金。
  • 我想知道你为什么要玩弄列表。您对问题的描述不能用正则表达式替换完全解决吗?只是好奇。
  • @mawimawi 这是遗留的 C++ 代码。我们不允许使用 BOOST(只是给你一个想法)。虽然正则表达式可能是一种更简洁的方法(在这种特殊情况下,它可能有点过头了,而且我还需要检测扩展名丢失或不是 .xml 的情况)。因此,虽然 Python 可以做各种简洁的事情,但我无法将其直接转换为我的遗留 C++ 代码库。希望这是有道理的。

标签: c++ python visual-studio-2010 string unicode-string


【解决方案1】:

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

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");
  }
}

【讨论】:

  • 好东西,如果它有效,那么我喜欢它。让我测试一下。顺便说一句:愚蠢的问题:是还是不是Unicode?​​span>
  • 是的,您对 CompareNoCase 的看法是正确的,对此感到抱歉,已修复。
  • 至于Unicode与否,对于Visual Studio项目,这取决于你的项目设置;特别是是否定义了 UNICODE 宏。 ATL 具有字符串转换功能,可以从 UTF-8 转换为 UTF-16 并返回,在 MSDN 中搜索“ATL 7.0 字符串转换类和宏”,它们被称为 CW2A()、CT2W() 等。
  • @Hamish Grubijan:您的字符串不会以 Unicode 格式存储。 Unicode 只是一个规范。您的数据需要使用该规范的特定表示,即 UTF-8、UTF-16、UTF-32 或许多其他格式之一。最常见的是 UTF-8。如果您使用的是 UTF-8,那么 .字符是单字节。
【解决方案2】:

我没有像您的代码那样拆分字符串,因为这在 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;

【讨论】:

  • 好,你显然不必在用 C++ 编码时用 Python 思考。是string Unicode 吗?如何将“CAtlString”转换为string?是std::string 吗?另外,您在哪里将"XmL" 转换为小写?
  • 啊抱歉,我不熟悉 ATL,所以我不确定如何转换为 std::string。 std::string 不是 unicode,但 std::wstring 是。尽管使用 wstring 有点棘手,因为您无法直接将其与字符串文字(即“xml”)进行比较。您需要使用其他代码来执行此操作....
  • std::string 可以是 Unicode;它可以保存任何 8 位编码的字符,包括 UTF-8。
猜你喜欢
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多