0

ファイルから小さなフレーズをコピーするための小さなプログラムがありますが、seekg()がどのように機能するかについて誤解されているか、コードに問題があり、関数が期待どおりに機能しないようです。

テキスト ファイルには次のものが含まれます。

//イントロ

以前に注意した=false

このコードは、「false」という単語を文字列にコピーすることを目的としています

std::fstream stats("text.txt", std::ios::out | std::ios::in);
//String that will hold the contents of the file
std::string statsStr = "";
//Integer to hold the index of the phrase we want to extract
int index = 0;

//COPY CONTENTS OF FILE TO STRING
while (!stats.eof())
{
    static std::string tempString;
    stats >> tempString;
    statsStr += tempString + " ";
}

//FIND AND COPY PHRASE
index = statsStr.find("previouslyNoted=");     //index is equal to 8
//Place the get pointer where "false" is expected to be
stats.seekg(index + strlen("previouslyNoted="));     //get pointer is placed at 24th index
//Copy phrase
stats >> previouslyNotedStr;

//Output phrase
std::cout << previouslyNotedStr << std::endl;

しかし、何らかの理由で、プログラムは次のように出力します。

=偽

私が期待したこと:

ファイルの 24 番目のインデックスに get ポインターを配置したと思いますが、これは "false" という語句が始まる場所です。次に、プログラムはそのインデックスからスペース文字に到達するまで、またはファイルの終わりに到達するまで入力します。

実際に起こったこと:

なんらかの理由で、get ポインターが予想よりも早くインデックスを開始しました。そして、その理由はわかりません。何が間違っているのか、何が間違っているのかについての説明をいただければ幸いです。

また、私は、私が望むところから始めて、単にpreviousNotedStrをstatsStrの部分文字列にすることができることを理解しており、すでにそれを試して成功しています。私は本当にここで実験しているだけです。

4

2 に答える 2

2

VisualC++ タグは、Windows 上にいることを意味します。Windows では、行末には 2 文字 (\r\n) が必要です。一度に文字列でファイルを読み取る場合、この行末シーケンスは区切り文字として扱われ、単一のスペース文字に置き換えられます。

したがって、ファイルを読み取った後、statsStr はファイルの内容と一致しません。ファイル内の改行があるすべての場所で、2 文字を 1 文字に置き換えました。したがって、seekg を使用して、statsStr 文字列から取得した数値に基づいてファイル内に自分自身を配置すると、間違った場所に移動してしまいます。

改行処理を正しく行ったとしても、ファイルに 2 つ以上の連続する空白文字が含まれている場合、これらは読み取りループによって 1 つの空白文字に折りたたまれるため、問題が発生します。

于 2014-08-20T19:58:09.903 に答える
1

ファイルを単語ごとに読んでいます。より良い方法があります:

while (getline(stats, statsSTr)
{
  // An entire line is read into statsStr.
  std::string::size_type posn = statsStr.find("previouslyNoted=");
  // ...
}

テキスト行全体を文字列に読み取ることにより、ファイルの位置を変更する必要はありません。

また、単語単位で読むときに空白の問題があります。これは、テキストがファイル内にあると考える場所に影響します。たとえば、空白はスキップされ、スキップされたスペース、改行、またはタブの数はわかりません。

ところで、同じファイル内のテキストを置き換えることさえ考えないでください。テキストの置換は、置換テキストがファイル内の元のテキストと同じ長さである場合にのみ機能します。代わりに新しいファイルに書き込みます。

編集 1:より良い方法は、キー文字列を配列として
宣言することです。これは、文字列内でポインターを配置するのに役立ちます。

static const char key_text[] = "previouslyNoted=";
while (getline(stats, statsStr))
{
  std::string::size_type key_position = statsStr.find(key_text);
  std::string::size_type value_position = key_position + sizeof(key_text) - 1; // for the nul terminator.
  // value_position points to the character after the '='.
  // ...
}

データ ファイルを INI や XML などの既存の形式に準拠させ、適切なライブラリを使用してそれらを解析することにより、プログラミング タイプを節約したい場合があります。

于 2014-08-20T19:57:10.463 に答える