Program in C that returns the number of similar characters between two strings without counting a letter multiple times

Viewed 64

I a currently trying to make a program in C to return the number of similar characters between two strings, but without counting a letter multiple times.

Checking if two strings are exactly the same too.

For example with "week" and "weak", it should return 3 because the letters 'w', 'e', and 'k' are in both words.

The size of the two strings are 4 only.

I made the "contains" function to check if we didn't already compared a character, for example with "test" and "tast" got 2 "t", so it was returning more than expected.

For now my code, seems to work but not correctly and I can't understand why...

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define STRLEN 4

bool contains(char tab[], char c){
    for(int i=0; i<STRLEN; i++){
        if(tab[i] == c){
            return 1;
        }
    }
    return 0;
}

int likeness(char* password, char* wordchosen) {

    if(strlen(password)!=STRLEN && strlen(wordchosen)!=STRLEN) {
        return -1;
    }

    if(!strcmp(password, wordchosen)) {
        return 4;
    }

    int like = 0;
    char found[STRLEN];

    for(int i=0; i<STRLEN; i++) {
        for(int j=0; j<STRLEN; j++) {
            /*printf("%c : %c\n", password[i], wordchosen[j]);
            printf("\n");*/
            if(password[i] == wordchosen[j] && !(contains(found, wordchosen[j]))) {
                like++;
            }
        }
        found[i] = password[i];
    }

    return like;
}

int main() {
    printf("week and week = %d\n", likeness("week", "week")); // should be 4 (same word even if only 3 (w, e, k))
    printf("test and tast = %d\n", likeness("test", "tast")); // should be 2 (t, s)
    printf("week and weak = %d\n", likeness("week", "weak")); // should be 3 (w, e, k)
    printf("snet and sent = %d\n", likeness("snet", "sent")); // should be 4 (s, n, e, t)
    printf("gree and green = %d\n", likeness("gree", "gren")); // should be 3 (g, r, e)
    printf("mail and main = %d\n", likeness("mail", "main")); // should be 3 (m, a, i)
    printf("same = %d\n", likeness("same", "same")); // should be 4
    // opposite side in the likeness func. return different result...
    return 0;
}
1 Answers

The array found is not initialized

char found[STRLEN];

So the function contains using the uninitialized array invokes undefined behavior.

Another problem is that inside the inner for loop

    for(int j=0; j<STRLEN; j++) {
        /*printf("%c : %c\n", password[i], wordchosen[j]);
        printf("\n");*/
        if(password[i] == wordchosen[j] && !(contains(found, wordchosen[j]))) {
            like++;
        }
    }

the variable like can be incremented several times when the letter password[i] is present in the string wordchosen more than one time and is not yet written in the array found..

Also it seems that instead of this if statement

if(strlen(password)!=STRLEN && strlen(wordchosen)!=STRLEN) {
    return -1;
}

you should write this one

if(strlen(password)!=STRLEN || strlen(wordchosen)!=STRLEN) {
    return -1;
}

Pay attention to that instead of your manually written function contains you could use standard C string function strchr or memchr.

Here is a demonstration program.

#include <stdio.h>
#include <string.h>

#define STRLEN 4

int likeness( const char *password, const char *wordchosen ) 
{
    if ( strlen( password ) != STRLEN || strlen( wordchosen ) != STRLEN ) 
    {
        return -1;
    }

    if ( strcmp( password, wordchosen ) == 0 ) 
    {
        return STRLEN;
    }

    int like = 0;
    char found[STRLEN + 1] = "";

    for ( ; *password; ++password )
    {
        if ( strchr( wordchosen, *password ) != NULL && 
             strchr( found, *password ) == NULL )
        {
            found[like++] = *password;
        }            
    }

    return like;
}

int main( void )
{
    printf("week and week = %d\n", likeness("week", "week")); // should be 4 (same word even if only 3 (w, e, k))
    printf("test and tast = %d\n", likeness("test", "tast")); // should be 2 (t, s)
    printf("week and weak = %d\n", likeness("week", "weak")); // should be 3 (w, e, k)
    printf("snet and sent = %d\n", likeness("snet", "sent")); // should be 4 (s, n, e, t)
    printf("gree and gren = %d\n", likeness("gree", "gren")); // should be 3 (g, r, e)
    printf("mail and main = %d\n", likeness("mail", "main")); // should be 3 (m, a, i)
    printf("same = %d\n", likeness("same", "same")); // should be 4
}

The program output is

week and week = 4
test and tast = 2
week and weak = 3
snet and sent = 4
gree and gren = 3
mail and main = 3
same = 4

As you can see the function definition does not depend on the value of STRLEN.

The function can be defined also without using the auxiliary array.

Here you are.

int likeness( const char *password, const char *wordchosen ) 
{
    if ( strlen( password ) != STRLEN || strlen( wordchosen ) != STRLEN ) 
    {
        return -1;
    }

    if ( strcmp( password, wordchosen ) == 0 ) 
    {
        return STRLEN;
    }

    int like = 0;

    for ( const char *p = password; *p; ++p )
    {
        if ( memchr( password, *p, p - password ) == NULL && 
             strchr( wordchosen, *p ) != NULL )
        {
            ++like;
        }            
    }

    return like;
}
Related