3

各行の単語を逆にする必要がある単純な文字列操作の問題があります: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=121&page=show_problem&problem=424

そう:

I love you.
You love me.
We're a happy family.

次のようになります。

I evol .uoy
uoY evol .em
er'eW a yppah .ylimaf

今、私は次のような単純な Java ソリューションを作成しました。

BufferedReader file = new BufferedReader(new InputStreamReader(System.in));
String s;
while((s=file.readLine())!=null){
    String[] sr = s.split(" ");
    for(int i = 0; i<sr.length; i++)
        System.out.print(new StringBuffer(sr[i]).reverse() + (i==sr.length-1?"\n":" "));
}

私は C++ を学ぼうとしているので、次のような C++ ソリューションも書いてみました。

string s;
while(getline(cin, s)){
    string tmp = "";
    for(int i = 0; i<=s.length(); i++)
        if( i==s.length() || s[i] == ' '){
            for(int j = tmp.length(); j>=0; j--)
                cout << tmp[j];
            if( i == s.length()) cout << endl;
            else cout << " ";
            tmp = "";
        }else
            tmp += s[i];
}

私の質問は次のとおりです。

  1. C++ ソリューションは「間違った答え」を返しますが、Java ソリューションは受け入れられます。なぜですか?
  2. C++ ソリューションに対して、どのような改善を加えることができますか?
4

6 に答える 6

3

boost::splitブーストが許可されている場合は、boost::joinとの組み合わせを使用しstd::reverseます。

std::string line;
std::vector<std::string> vs;
while (getline(std::cin, line)) {       
    boost::split(vs, line, ::isspace);
    for (auto & word : vs)
        std::reverse(word.begin(), word.end());
    std::cout << boost::join(vs, " ") << '\n';
}

ブーストが利用できない場合は、それらの関数 (または同様のもの) を個人のライブラリに置き、提出物にコピーするだけです。

于 2012-06-22T05:16:20.593 に答える
3
std::string line_string;
while ( getline( std::cin, line_string ) ) {

    // Instead of `split`, read out of a std::istringstream:
    std::istringstream line_stream( line_string );
    std::string word;
    while ( line_stream >> word ) {

        // Use std::reverse instead of a loop:
        std::reverse( word.begin(), word.end() );

        // Always qualify with std:: instead of using namespace std;
        std::cout << word << ' ';
    }
    std::cout << '\n'; // prefer '\n' to std::endl unless you need a flush
}

http://ideone.com/hd3bg

これで問題が解決しない場合は、おそらく各行の末尾にある末尾のスペースが原因です。ブール変数を使用して、改行の前にスペースを印刷しないようにします。

于 2012-06-22T04:57:07.483 に答える
1

間違った理由は次のとおりです。

string s;
while(getline(cin, s)){
    string tmp = "";
    for(int i = 0; i<=s.length(); i++)
        if( i==s.length() || s[i] == ' '){
            for(int j = tmp.length(); j>=0; j--)
                        ^^^^^^^^^^^^ => the first tmp[j] is \0!
                                     => should be tmp.length()-1
                cout << tmp[j];
            if( i == s.length()) cout << endl;
            else cout << " ";
            tmp = "";
        }else
            tmp += s[i];
}

c/c++ では、インデックスは 0 から始まることを思い出してください。

于 2012-06-22T05:42:05.377 に答える
1

逆の順序で単純に印刷するのではなく、逆の操作を処理するために絶対に新しい変数を作成したい場合。次に、次のことを考慮する必要があります。C++ では、インデックスは文字列の長さではありません。インデックスは 0 から始まるため、インデックス 0 からインデックス : length - 1 まで開始します。

C++ を始めたい場合は、基本に慣れた後、他の場所に行く前に STL を掘り下げることをお勧めします (これは私の意見です)。

ここにいくつかのコードがあります:

string s;  
while(getline(cin, s))
{      
   string tmp = "";      
   for(int i = s.length() - 1; i >= 0; i++)
       std::cout<<s[i];
}
于 2012-06-22T10:31:23.843 に答える
0

ここで私が試したもの。

#include <iostream>
#include <string>

 using namespace std;


 int main(){

    string s = "Hello How are you Mr vins what are you doing now";
    string temp, reverse;

   int i,j;
     // Traverse through First string
    for (i=0;i <=s.length(); i++)
   {
if(s[i] == ' ' || s[i] == '\0') {
    //After getting space reverse the previous word and add to reverse string
    for (j = temp.length(); j >=0; j--)
        reverse = reverse + temp[j];

    reverse = reverse + " ";
    temp="";
    continue;
}
temp = temp + s[i];

}

 cout << "\nlets see reversed sentence \n";

   cout << reverse << "\n";
      return 0;
   }
于 2012-06-22T08:24:42.583 に答える
0

word.rbegin(), word.rend()これを行う場合は、新しい文字列を作成し、引数としてコンストラクターに渡すことで、各単語を逆にすると思います。

以前の回答のLineクラスと別の回答のクラスを使用すると、次のinfix_ostream_iteratorようになります。

#include "infix_iterator.h"
#include "line"


int main() {
    auto rev_words = [](std::string const &in) -> std::string {
        std::istringstream b(in);
        std::ostringstream r;

        std::transform(std::istream_iterator<std::string>(b),
            std::istream_iterator<std::string>(),
            infix_ostream_iterator<std::string>(r, " "),
            [](std::string const &in){return std::string(in.rbegin(), 
                                                         in.rend());});
        return r.str();
    };

    std::transform(std::istream_iterator<line>(std::cin), 
        std::istream_iterator<line>(), 
        std::ostream_iterator<std::string>(std::cout, "\n"),
        rev_words);
    return 0;
}

はい、これはおそらく完全に機能的なスタイルに少し行き過ぎています。代わりに、次のようなことを行う方が間違いなく簡単です。

std::string line;
while (std::getline(std::cin, line)) {
    std::istringstream buffer(line);
    std::transform(std::istream_iterator<std::string>(buffer),
                   std::istream_iterator<std::string>(),
                   infix_ostream_iterator<std::string>(std::cout , " "), 
                   [](std::string const &in){return std::string(in.rbegin(), 
                                                                in.rend()););
    std::cout << "\n";
}
于 2012-06-22T05:54:59.550 に答える