遍历向量中的每个元素

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)
       }
    }

所以我的问题是,如何遍历每个单词,我的意思是b[i][j]是正确的方法吗?
如果是的话,这种形式将非常有效吗?:
if(b[i][j] == vowels[v]) {
//blabla
}

thanks.


1
几乎,你的意思是:如果(b [i] [j] == vowels [v]) - Nir Alfasi
2个回答

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++并不总是能够优雅地实现它。但在这种情况下,它可以很好地工作。

请参见计算字符串中元音字母数量,其中列出了我认为您正在尝试解决的问题的一些解决方案。你也可以看到各种可接受的循环/迭代技巧。


是的,我现在明白了,这是一种高级方法。但是为什么我的方法不好呢?我只是好奇,有大约7行代码来计算元音并将它们打印出来,但在这种情况下,代码行数更多。这是关于性能而不是数量吗? - ddacot
不,两种方法的性能可能差不多,而且你的方法并不一定不好。但是,你必须同时处理几个索引变量并自己管理迭代,这就是愚蠢错误可能潜入的地方。此外,一旦你习惯了阅读更高级别的内容,我认为你会发现它更容易维护,因为代码更直接地表达了你试图做什么。 - Owen S.
此外,就代码行数而言,请注意我的代码片段附有完整的上下文并且展开了示例。我认为在这种情况下,两种方式的代码大小差不多,但是除去大括号和包含语句,我认为函数式方法实际上可能会更加紧凑。(对于更高级的示例,它可能会变得更短)。随着您使用函数式方法,您可能还会发现,您被迫进行的分解使您的代码更清晰、更具可重用性。 - Owen S.

2

std::vector<T> 定义了 T operator[](int)。这意味着您可以通过 x[i] 访问向量 x 的第 i 个元素。

std::string 定义了 char operator[](int),它返回字符串中该位置的 char

因此,如果您有一个名为 xstd::vector<std::string>x[i][j] 将返回向量中第 i 个位置的字符串的第 j 个字符。

这不是 C++ 中惯用的方法 - 最常见的方法是使用迭代器(调用 .begin().end())。但由于向量访问和字符串字符访问都是常数时间,所以这并不是一个很大的问题。


"...这并不是什么大问题。"考虑到vector::iterator是使用指针实现的,并且在大多数基础平台上,iterator::operator++()是"指针算术",而int::operator++()是寄存器立即指令。考虑到一些处理器具有用于循环和索引的固件实现的指令,相对于迭代器版本,索引版本虽然不是通用的,但甚至可能更快! - Emilio Garavaglia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接