Tedy S.
Tedy S.

Reputation: 89

checking whether an element at a certain position exists (is set) in a STL vector

I'm writing an algorithm which takes random strings as input. I need to output the maximum length encountered and also how many words have that particular length. YES, I know I can use a different approach but I was thinking to store each string in a v[it's length] and if there are multiple strings with the same length then I would increment u[same length], then just output those values. How can I check whether v[length] is already set?

Sorry for possible bad English.

#include <iostream>
#include <vector>
#include <string>

using namespace std;

typedef unsigned short us;
typedef vector<string> vstr;
typedef vector<us> vus;

int main()
{
    string str;
    vstr v;
    vus u(50, 1);
    us len;

    while (cin >> str && str != "0")
    {
        len = str.length();

        //if there is an element set at v[len] then ++u[len] otherwise v[len] = str;
    }

    //bunch of other code

    return 0;
}

Upvotes: 0

Views: 666

Answers (3)

Andy Prowl
Andy Prowl

Reputation: 126582

YES, I know I can use a different approach

Honestly, I really believe you'd be better off following a different approach then.

You don't need a vector of lengths at all, nor a map, and neither you need a vector of strings unless you want to display those strings as well (here, I will assume you do need it). Finally, you don't even need to know the maximum length of those strings:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<std::string> words;

    std::string::size_type maxLength = 0;
    std::string str;
    while (std::cin >> str)
    {
        auto len = str.length();
        if (len == maxLength)
        {
            words.push_back(str);
        }
        else if (len > maxLength)
        {
            maxLength = len;

            words.clear();
            words.push_back(str);
        }
    }

    std::cout << "Max length: " << maxLength << std::endl;
    std::cout << "# of words with max length: " << words.size() << std::endl;
    std::cout << "Words with max length: " << std::endl;
    for (auto const& s : words) { std::cout << s << std::endl; }

    return 0;
}

Upvotes: 3

Jonathan Wakely
Jonathan Wakely

Reputation: 171501

A std::vector v has a length given by v.size(), and all elements in the range [0,v.size()) exist.

So an element exists at v[n] if v.size() > n

You can test for it either by checking the vector's length, or accessing the element with v.at(n) instead of v[n] because the at() function will throw an exception if the element doesn't exist (that is, if the length is not at least n)

The fact a std::vector contains an element at every index up to its length means it is not an efficient representation of a sparse array To represent a sparse array with one of the standard containers it is better to use std::map because it doesn't require elements to have contiguous keys.

Upvotes: 0

Tushar
Tushar

Reputation: 8049

This won't work unless you know the maximum length of any possible string beforehand. Let's call this maximum X. Then you can construct a vector of X ints, initialized to 0, and just increment the one you need using the subscript operator.

std::vector<int> counts(X, 0); // X ints, initialized to 0
for (const string str : v) {
    int length = str.size();
    try {
        counts.at(length)++;
    } catch (const std::out_of_range& oor) {
        // Your professor lied to you!
    }
}

The way I would approach this problem would be to use a map. Then you can just do the following:

std::map<int, int> counts;
for (const string str : v) {
    int length = str.size();
    ++counts[length];
}

counts[length] will create the element at [length] if it doesn't exist already, and will increment it if it already exists.

Upvotes: 3

Related Questions