2

OK, so I was looking for an algorithm that could help me find a string within a substring. The code I was using before was from a similar question but it doesn't do it.

// might not be exposed publicly, but could be
int index_of(string const& haystack, int haystack_pos, string const& needle) {
  // would normally use string const& for all the string parameters in this
  // answer, but I've mostly stuck to the prototype you already have

  // shorter local name, keep parameter name the same for interface clarity
  int& h = haystack_pos;

  // preconditions:
  assert(0 <= h && h <= haystack.length());

  if (needle.empty()) return h;
  if (h == haystack.length()) return -1;
  if (haystack.compare(h, needle.length(), needle) == 0) {
    return h;
  }
  return index_of(haystack, h+1, needle);
}

int index_of(string haystack, string needle) {
  // sets up initial values or the "context" for the common case
  return index_of(haystack, 0, needle);
}

this doesn't return the start index of "el" on the string "hello" and I can't figure it out.

EDIT: OK, let me show you a bit more of the code including some real-life examples: I'm trying to analyze a string that is a path to a file I want to sort in my filesystem. An input example is this:

input:/media/seagate/lol/Sons.of.Anarchy.S04.720p.HDTV.x264/Sons.of.Anarchy.S04E01.720p.HDTV.x264-IMMERSE.mkv

when I try to parse this string to get the name of the by detecting the presence of SxxExx,I look for "s0","S0", etc (I know it's not the best implementation I was just trying to see if it worked and look at the code later). So when I use that input, what I get on the output is:

input:/media/seagate/lol/Sons.of.Anarchy.S04.720p.HDTV.x264/Sons.of.Anarchy.S04E01.720p.HDTV.x264-IMMERSE.mkv

aux: 0p.HDTV.x264-IMMERSE.mkv

input:/media/seagate/lol/Sons.of.Anarchy.S04.720p.HDTV.x264/Sons.of.Anarchy.S04E01.720p.HDTV.x264-IMMERSE.mkv

aux: 1.720p.HDTV.x264-IMMERSE.mkv

input:/media/seagate/lol/Sons.of.Anarchy.S04.720p.HDTV.x264/Sons.of.Anarchy.S04E01.720p.HDTV.x264-IMMERSE.mkv

aux: 264-IMMERSE.mkv

intended output for aux: S04E01.720p.HDTV.x264-IMMERSE.mkv

So as you can see it's just looking for any char that is in the string and stops, which also accounts for the multiple valid "found"s which should've been just the one.

the full code where I'm trying to use this is:

bool StringWorker::isSeries(size_t &i) {

    size_t found1, found2, found3, found4, found5, found6;
    found1 = input->find_last_of("S0"); //tried several find functions including the
    found2 = input->find_last_of("S1"); //index_of() mentioned above in the post
    found3 = input->find_last_of("S2");
    found4 = input->find_last_of("s0");
    found5 = input->find_last_of("s1");
    found6 = input->find_last_of("s2");

    if (found1 != string::npos) {
        if (input->size() - found1 > 6) {
            string aux = input->substr(found1, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found1;
                return true;
            }
        }
    }
    if (found2 != string::npos) {
        if (input->size() - found2 > 6) {
            string aux = input->substr(found2, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found2;
                return true;
            }
        }
    }

    if (found3 != string::npos) {
        if (input->size() - found3 > 6) {
            string aux = input->substr(found3, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found3;
                return true;
            }
        }

    }
    if (found4 != string::npos) {
        if (input->size() - found4 > 6) {
            string aux = input->substr(found4, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found4;
                return true;
            }
        }

    }
    if (found5 != string::npos) {
        if (input->size() - found5 > 6) {
            string aux = input->substr(found5, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found5;
                return true;
            }
        }

    }
    if (found6 != string::npos) {
        if (input->size() - found6 > 6) {
            string aux = input->substr(found6, input->size());
            cout << "input:" << *input << endl;
            cout << "aux: " << aux << endl;
            if (isalpha(aux.at(0)) && isdigit(aux.at(1)) && isdigit(aux.at(2))
                    && isalpha(aux.at(3)) && isdigit(aux.at(4))
                    && isdigit(aux.at(5))) {
                i = found6;
                return true;
            }
        }

    }

    return false;

}

Can you see anything wrong here?

6
  • 7
    What's wrong with std::string::find? Commented Nov 22, 2012 at 8:43
  • 1
    What's wrong with std::search? Commented Nov 22, 2012 at 8:44
  • Works for me. You must be using the function wrongly. Post a complete program. Commented Nov 22, 2012 at 8:44
  • @john It looked correct to me as well. Except that it's a good example of where recursion is not a good solution. (Imagine looking for a substring in a string of a couple of million characters.) And he could improve the end condition by using h > haystack.size() - needle.size(); you can't find a match if the string you're looking at is smaller than the substring you're trying to match. Commented Nov 22, 2012 at 8:48
  • 1
    @JackTakahashi As everyone is telling you, you should use string::find. But also there is no reason your index_of function wouldn't work as well. Since you can't get either method to work you must be doing something else wrong. Something that isn't in the code above. Try found1 = input->find("S0"); again, and if it's still not working try a debugger. Find out what is really going wrong, because it's not what you think it is. Commented Nov 23, 2012 at 7:40

3 Answers 3

6

Why don't you use the find() method of std::string -> link.

Sign up to request clarification or add additional context in comments.

3 Comments

because the find() method of std::string when passed a string "el" will return the first occurrence of "e" even if not followed by "l", which leads to error.
@JackTakahashi I don't think so
Check out the example I edited the original post with. You'll see what I mean.
3

This code returns the index through index = sub_str.find("el"):

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

int main ()
{
  string sub_str="abc def ghi jk lmnop  hello";

  string sub_str2;
  size_t index;


  index = sub_str.find("el");     
  sub_str2 = sub_str.substr (index);   

  cout<<"index = "<<index<<"\n";
  cout<<sub_str2<<"\n";

  return 0;
}

Comments

0

For finding a substring and its index in a string you can try this out -

int find_sub(const std::string& mstring,sub)
{
  int lensub=sub.length(),len=mstring.length(),f=0,pos;
  std::string b="";
  for(int i=0;i<len-lensub;i++)
  {
    for(int j=i,k=0;j<i+lensub;j++,k++)
      b[k]=mstring[j];
    if(b.compare(sub)==0)
    {
      f=1;
      pos=i;
      break;
    }
  } 
  if(f==1)
    cout<<"substring found at: "<<pos+1;
  else
    cout<<"substring not found!";
  return f;
}

You also check how many times substring appears by removing break; and increasing value of f every time. Also get their indexes by converting pos to an array.

4 Comments

The OP uses std::string and the question is tagged C++. If you really want to help, try to,understand why the OP code is wrong.
also the question is three years old
@manuell I thought my code could be converted to be usable with std::string anyway I edited it. I used arrays because I am not so much familiar with std::string. And what do you mean by "is tagged C++"? I actually wrote a c++ code.
yeah I had not seen that it was 3years old.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.