Poriferous
Poriferous

Reputation: 1582

Parse string for a word

I want to create a program that parses a string and does something if a word within the string is found. Here's what I got:

size_t strPos;
string str = "";

switch(str.find(str, strPos)
{
   case 'APPLE':
   cout << "You are eating an apple!" << endl;
   break;

   case 'ORANGE':
   cout << "You are eating an orange!" << endl;
   break;

   default:
   cout << "You're eating something... that's for sure!" << endl;
   break;

   // etc...
};

The problem is that this code runs but won't work. How can I parse a string and search for a word like in the above? I figure using a switch statement isn't the right thing to be using.

Upvotes: 0

Views: 344

Answers (5)

lebed2045
lebed2045

Reputation: 468

If I understood your questions correctly, you need something like that:

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

int main() {
    string text = "APPLE enter your source code or insert template or sample or your template";
    stringstream ss; // we need this for easy way to parse the input text
    ss.str(text);
    for (string word; ss >> word;) {
        cout << word << endl; // or do what ever you want with word
        if (word == "APPLE") {
            cout << "found an APPLE" << endl;
        } else if (word == "ORANGE") {
            //...
        }
    }
    return 0;
}

You can play around this code here http://ideone.com/Rsr9ya

Upvotes: 0

Christophe
Christophe

Reputation: 73376

You could use regex for complex pattern matching:

string s = "An apple a day keeps the doctor away and may be oranges too"; 

regex what("APPLE|ORANGE|etc", regex_constants::icase);  // what to search for
smatch sm;       
while (regex_search(s, sm, what)) {   // loop through found occurences 
    cout << "Found: " << sm.str() << endl;
    s = sm.suffix().str();
}

This will print:

found apple
found orange

Of course, instead of the cout, you could have an if clause:

if (sm.str()=="apple") {
    //...
} else if (sm.str()=="orange") {
    //...
} 

And if you'd prefer the switch, you coud create a map<string, int> m; to associate each string you're looking for to an int, and you would then use this int in a switch(m[sm.str()])

Upvotes: 0

Thomas Matthews
Thomas Matthews

Reputation: 57698

You will have to use a lookup table, a std::map or an if-else if-else ladder.

Each data structure depends on what you want to associate with your strings:

  • Lookup table -- functions or data. If functions, they must have the same signature.
  • std::map -- functions or data. If functions, they must have the same signature.
  • If-else ladder -- Very flexible.

Lookup Table

This involves creating an entry or record structure and searching for the "key" value. Once the "key" is found, you have access to the function pointer or data associated with the key.

struct  Lookup_Entry
{
  std::string item;    // The "key"
  std::string phrase;  // The "value"
};
Lookup_Entry lookup_table[] =
{
  { "APPLE", "You ate an apple!\n"},
  { "ORANGE", "You ate an orange!\n"},
  { "ROCK", "You should not eat rocks.\n"},
};

Using the std::map

std::map< std::string, std::string> lookup_table;
lookup_table["APPLE"] = "You are eating an apple.\n";
lookup_table["ORANGE"] = "You are eating an orange.\n";
lookup_table["ROCK"] = "You broke some teeth eating the rock.\n";

if-else if-else ladder

if (text == "APPLE"}
{
  cout << "You ate an apple.\n";
}
else if (text == "ORANGE")
{
  cout << "You ate a yummy orange.\n";
}
else
{
  cout << "You ate something unknown, hope you don't get sick.\n";
}

Upvotes: 0

InsertMemeNameHere
InsertMemeNameHere

Reputation: 2433

Aside from some syntax errors, your code has a few problems.

In C++, you cannot use string literals in switch statements.

case 'APPLE':

Literal constants delimited by single quotes are multi-character literals. This creates an int where the character values are coalesced into a single value in an implementation-defined manner.

To do any sort of pattern matching in C++, I recommend using std::regex.

using namespace std;

regex r0{"[a-zA-Z]*"};

string str = "APPLE ORANGE PEAR";

sregex_iterator ritr{str.begin(), str.end(), r0};
sregex_iterator rend;

while(ritr != rend){
    auto s = ritr->str();
    if(s == "APPLE"){
        cout << "I found an apple!" << endl;
    }
    if(s == "ORANGE"){
        cout << "I found an orange!" << endl;
    }
    if(s == "PEAR"){
        cout << "I found a pear!" << endl;
    }
    ++ritr;
}

You can extend this by using an std::map to map matched strings to anything (a functor would be nice).

Upvotes: 1

Chris
Chris

Reputation: 1558

There are several issues.

  1. In C++ you cannot use switch on strings.

  2. The start position of your search (strPos) is uninitalized in your code

  3. Even if it is 0,

    str.find(str, strPos)
    

    returns the start position of the string in itself (= 0) see string::find

  4. 'APPLE' isn't a string, "APPLE" would be.

As also stated in the comments while I was typing this answer, use

    if (str == "APPLE")
    {...}
    else if (str == "ORANGE")
    {...}
    else
    {...}

Edit:

  1. As Ken White wrote in the comment, str is always initialized to an empty string.

Upvotes: 2

Related Questions