Hey all!

I'm trying to figure out how to check if an element already exists in a vector.

EXAMPLE:
Elements in the vector are: "Dog", "Cat", "Fish", "Bird"

If a user tries to add (case ignored) "Dog", "dog" or any other variation, I want it to spit out and error stating it already exists.

If a user tries to add (case ignored)"Elephant", I want it to properly add it to the vector in all lowercase letters.
The vector will be sorted alphabetically after all additions have been made.

Essentially, this is what I have but as you can see is incomplete. I've got myself (and brain) stuck into a logical loop.

vector<string> wordDictionary;

void addWord(string word) {
	int i;
	if (!wordDictionary.empty()) {
		for (i = 0; i < wordDictionary.size(); i++) {
			string tmpString = wordDictionary[i];
			if (strcmpi(tmpString.c_str(), word.c_str()) == 0) {
				if
				break;
			}
			wordDictionary.push_back(word);
		}
	} else {
		wordDictionary.push_back(word);
	}
}

any ideas?

Edited 6 Years Ago by SacredFootball: n/a

Narue is right, but if you do want to use a vector for some reason, std::vector has a find() function that does exactly what you're looking for. Here is the example I have:

void TestFind()
{
  std::vector<unsigned int> V(10);
  
  for(unsigned int i = 0; i < 10; i++)
  {
    V[i] = 10*i;
    std::cout << V[i]   << " ";
  }
  
  std::cout << std::endl;
  
  std::vector<unsigned int>::iterator it = find(V.begin(), V.end(), 70);
  
  if(it == V.end())
  {
      std::cout << "Could not find 70 in the vector"  << std::endl;
  }
  else
  {
    std::cout << "The number 70 is located at index " << it - V.begin() << std::endl;
  }
}

Hope that helps,

Dave

Narue is right, but if you do want to use a vector for some reason, std::vector has a find() function that does exactly what you're looking for. Here is the example I have:

void TestFind()
{
  std::vector<unsigned int> V(10);
  
  for(unsigned int i = 0; i < 10; i++)
  {
    V[i] = 10*i;
    std::cout << V[i]   << " ";
  }
  
  std::cout << std::endl;
  
  std::vector<unsigned int>::iterator it = find(V.begin(), V.end(), 70);
  
  if(it == V.end())
  {
      std::cout << "Could not find 70 in the vector"  << std::endl;
  }
  else
  {
    std::cout << "The number 70 is located at index " << it - V.begin() << std::endl;
  }
}

Hope that helps,

Dave

As far as I can tell at this point in time, vectors are going to cover everything I need. I'm trying to use

std::vector<unsigned int>::iterator it = find(V.begin(), V.end(), 70);

but it's giving me a compile error on the 'find'

It says it's undefined. I have the following include and namespace:

#include <iostream>
#include <vector>
#include <iterator>
#include "StdAfx.h"
#include "Dictionary.h"

using namespace std;

As far as I can tell at this point in time, vectors are going to cover everything I need.

Yes, but will they cover everything you need in the most efficient and productive manner? Clearly you need to take an extra step that isn't directly supported (checking for duplicates), which should raise red flags about your choice of data structure.

I can use an array to do damn near anything, but there are many cases where that would be the height of stupidity.

Oh, you need to include <algorithm> for find. It's neither a member function of std::vector nor tied to std::vector.

Edited 6 Years Ago by Narue: n/a

Yes, but will they cover everything you need in the most efficient and productive manner? Clearly you need to take an extra step that isn't directly supported (checking for duplicates), which should raise red flags about your choice of data structure.

I can use an array to do damn near anything, but there are many cases where that would be the height of stupidity.

Oh, you need to include <algorithm> for find. It's neither a member function of std::vector nor tied to std::vector.

Sorry, I should have explained better. When I said they cover everything I need, I also meant to imply that as far as I know, they'll be the best structure that I know of. I'm still a beginner.

The array/list/set/vector/whatever needs to be able to grow and shrink on the fly, sort and be able to check for duplicates. My limited knowledge only knows that vectors can do the grow/shrinking functionality as well as the others.

Is there a better, more efficient and recommended way to go about it? I'd like to develop good programming habits from the start :D

Thanks for all your help so far guys :)

Ah, I forgot to tell you to

#include <algorithm>

hmmm... doesn't seem to fix the problem. I've tried adding it to different locations in the include section but still no luck.

This compiles fine for me:

#include <iostream>
#include <vector>
#include <algorithm>

int main(int argc, char* argv[])
{
  std::vector<unsigned int> V(10);
  
  for(unsigned int i = 0; i < 10; i++)
  {
    V[i] = 10*i;
    std::cout << V[i]   << " ";
  }
  
  std::cout << std::endl;
  
  std::vector<unsigned int>::iterator it = find(V.begin(), V.end(), 70);
  
  if(it == V.end())
  {
      std::cout << "Could not find 70 in the vector"  << std::endl;
  }
  else
  {
    std::cout << "The number 70 is located at index " << it - V.begin() << std::endl;
  }
  
  return 0;
}

hmmm... doesn't seem to fix the problem. I've tried adding it to different locations in the include section but still no luck.

Oops. It's a different error.

"No suitable user-defined conversion ... exists."
researching this.

I don't know what you mean by "wacky casing", but correct, it does all of the checking for you. insert() just does nothing if the element already exists.

I don't know what you mean by "wacky casing", but correct, it does all of the checking for you. insert() just does nothing if the element already exists.

Ah, I see. by "Wacky Casing" I meant something along the lines of "eLEphAnt".
I though a set would only check for identical casing or something.

Thanks for your help guys! I'll get to work on the sets ASAP :)

It definitely will NOT work with different cases. It would only think the element already exists if EXACTLY that element exists.

So if you have already added "dog", and then you try to add "Dog", you will now have BOTH "dog" AND "Dog" in the set.

Dave

It definitely will NOT work with different cases. It would only think the element already exists if EXACTLY that element exists.

So if you have already added "dog", and then you try to add "Dog", you will now have BOTH "dog" AND "Dog" in the set.

Dave

That's what I need it to do. I don't want multiples of the same thing, just different cases. Looks like I'm going to have to write a string compare to ignore case then try to add it to the set.

Or maybe I'll just force all input to the set to be lowercase/uppercase. I think I like that idea better.

Note that std::set is also naturally sorted without any effort on your part. You mentioned the ability to sort as a requirement.

I don't want multiples of the same thing, just different cases.

You can supply a custom comparison. Very trivial:

#include <cstring>
#include <iostream>
#include <set>
#include <string>

struct compare
{
    bool operator()(const std::string& a, const std::string& b)
    {
        return stricmp(a.c_str(), b.c_str());
    }
};

int main()
{
    typedef std::set<std::string, compare> set_t;

    set_t x;

    x.insert("test");
    x.insert("Test");
    x.insert("tEst");
    x.insert("teSt");
    x.insert("tesT");

    set_t::const_iterator it = x.begin();
    set_t::const_iterator end = x.end();

    while (it != end)
    {
        std::cout<< *it++ <<'\n';
    }
}
This article has been dead for over six months. Start a new discussion instead.