Demetris
Demetris

Reputation: 1

Is there a better way to count substring occurrences within a string than char* and a loop?

I have this line:

const char *S1 = "AaA BbB CcC DdD AaA";

I think that this creates a pointer *S1, which is located a constant char type value and has the AaA BbB CcC DdD AaA value in it. Is that right?

If so, how can I read each character of this constant value and recognize how many times AaA occurs?

I was thinking of creating a loop that will copy each letter to a different cell and then 3 enclosed if statements, of which the first could check for A, the second for a and so one. And if those 3 are true I will increment a counter like so i++. Is that correct?

I think it's too complicated and it can be done with less code.

Upvotes: 0

Views: 150

Answers (3)

NetVipeC
NetVipeC

Reputation: 4432

The C++ way:

  • using std::string for string management, it provide a lot benefit, memory management, iterators, some algorithms like find.
  • using find method of std::string to search for the index of s1 where s2 begin, if s2 is not present in s1 (a dummy value std::string::npos is returned).

Code:

#include <iostream>

int main() {
    std::string s1("AaAaAaA");
    //std::string s1("AaA BbB CcC DdD AaA");
    std::string s2("AaA");

    int times = 0;
    size_t index = s1.find(s2, index);
    while (index != std::string::npos) {
        times++;
        index = s1.find(s2, index + 1);
    }

    std::cout << "Found '" << s2 << "' in '" << s1 << "' " 
              << times << " times" << std::endl;
}

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545518

Your fundamental approach is sound. However, it’s complex and doesn’t scale: what if you wanted to search for a word with more than three letters? Four ifs? Five ifs? Six …? Clearly that won’t do.

Instead, use two loops: one to go over the string you search in (the “haystack” or “reference”) and one over the string you search for (“needle” or “pattern”).

But luckily you don’t even have to do that, because C++ gives you the tools to search for the occurrence of one string in another, the find function:

#include <string>
#include <iostream>

int main() {
    std::string const reference = "AaA BbB CcC DdD AaA";
    std::string const pattern = "AaA";

    std::string::size_type previous = 0;
    int occurrences = 0;
    for (;;) {
        auto position = reference.find(pattern, previous);
        if (position == std::string::npos)
            break;
        previous = position + 1;
        ++occurrences;
    }

    std::cout << occurrences << " occurrences of " << pattern << '\n';
}

You can look up the individual types and functions in the C++ reference. For instance, you can find the std::string::find function there, which does the actual searching for us.

Note that this will find nested patterns: the reference “AaAaA” will contain two occurrences of “AaA”. If this isn’t what you want, change the line where the previous position is reassigned.

Upvotes: 1

Claudi
Claudi

Reputation: 5416

A simple way to achieve what you want is using strstr(str1, str2) function, which returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.

int count_sequence(const char *S1, const char *sequence) {
    int times, sequence_len;
    const char *ptr;

    times = 0;
    sequence_len = strlen(sequence);
    ptr = strstr(S1, sequence); //Search for the first sequence
    while(ptr != NULL) {
        times++;
        ptr = strstr(ptr + sequence_len, sequence); //search from the last position
    }
    return times;
}

Upvotes: 0

Related Questions