2012-02-12 18 views
3

だから、私は4つのエレメンツ[文字列要素]を含むベクトルを持っているとしましょう。私は最初にベクトルをループし、次に各要素を通して、文字列[ループ] をループし、その単語に含まれる母音の数を数えます。ベクトルの各要素をループする

for(int i = 0; i < b.size(); i++) 
    { 
     for(int j = 0; j < b[i].size(); j++) 
     { 
     for(int v = 0 ; v < sizeof(vowels)/sizeof(vowels[0]); v++) 
      if(//blabla) 
     } 
    } 

ので、私の質問は、どのように各単語からiループは、私はb[i][j]はそれを行うための正しい方法であることを意味することができますか?

もしそうなら、このフォームは素晴らしいでしょうか? :

if(b[i][j] == vowels[v]) { 
//blabla 
} 

ありがとうございます。

+1

ほとんどの場合、次のようになります。if(b [i] [j] == vowels [v]) – alfasin

+1

なぜイテレータではないのですか? – Pubby

答えて

5

これについてもっと詳しく調べるには、C + +を学ぶことについて真剣に考えていなければなりません。索引やランダムアクセスを使わないで、高水準のSTL関数を使用してください。考えてみましょう:

あなたが書いたループは、これらの線にほぼ対応
#include <algorithm> 
#include <iostream> 
#include <map> 
#include <numeric> 
#include <set> 
#include <string> 
#include <vector> 

bool is_vowel(char s) { 
    static const char vowels[] = { 'a', 'e', 'i', 'o', 'u' }; 
    const char* vbegin = vowels; 
    const char* vend = vowels + sizeof(vowels)/sizeof(char); 
    return (std::find(vbegin, vend, s) != vend); 
} 

std::string::difference_type count_vowels(const std::string& s) { 
    return std::count_if(s.begin(), s.end(), is_vowel); 
} 

template <class T> void printval(const T& obj) { std::cout << obj << std::endl; } 

int main() { 
    std::vector<std::string> b; 
    b.push_back("test"); 
    b.push_back("aeolian"); 
    b.push_back("Mxyzptlk"); 

    std::vector<int> counts(b.size()); 
    std::transform(b.begin(), b.end(), counts.begin(), count_vowels); 
    std::for_each(counts.begin(), counts.end(), printval<int>); 

    int total = std::accumulate(counts.begin(), counts.end(), 0); 
    printval(total); 
    return 0; 
} 

std::transform(b.begin(), b.end(), counts.begin(), count_vowels); 
.. 
std::count_if(s.begin(), s.end(), is_vowel); 
.. 
std::find(vbegin, vend, s) 

これは、C++がIMO引っ張っ常にエレガントではない高レベルの機能/ジェネリックプログラミングのイディオムを使用しています。しかし、この場合は正常に動作します。

私が解決しようとしている問題の一部を解決するための解説については、Count no of vowels in a stringを参照してください。そこに表示されているさまざまな許容ループ/反復技術を見ることができます。

+0

いや、これは先進的な方法です。しかし、なぜ私の方法は良くないのですか?私はちょうど興味がある、母音を数えてそれらを印刷するコードの7行がありますが、この場合は7以上です。数量ではなく性能についてですか? – ddacot

+0

Nah、どちらもほぼ同じ性能を発揮し、あなたの方法は必ずしも悪くはありません。あなたはいくつかのインデックス変数を悩まさなければならず、自分自身で反復を管理する必要があります。そして、それは愚かな間違いが潜んでいるところです。また、高水準のものを読むことに慣れてしまうと、コードは、あなたがやろうとしていることをもう少し直接的に表現しているからです。 –

+0

また、#行のコードまで、私のコードスニペットには完全なコンテキストが添付されていて、この例が完成していることに注意してください。私はこのケースでどちらかというとほぼ同じサイズになると思いますが、中括弧を除いて、機能的なアプローチが実際にはもっとコンパクトになるかもしれないと思います。 (より高度な例については、かなり短くなる可能性があります)。そして、機能的なアプローチを進めていくうちに、あなたがしなければならない分解は、コードをよりクリーンで再利用可能にすることができます。 –

2

std::vector<T>は、T operator[](int)を定義する。これは、xの要素ix[i]経由でベクトルにアクセスできることを意味します。

std::stringchar operator[](int)と定義されており、文字列内のその位置にcharを返します。

あなたはxと呼ばれるstd::vector<std::string>を持っているのであれば、x[i][j]は、ベクターのi番目の位置にある文字列のj番目の文字を返します。

これは慣用的なC++の方法ではありません。最も一般的な方法はイテレータ(.begin().end()コール)です。しかし、ベクトルアクセスは一定の時間(文字列のように)であるため、それほど大きな問題ではありません。

+0

答えに感謝します。 – ddacot

+0

"...それは大したことではありません。" vector :: iteratorがポインタで実装されていることを考慮すると、最も基本的なプラットフォームである 'itrator :: operator ++()'は "ポインタaritmetic"であると考えていますwile int :: operator ++() ルーピングおよびインデックス作成のためにファームウェアで命令が実装されていることを考慮すると、ジェネリックではないものの、インデックスバージョン(イテレータバージョンとの関連)はさらに高速になります。 –

関連する問題