2

I have a string of items (see code). I want to say when a specific item from that list is found. In my example I want the output to be 3 since the item is found after the first two items. I can print out the separate items to the console but I cannot figure out how to do a count on these two items. I think it is because of the while loop... I always get numbers like 11 instead of two separate 1s. Any tips? :)

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


int main() {

string items = "box,cat,dog,cat";
string delim = ",";
size_t pos = 0;
string token;
string item1 = "dog";
int count = 0;
`;
 

while ((pos = items.find(delim)) != string::npos)
{
    token = items.substr(0, pos);
    if (token != item1)
    {
        
            cout << token << endl;  //here I would like to increment count for every   
                                    //item before item1 (dog) is found     
         items.erase(0, pos + 1);
        
    }
    else if (token == item1)

    return 0;

    
}


    return 0;      //output: box cat
}
Bis Andi Grenzen
  • 157
  • 1
  • 10
  • 2
    Unrelated, but if you have `if (condition) { ... } else if (not_condition) { ... }` then that's exactly like `if (condition) { ... } else { ... }`. No second `if` needed. – Some programmer dude Aug 04 '20 at 10:50
  • 2
    As for your problem, unless `"dog"` is the first sub-string found, there will *always* be an "item" before `"dog"`. So you can simplify it as incrementing `count` *when you find `"dog"`*. – Some programmer dude Aug 04 '20 at 10:51
  • But what if “dog“ shows up twice in the string? Like: tree, dog, house, cat, dog... and I just want to say that I found dog after item 1. (That‘s why I used the else condition to break the while loop if that is the case. – Bis Andi Grenzen Aug 04 '20 at 10:58
  • 1
    Add a special case for when `"dog"` is the first item. Perhaps also add a case for when you have multiple consecutive `"dog"` items. – Some programmer dude Aug 04 '20 at 11:04

2 Answers2

1

I replaced your search algorithm with the method explode, that separates your string by a delimiter and returns a vector, which is better suited for searching and getting the element count:

#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

std::vector<std::string> explode(const std::string& s, char delim)
{
  std::vector<std::string> result;
  std::istringstream iss(s);
  
  for (std::string token; std::getline(iss, token, delim); )
  {
    result.push_back(std::move(token));
  }
      
  return result;
}


int main() 
{
  std::string items = "box,cat,dog,cat";
  std::string item1 = "dog";
  char delim = ',';
  
  auto resultVec = explode(items, delim);
  
  auto itResult = std::find_if(resultVec.begin(), resultVec.end()
              , [&item1](const auto& resultString)
              {
                return item1 == resultString;
              });
                
  if (itResult != resultVec.end())
  {
      auto index(std::distance(resultVec.begin(), itResult) + 1); // index is zero based
                
      std::cout << index;
  }
                
  return 0;
}

By using std::find_if you can get the position of item1 by iterator, which you can use with std::distance to get the count of elements that are in front of it.

Credits for the explode method go to this post: Is there an equivalent in C++ of PHP's explode() function?

SAlex
  • 361
  • 2
  • 10
  • Interesting code! Thank you. A couple of new functions which I haven‘t used before. Why do I need the utility header file? I‘m going to try and understand the different steps next... – Bis Andi Grenzen Aug 04 '20 at 12:31
  • 1
    Oh, you are right, utility is not required, as well as the second string include :D. I'll edit my reply – SAlex Aug 04 '20 at 12:49
1

There are many ways to Rome. Here an additional solution using a std::regex.

But main approach is the same as the accepted answer. Using modern C++17 language elements, it is a little bit more compact.

#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <vector>

const std::regex re{ "," };

int main() {

    std::string items{ "box,cat,dog,cat" };

    // Split String and put all sub-items in a vector
    std::vector subItems(std::sregex_token_iterator(items.begin(), items.end(), re, -1), {});

    // Search and check if found and show result
    if (auto it = std::find(subItems.begin(), subItems.end(), "dog"); it != subItems.end())
        std::cout << "Found at position: " << std::distance(subItems.begin(), it) + 1 << '\n';
    else 
        std::cout << "Not found.\n";
    return 0;
}
A M
  • 14,694
  • 5
  • 19
  • 44