-1

Basically i have an array of strings and i need to check if they are arranged in lexographic order (case insensitive of upper or lower case, meaning it doesn't matter which one it is). For that I took the already created strcmp function and re-arranged it so that it won't matter if it's upper or lower case. But when entering str_compare, it won't enter the while loop and just exits the function. Does anyone know why? Here is the code:

int main(){
...
char * banned_words[N];
...
if (!are_sorted(banned_words, n)) {
        printf("Words are not sorted correctly!\n");
        free_strings(banned_words, n);
        return ERROR;
    }
...
}

bool are_sorted(char * strings[], int n) {

    int length = n;
    int result = 0;

    for (int i = 0; i < length - 1; i++) {
        result += str_compare(strings[i], strings[i + 1]);
    }
        if (result > 0)
            return false;
        else
            return true;

}

int str_compare(char **str1, char **str2){
    while (str1 && str2) {
        if (str1 >= 'A' && str1 <='Z' && (str1 + 'a' - 'A') == str2){
            **str1++;
            **str2++;}
        else if (str2 >= 'A' && str2<='Z' && (str2 + 'a' - 'A') == str1){
            **str1++;
            **str2++;}
        else if (str1 == *str2){
            **str1++;
            **str2++;}
        else break;
    }

    if (str1 >= 'A' && str1<='Z')
        return (str1 +'a' - 'A') - str2;
    else if (str2 >= 'A' && str2<='Z')
        return str1 - (str2 +'a'-'A');
    else return str1 - str2;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
rachel
  • 1
  • 1
  • 3
    You should enable compiler warnings. See https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings . – Sneftel Jun 12 '22 at 09:22
  • 1
    You pass `strings[i]` and `strings[i + 1]`. At every location inside the `strings` array, is a type `char *`, not `char **`. You are confused about the argument type that `str_compare` needs to receive. It should accept `char *` twice. Furthermore you attempt to compare them to a `char`, which is also wrong. Enable compiler warnings to warn about incompatible types. – Cheatah Jun 12 '22 at 09:29
  • 1
    And lastly you should not modify values in a function that you call "compare". – Cheatah Jun 12 '22 at 09:29
  • Pointer errors notwithstanding, `result += str_compare` won't work because `str_compare` can return both positive and negative numbers that might just sum up to zero. – n. m. could be an AI Jun 12 '22 at 09:31
  • @Cheatah the intent was probably to modify local variables `str1` and `str2` only. It didn't work well but there's nothing wrong with the intent. – n. m. could be an AI Jun 12 '22 at 09:33
  • I see what you're saying @Cheatah. Indeed, I'm confused with all the * pointers thing. Essentially I want to enter to str_compare and start comparing letter by letter of both strings to see which one is bigger. If you could further explain what is going on with the whole *strings[] and *str1 situation I'd be very greatful. – rachel Jun 12 '22 at 10:59

1 Answers1

1

You call the function str_compare with expressions of the type char *

result += str_compare(strings[i], strings[i + 1]);

While function parameters have the type char **.

int str_compare(char **str1, char **str2){

This while loop

while (str1 && str2) 

invokes undefined behavior because the condition of the loop evaluates to false when at least one pointer will become a null pointer.

Also within the function conditions in the if statements like for example

if (str1 >= 'A' && str1 <='Z' && (str1 + 'a' - 'A') == str2){

or

else if (str1 == *str2){

do not make a sense. Compared operands have different types.

Also the return statements in this code snippet

if (str1 >= 'A' && str1<='Z')
    return (str1 +'a' - 'A') - str2;
else if (str2 >= 'A' && str2<='Z')
    return str1 - (str2 +'a'-'A');
else return str1 - str2;

can produce unpredictable results.

And this code snippet within the function are_sorted

for (int i = 0; i < length - 1; i++) {
    result += str_compare(strings[i], strings[i + 1]);
}
    if (result > 0)
        return false;
    else
        return true;

actually does not determine whether the array of strings is sorted. For example the comparison of one pair of strings can yield -1 while the comparison of other pair of strings can yield 1 and the result will be equal to 0 though the array is not sorted.

The function str_compare can be defined the following way as shown in the demonstrative program below.

#include <stdio.h>
#include <ctype.h>

int str_compare( const char *s1, const char *s2 )
{
    char c1 = '\0', c2 = '\0';
    while ( *s1 && ( c1 = tolower( ( unsigned char )*s1 ) ) == ( c2 = tolower( ( unsigned char) *s2 ) ) )
    {
        ++s1;
        ++s2;
    }

    return islower( ( unsigned char )*s1 ) && islower( ( unsigned char ) *s2 ) 
        ?  c1 - c2 
        : *s1 - *s2;
}    

int main(void) 
{
    const char *s1 = "HeLlO";
    const char *s2 = "hElLo";

    printf( "\"%s\" == \"%s\" is %d", s1, s2, str_compare( s1, s2 ) );

    return 0;
}

The program output is

"HeLlO" == "hElLo" is 0

If you may not use the standard C function tolower then the function str_compare can look the following way

int str_compare( const char *s1, const char *s2 )
{
    char c1 = '\0', c2 = '\0';
    while ( 1 )
    {
        c1 = *s1; c2 = *s2;

        if (  'A' <= c1 && c1 <= 'Z' ) c1 += 'a' - 'A';
        if (  'A' <= c2 && c2 <= 'Z' ) c2 += 'a' - 'A';

        if ( c1 != c2 || c1 == '\0' ) break;

        ++s1; ++s2;
    } 

    return 'a' <= c1 && c1 <= 'z' && 'a' <= c2 && c2 <= 'z' 
        ? c1 - c2 : *s1 - *s2;
}

As for the function are_sorted then it can be defined for example the following way

bool are_sorted( char * strings[], size_t n ) 
{
    size_t i = n;

    if ( n != 0 )
    { 
        ++i;
        while ( i != n && str_compare( strings[i-1], strings[i] ) <= 0 ) ++i;
    }  

    return i == n ;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335