2

現在、私は C++ 環境を使用して非常に基本的なゲームに取り組んでいます。このゲームは以前は学校の課題でしたが、プログラミングの授業が終わった今、自分のスキルを広げて、この古い課題にもっと力を入れたいと思いました。

私はすでに多くの変更を行っており、満足しています。すべてのデータをフォルダー階層に集中化し、それらの場所を読み取るコードを取得しました。

しかし、私の問題は、私を悩ませてきた非常に根本的な欠陥から生じています。

使用している画像データにアクセスするために、次のコードを使用しました。

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

string bowImage = imageLocation + "bow.png";

問題は、プレイヤーがゲームボード上のアイテムを拾ったときに、私のコードが次のコードを使用することになっていることです:

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

コマンドラインに「You pick up a Bow!」と出力します。しかし、代わりに「You pick up a ..\DATA\Images\!」と表示されます。

データを一元化する前は、次のものを使用していました。

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

私の Item クラスコンストラクターで、アイテム名を弓やろうそくのようなものに切り刻みます。データの構造を変更した後、名前を同じ単純な「bow」または「candle」に切り詰める方法を変更する必要があることに気付きました。

データ構造の変更を反映するために上記のコードを次のように変更しました。

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

しかし、残念なことに、先ほど触れたように、このコードの変更は、私が計画していたほどうまく機能していません。

さて、私の問題が何であるかについて、本当に長い説明をしたので、ここに私の質問があります。

不要な 2 つのセクション間の文字列の中間をどのように抽出しますか? また、ターゲットであるその中間部分の長さは不明です。

皆さんが与えることができるどんな助けにもとても感謝しています. さらに情報が必要な場合は、お問い合わせください。より多くの助けが必要な場合は、コードの一部または全体をアップロードしていただければ幸いです。改めまして、誠にありがとうございました。

4

6 に答える 6

7

正直なところ、あなたはおそらく間違った端からこれに近づいています。

アイテムクラスには、プライベートメンバーの文字列「bow」が必要です。関数Item::GetFilePathは、(実行時に) ".. \ DATA \ Images \" + this-> name+".png"を実行します。

「bow」アイテムオブジェクトの基本的なプロパティは、ファイル名bow.pngではなく、「bow」であるという事実です。ファイル名は単なる派生プロパティです。

于 2008-12-15T10:41:46.633 に答える
3

ブーストファイルシステムを使用:

#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!
于 2008-12-15T10:25:54.357 に答える
3

私があなたを正しく理解していると仮定すると、あなたの質問の短いバージョンは次のとおりです。ファイルパスを含む文字列を分割して、パスと拡張子を削除し、「タイトル」だけを残すにはどうすればよいですか?

find_last_ofメソッドが必要です。これはパスを取り除きます:

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

\\他のプラットフォーム用に変更する必要がある場合に備えて、定数を定義したい場合があることに注意してください。すべての OS ファイル システム\\がパス セグメントの分離に使用されるわけではありません。

find_last_ofまた、一般にファイル名にはパス全体にドットを含めることができるため、拡張ドットにも使用する必要があることに注意してください。拡張機能の開始を示すのは最後の 1 つだけです。

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を参照してください。

于 2008-12-15T08:40:15.037 に答える
2

したがって、Paul と私の考えを組み合わせて、次のようなことを試してください (読みやすいように分割してください)。

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」などで始まることがわかっている場合は、少し単純化できます(定数に格納でき、文字列で検索する必要はありません)

編集: find_last_ofEarWicker が提案するように、拡張機能の検索部分を使用するように変更しました (これにより、パスに拡張機能の前のどこかに '.png' が含まれる場合が回避されます)。

于 2008-12-15T08:03:47.607 に答える
1

item_name.find("..\DATA\Images\") は、部分文字列 "..\DATA\Images\"が始まるインデックスを返しますが、それが終わるインデックスが必要なようですので、追加する必要があります"..\DATA\Images\" から find によって返されるインデックスまでの長さ。

また、hamishmcn が指摘したように、substr の 2 番目の引数は、返される文字数である必要があります。これは、「.png」が始まるインデックスから「..\DATA\Images\」が終わるインデックスを引いたものになると思います。

于 2008-12-15T07:26:24.640 に答える
0

間違っているように見えることの 1 つは、substr の 2 番目のパラメーターは、位置ではなく、コピーする文字数でなければならないことです。

于 2008-12-15T07:22:50.793 に答える