Discover string inside string without string library. h?

Asked

Viewed 424 times

1

My function needs to check if one string is contained in another and speak where the first place where the letter was equal occurred, but is always returning the size of the first string

What’s wrong with my implementation?

my code:

void str_conteudo( char str1[], char str2[])
{  
int i=0;
int y;

while(str1[i] != str2[i] )
{
    if (str2[i] != str1[i])
    {
        y=i;
    }
    i++;

}

if(y>0)
printf("Indice do primeiro caractere que contem a string 2: %d ", y);
else
printf("A string 2 nao esta contida na string 1. \n");

}
  • The problem you’re trying to solve is called substring. Searching for substring search algorithms and understanding them in depth will help you a lot

1 answer

3


In its implementation it has the logic that goes through the letters of the main sentence, but the logic that sees if each letter is equal to the letters of the second string is missing.

Trying to make the most of your logic can do so:

void str_conteudo( char str1[], char str2[]) {
    int i=0,j, k;
    int y = -1; //y começa a -1, pois estava sem valor de inicio

    while(str1[i] != '\0') { // enquanto a string principal não termina
        if (str2[0] == str1[i]) { //se a letra em que vai é igual à 1a letra da substring
            //percorrer enquanto ambas as letras são iguais e até ao fim da substring
            for (j=i+1, k=1; str1[j]!='\0' && str2[k]!='\0' && str1[j] == str2[k];++j,k++);

            if (str2[k] == '\0'){ //se a segunda foi até ao fim então achou
                y = i;
                break;
            }
        }
        i++;
    }

    if(y>=0) // >= 0 e não > 0
        printf("Indice do primeiro caractere que contem a string 2: %d \n", y);
    else
        printf("A string 2 nao esta contida na string 1. \n");
}

Testing

str_conteudo ("Frase de teste","de"); //6 
str_conteudo ("Frase de teste","teste"); //9
str_conteudo ("Frase de teste","Frase"); //0
str_conteudo ("Frase de teste","cuFra"); // não contem
str_conteudo ("Frase de teste","testem"); // não contem

See these tests in Ideone

The biggest difference to the code you had is in what was added inside the if in the while.

It’s never a good idea to write or read content. They should only return the result, giving freedom to those who call to do what they want with this result. Besides if that has in the while nor would it be necessary to change a few more things.

Taking these points that I mentioned I was switching function to something like:

int str_conteudo( char str1[], char str2[]) {
    int i=0, j, k;
    for(i = 0; str1[i] != '\0'; ++i) {
        for (j = i,k = 0;str1[j]!= '\0' && str2[k] != '\0' && str1[j] == str2[k]; ++j,k++);
        if (str2[k] == '\0'){
            return i;
        }
    }
    return -1;
}

Of course I could have switched the iteration and access to pointer syntax that would be shorter, but I chose to keep it with index to make the solution comparable and similar to yours.

Now the tests have to show the value obtained by the function, which returns -1 whenever you can’t find the substring:

printf("%d\n", str_conteudo ("Frase de teste","de")); //6
printf("%d\n", str_conteudo ("Frase de teste","teste")); //9
printf("%d\n", str_conteudo ("Frase de teste","Frase")); //0
printf("%d\n", str_conteudo ("Frase de teste","cuFra")); //-1
printf("%d\n", str_conteudo ("Frase de teste","testem")); //-1

See these tests also on Ideone

Just for reference, I leave the same example of top implemented with pointer notation, although exactly the same solution:

int str_conteudo( char *str1, char *str2) {
    char *curr1 = str1, *s1, *s2;
    while(*curr1){
        for(s1 = curr1, s2 = str2; *s1 && *s2 && *s1 == *s2; ++s1, ++s2);
        if (!*s2) return curr1 - str1;
        curr1++;
    }
    return -1;
}

As a final note, the logic you are implementing is that the native function strstr provides.

  • 1

    I’m not gonna do one right now, but if I were to exemplify it, I would loop in a state machine. A pointer on the needle, another on the haystack, and would advance as the state (searching, comparing, resetting)

  • @And come back later with the pointer back in case you don’t find one full match ?

  • yes, still it would be more optimized in cases that did not find partial or found integer - only cases of Rewind would be partial incomplete - If you want to call 2 loops, would be "2 occasional loops" :)

  • @Bacco Technically it would be a loop, although done manually :D. But yes it would not be 2 loops written in the form of for/while. It is certainly an interesting idea. I will refract so as not to hurt susceptibilities! p

  • Remembering that I am speaking as exercise. In practice I think I would not implement this for real use kkk. By the way, I saw a very cool search optimized multiple strings in a single step, this yes I want to understand and do for real use.

  • @Isac this alternative of your answer is the implementation naïve, with time O(|str1| * |str2|); can be optimized for O( (|str1| - |str2|) * |str2|). That is, this alternative will always be quadratic. Already the idea of Bacco is O(|str1| + |str2|)

  • 1

    @Jeffersonquesado do not forget the Rewind in the case of mine, if it is not done correctly it will lose a substring in some situations. (had exemplified wrong here)

  • It seems to me that the complexity is the same, because in the second example I have for no letter equal my solution is O(|str1|) which would be equal to the example of Bacco. Why let the pointer go forward and then walk with it back is basically the Inner for that I have but written otherwise. Unless I’m visualizing his solution at 100%. For all intents and purposes, in most cases my inner for functions as a if.

  • @Bacco the KMP that uses an FSA does not need a Rewind walking in the str1/large string that can contain str2. It solves in a stride, and assemble this automaton based on the str2 I think it’s linear.

  • @Jeffersonquesado I keep thinking that to find "ababac" within "xxxxabababacxxx" without Rewind does not work, right? Pq is contained, but in the first step will confuse the first 5 characters after x.

  • @Bacco does, and when I was a programming athlete, I did it in a stride. Let me study and I’ll post the answer here, because I can’t remember how xD is

  • I’ll see later, because now I really need to sleep. I want to make one of multiple strings and high performance, pq is to replace a LIKE in Sqlite in an application of mine.

  • If you have these solutions then post to share knowledge! That I was curious.

Show 8 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.