【问题标题】:String extraction字符串提取
【发布时间】:2008-12-15 07:11:18
【问题描述】:

目前我正在使用 C++ 环境开发非常基本的游戏。该游戏曾经是一个学校项目,但现在我已经完成了编程课程,我想扩展我的技能并在这个旧任务上发挥更大的作用。

我已经做了很多我很满意的改变。我已将所有数据集中到文件夹层次结构中,并获得了读取这些位置的代码。

但是,我的问题源于一个一直困扰着我的非常根本的缺陷。

为了访问我正在使用的图像数据,我使用了代码:

string imageLocation = "..\\DATA\\Images\\";

string bowImage = imageLocation + "bow.png";

问题是当玩家拿起游戏板上的物品时,我的代码应该使用该代码:

hud.addLine("You picked up a " + (*itt)->name() + "!");

打印到命令行,“你拿起了弓!”。但相反,它显示“你拿起了一个 ..\DATA\Images\!”。

在我集中我曾经使用的数据之前:

name_(item_name.substr(0, item_name.find('.')))

在我的 Item 类构造函数中将项目名称切割成弓或蜡烛之类的东西。在我改变了我的数据结构之后,我意识到我必须改变我将名字砍成同样简单的“弓”或“蜡烛”的方式。

我已更改上述代码以反映我对数据结构的更改为:

name_(item_name.substr(item_name.find("..\\DATA\\Images\\"), item_name.find(".png")))

但不幸的是,正如我之前提到的,这种代码更改并没有像我计划的那样工作。

现在我已经对我的问题进行了冗长的介绍,这是我的问题。

如何在不需要的两个部分之间提取字符串的中间部分?此外,作为您目标的中间部分的长度未知。

非常感谢你们提供的任何帮助。如果您需要更多信息,请询问;我将非常乐意上传部分甚至我的整个代码以获得更多帮助。再次非常感谢您。

【问题讨论】:

    标签: c++ string extract


    【解决方案1】:

    老实说,您可能是从错误的角度来解决这个问题的。

    你的物品类应该有一个字符串“bow”,在一个私有成员中。然后函数 Item::GetFilePath 将(在运行时)执行 "..\DATA\Images\" + this->name + ".png"。

    “弓”项目对象的基本属性不是文件名 bow.png,而是它是“弓”这一事实。文件名只是一个派生的属性。

    【讨论】:

      【解决方案2】:

      假设我理解正确,您的问题的简短版本是:如何拆分包含文件路径的字符串,以便删除路径和扩展名,只留下“标题”?

      您需要find_last_of 方法。这摆脱了路径:

      std::size_type lastSlash = filePath.find_last_of('\\');
      if (lastSlash == std::string::npos)
          fileName = filePath;
      else
          fileName = filePath.substr(lastSlash + 1);
      

      请注意,您可能需要将常量定义为\\,以防您需要为其他平台更改它。并非所有操作系统文件系统都使用\\ 来分隔路径段。

      另外请注意,您还需要使用find_last_of 作为扩展点,因为文件名通常可以在其路径中包含点。只有最后一个表示扩展的开始:

      std::size_type lastDot = fileName.find_last_of('.');
      if (lastDot == std::string::npos)
      {
          title = fileName;
      }
      else
      {
          title = fileName.substr(0, lastDot);
          extension = fileName.substr(lastDot + 1);
      }
      

      http://msdn.microsoft.com/en-us/library/3y5atza0(VS.80).aspx

      【讨论】:

        【解决方案3】:

        使用 boost 文件系统:

        #include "boost/filesystem.hpp"
        
        namespace fs = boost::filesystem;
        
        void some_function(void)
        {
            string imageLocation = "..\\DATA\\Images\\";
            string bowImage = imageLocation + "bow.png";
            fs::path image_path( bowImage  ); 
            hud.addLine("You picked up a " + image_path.filename() + "!");  //prints: You picked up a bow!
        

        【讨论】:

          【解决方案4】:

          所以结合保罗和我的想法,尝试这样的事情(为了可读性而分解):

          string extn = item_name.substr(item_name.find_last_of(".png"));
          string path = item_name.substr(0, item_name.find("..\\DATA\\Images\\"));
          name_ = item_name.substr( path.size(), item_name.size() - extn.size() );
          

          如果您知道项目名称总是以“..DATA”等开头,则可以稍微简化一下(您可以将其存储在常量中,而无需在字符串中搜索)

          编辑:按照 EarWicker 的建议,将扩展查找部分更改为使用 find_last_of,(这样可以避免您的路径在扩展之前的某处包含“.png”的情况)

          【讨论】:

            【解决方案5】:

            item_name.find("..\DATA\Images\") 将返回子字符串 "..\DATA\Images\" 开始 的索引,但您似乎想要它结束的索引,所以你应该将“..\DATA\Images\”的长度添加到find返回的索引中。

            另外,正如 hamishmcn 所指出的,substr 的第二个参数应该是要返回的字符数,即“.png”开始的索引减去“..\DATA\Images\”结束的索引,我想。

            【讨论】:

              【解决方案6】:

              看起来不对的一件事是 substr 的第二个参数应该是要复制的字符数,而不是位置。

              【讨论】:

                猜你喜欢
                • 2011-07-21
                • 2019-10-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-12-07
                相关资源
                最近更新 更多