0

段落を取り、各単語の最初の文字を表示する関数を作成しようとしていました。プログラムは最初の数回は正常に実行されますが、その後のインスタンスでは、関数の実行後に動作が停止します。コードは次のとおりです。

//program that returns the first letter of each word in a paragraph
#include <iostream>
#include <string>
using namespace std;

void firstLetter(string, ostream&);

int main()
{
    string paragraph;

    cout<<"Enter a paragraph."<<endl;
    getline(cin, paragraph);

    firstLetter(paragraph, cout);

    return 0;
}

void firstLetter(string words, ostream& out)
{
    for(int i= 0; i < words.length(); i++){
        out<<words[i++]<<" ";

        while(words[i] != ' '){
            i++;
        }
    }
}

.exe ファイルを削除してプロジェクトを再構築しようとしましたが、数回実行すると再び機能しなくなります。なぜこれが起こっているのですか?

4

4 に答える 4

3

ループが問題です。

for(int i= 0; i < words.length(); i++){
    out<<words[i++]<<" ";

    while(words[i] != ' '){
        i++;
    }
}

インクリメントi式 ( i++) でインクリメントしますが、式でもインクリメントしますout <<...。while ループはここで無効なデータにアクセスできます。これは、for ループでの前回のチェックの後、およびスキップされた文字ごとに再度インクリメントしているためです。遅かれ早かれ、ここで無効なデータにアクセスするようになり、未定義の動作が発生したり、セグメンテーション エラーが発生したりすることさえあります。

最後の文字を出力/スキップしなかった場合にのみ、スペース以外をスキップしたいと思います(最後の単語の場合)。これには、while ループで別のチェックが必要です。

    while(i < words.length() && words[i] != ' '){
        i++;
    }

複数のスペース、ダッシュ (出力したくない場合)、その他の派手な印刷上の問題などにはまだ問題があります... しかし、これらのケースを考慮する必要はないと思います。

于 2013-01-05T02:15:26.497 に答える
2

ループ内でiのサイズを超えていないか確認する必要があります。wordswhile

while(i < words.length() && words[i] != ' '){
    i++;
}
于 2013-01-05T02:25:11.540 に答える
0

ライムスに同意します。'hello, world' があると思いますが、出力は 'h w' で、エラーになります。'world' の後に ' ' がないため、while ループが終了せず (無効な場所に到達する)、代わりに '\0' が発生します。「\0」をチェックして、関数を返すことをお勧めします。お気に入り :

while(words[i] != ' ' && words[i] != '\0') 
{
i++;
}

(そして、あなたが出会った素晴らしいケースは、最後にスペースがあるものであるべきだと思います。)

于 2013-01-05T02:23:22.757 に答える
0

問題は、i が文字列の境界を超えると内側のループが無限になることです。

  void firstLetter(string words, ostream& out)
    {
        for(size_t i= 0, len = words.length(); ; i++){  // i < words.length() removed, it is checked in the inner loop
            out<<words[i]<<" ";

            while(words[i] != ' '){
                if( i == len-1 ) return;
                i++;
            }
        }
    }

私が個人的に使用することを好む代替手段は次のとおりです。

#include <sstream>

    void firstLetter2(string words, ostream& out)
    {
        istringstream iss(words);

        while( ! iss.eof() )
        {
            string sWord;
            iss >> sWord >> ws;
            out<<sWord[0]<<' ';
        }
    }
于 2013-01-05T02:33:15.153 に答える