Home > OS >  Check whether two strings are in same case
Check whether two strings are in same case

Time:11-11

This is my function code. I want to check whether given two string are in same case

example
String1 = PEN
String2 = PENCIL

the output should be SAME

example 2
String1 = PEN
String2 = pencil

the output should be NOT SAME This is C program code. But not sure it is working correct, is there anyother way to solve this like any keyword to check same case or not. or any other methods to solve

int areSameCase(char str[],char str1[])
{
    int i=0,j=0;
    while(str[i]!='\0' && str1[j]!='\0')
    {
        if((str[i]>='a' && str[i]<='z') == (str1[j]>='a' && str1[j]<='z'))
        {
            return 1;
        }
        else if((str[i]>='A' && str[i]<='Z') == (str1[j]>='A' && str1[j]<='Z'))
        {
            return 1;
        }
        else
        {
            return 0;
        }
            i  ;
            j  ;
    }
}

CodePudding user response:

You can use isupper and islower

Example:

#include <ctype.h>

int areSameCase(const char str*, const char str1*)
{
    for (int i = 0; str[i]!='\0' && str1[i]!='\0';   i)
    {
        int l_a = islower(str[i]);
        int l_b = islower(str1[i]);
        int u_a = isupper(str[i]);
        int u_b = isupper(str1[i]);
        if ((!l_a &&  l_b) ||  // b is lower case but a isn't
            ( l_a && !l_b) ||  // a is lower case but b isn't
            (!u_a &&  u_b) ||  // b is upper case but a isn't
            ( u_a && !u_b))    // a is upper case but b isn't
        {
            return 0;
        }
    }
    return 1;
}

Using bool you can do it with a bit fewer lines:

#include <ctype.h>
#include <stdbool.h>

int areSameCase(const char str*, const char str1*)
{
    for (int i = 0; str[i]!='\0' && str1[i]!='\0';   i)
    {
        bool l_a = islower(str[i]);
        bool l_b = islower(str1[i]);
        bool u_a = isupper(str[i]);
        bool u_b = isupper(str1[i]);
        if ((l_a != l_b) || (u_a != u_b))
        {
            return 0;
        }
    }
    return 1;
}

or even

#include <ctype.h>
#include <stdbool.h>

int areSameCase(const char str*, const char str1*)
{
    for (int i = 0; str[i]!='\0' && str1[i]!='\0';   i)
    {
        if (((bool)islower(str[i]) != (bool)islower(str1[i])) ||
            ((bool)isupper(str[i]) != (bool)isupper(str1[i])))
        {
            return 0;
        }
    }
    return 1;
}

CodePudding user response:

NOTE: please don't write code like this if portability is a concern!

This is a performance over readability solution.

bool is_same_case (const char* s1, const char* s2)
{
  // CASE_MASK is a bit mask, always set in ASCII 'a' to 'z', but not in 'A' to 'Z'
  const char CASE_MASK = 0x60; 
  const char cas = s1[0] & CASE_MASK;

  for(size_t i=1; s1[i]!='\0'; i  )
    if((s1[i] & CASE_MASK) != cas)
      return false;

  for(size_t i=0; s2[i]!='\0'; i  )
    if((s2[i] & CASE_MASK) != cas)
      return false;

  return true;
}

This code takes advantage of 'A' to 'Z' in ASCII encoding having numbers 0x41 to 0x5A and 'a' to 'z' having numbers 0x61 to 0x7A. Thus the bits in the mask 0x6 is always set in lower case characters, but not in upper case ones. So the code is definitely not portable since it assumes the classic ASCII encoding (...which on the other hand is incredibly common).

To check if both strings have letters of the same case, then none of the strings are allowed to derive from the case of any other given letter. So we can store the bit combination corresponding to the first letter and compare everything else against that.

The code iterates through the first string, checking all letters against the case mask, then does the same for the second string. In case something doesn't match, it stops.

The advantage of this somewhat cryptic code is performance. It doesn't handle the scenario where something isn't a letter, so the checks are faster than the isupper/islower functions. All in all it's some ~40 instructions when checked on an x86_64, the amount of branching is kept to a minimum and it inspects one string at a time rather than comparing them, which could perhaps be beneficial for data cache usage.

Full test code:

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

bool is_same_case (const char* s1, const char* s2)
{
  // CASE_MASK is a bit mask, always set in ASCII 'a' to 'z', but not in 'A' to 'Z'
  const char CASE_MASK = 0x60; 
  const char cas = s1[0] & CASE_MASK;

  for(size_t i=1; s1[i]!='\0'; i  )
    if((s1[i] & CASE_MASK) != cas)
      return false;

  for(size_t i=0; s2[i]!='\0'; i  )
    if((s2[i] & CASE_MASK) != cas)
      return false;

  return true;
}

#define TEST(s1,s2) printf("%s %s = %s\n", s1, s2, is_same_case(s1,s2)?"yes":"no")

int main (void) 
{
  TEST("hello","world");
  TEST("Hello","World");
  TEST("HELLO","WORLD");
  TEST("HELLO","hello");
}

Output:

hello world = yes
Hello World = no
HELLO WORLD = yes
HELLO hello = no
  • Related