Search code examples
c++arraysstringsearchcstring

Most efficient way to search array of string objects in c++?


I've been searching for some more information on this topic, and can't seem to find the answer I'm looking for, so I hope you can help!

Part of an assignment I'm working on is to write a program that searches an array of strings (address book), and returns matches if a full or partial match is found. I'm able to do it easily using an array of C-Strings, with the strstr() function running through a for loop and setting the pointer to the result of running the user input keyword into the array (see below).

My question is, how would I be able to do this, if at all, utilizing String objects? I also need to take into consideration there being more than one possible match. Is this the most efficient way of working this program out as well? I've already submitted my working version, I'm just curious as to some other methods to accomplish the same task!

#include <iostream>
#include <cstring>
using namespace std;

int main()
{

  bool isFound = false;         // Flag to indicate whether contact is found
  const int SIZE = 11;          // Size of contacts array
  const int MAX = 50;           // Maximum characters per row
  char contacts[SIZE][MAX] = { 
                                "Jig Sawyer, 555-1223",
                                "Michael Meyers, 555-0097",
                                "Jason Vorhees, 555-8787",
                                "Norman Bates, 555-1212",
                                "Count Dracula, 555-8878",
                                "Samara Moran, 555-0998",
                                "Hannibal Lector, 555-8712",
                                "Freddy Krueger, 555-7676",
                                "Leather Face, 555-9037",
                                "George H Bush, 555-4939",
                                "George W Bush, 555-2783"
                              };
  char *ptr = NULL;             // Pointer to search string within contacts
  char input[MAX];              // User search input string


  // Get the user input
  cout << "Please enter a contact to lookup in the address book: ";
  cin.getline(input,MAX);

  // Lookup contact(s)
  for (int i=0; i<SIZE; i++)
  {
    ptr = strstr(contacts[i], input);
    if (ptr != NULL)
      {
        cout << contacts[i] << endl;
        isFound = true;
      }
  }

  // Display error message if no matches found
  if (!contactFound)
    cout << "No contacts found." << endl;

  return 0;
} 

As you can tell, I like horror movies :)


Solution

  • An alternative would be to use regular expressions for string search. Now there's a lot of info out there and I'll just be providing a simple example where you try to match a subrange of the records (addresses) with a word2Search (which I've hardcoded to avoid cluttering the example).

    I'm also using (a technique already mentioned in the comments) a preprocessing step where the array is sorted. Beware of two things :

    • The sorting is done to enable a fast searching method, ie binary search (implemented with lower_bound upper_bound here)

    • If the word you are searching is not at the beginning of a record, there is no point in sorting the records since you won't be able to find a valid range (here it ite) to search into (eg if you search for the numbers, the sorting of the string would be done in lexicographical comparison between strings, so it wouldn't be any good for locating 555 among strings beginning with M J and so on)

    Explanation in the comments:

    int main()
    {
        // 1. Minor change - an array of strings is used
        string contacts[] = { 
            "Jig Sawyer, 555-1223",
            "Michael Meyers, 555-0097",
            "Jason Vorhees, 555-8787",
            "Norman Bates, 555-1212",
            "Count Dracula, 555-8878",
            "Samara Moran, 555-0998",
            "Hannibal Lector, 555-8712",
            "Freddy Krueger, 555-7676",
            "Leather Face, 555-9037",
            "George H Bush, 555-4939",
            "George W Bush, 555-2783"
        };
        // 2. The array is sorted to allow for binary search
        sort(begin(contacts), end(contacts));
        // 3. Example hard coded a word to search 
        string word2Search = "George";
        // 4. A regular expression is formed out of the target word
        regex expr(word2Search);
        // 5. Upper and lower bounds are set for the search
        char f = word2Search[0];
        std::string val1(1, f);
        std::string val2(1, ++f);
        // 6. Perform the search using regular expressions
        for (auto it(lower_bound(begin(contacts), end(contacts), val1)), 
            ite(lower_bound(begin(contacts), end(contacts), val2)); it != ite; ++it)
        {
            if (regex_search(it->begin(), it->end(), expr)) {
                cout << *it << endl;
            }
        }
    
        return 0;
    }