【问题标题】:Check whether two strings are in same case检查两个字符串是否大小写相同
【发布时间】:2021-12-23 02:26:24
【问题描述】:

这是我的功能代码。我想检查给定的两个字符串是否大小写相同

example
String1 = PEN
String2 = PENCIL

输出应该是SAME

example 2
String1 = PEN
String2 = pencil

输出应该不一样 这是 C 程序代码。但不确定它是否正常工作,有没有其他方法可以解决这个问题,就像任何关键字一样检查相同的大小写。或任何其他解决方法

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++;
    }
}

【问题讨论】:

  • 你没有增加循环计数器。
  • 您的循环在检查第一个字符后无条件返回。它无法正确检查超过一个字符的字符串。
  • 如果字符不同,你就知道它不是同一种情况吗?
  • 如果您将测试分解为单独的函数,例如 int isLowerCase(char c) 和 int isUpperCase(char c),这项任务将会变得很多。然后您可以从 areSameCase() 调用这些函数
  • 是否应该将"PEN" 和"PENcil" 报告为“相同情况”?

标签: c string


【解决方案1】:

您可以使用isupper 和islower

例子:

#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;
}

使用bool 你可以用更少的行来完成:

#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;
}

甚至

#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;
}

【讨论】:

  • [j] 应该是 [i]。
  • 啊,是的。 isupper 和 islower 将非零值返回为 true,而不仅仅是 1。
  • 如果int 被替换为bool 那么isupper 等返回什么都没有关系。
  • 顺便说一句,参数应该是正确的,否则函数不能与const char*等参数一起使用。
  • 请解释一下你是怎么做到的
【解决方案2】:

注意: 如果担心可移植性,请不要编写这样的代码!

这是一个性能超过可读性的解决方案。

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;
}

此代码利用 ASCII 编码中的 'A' 到 'Z',编号为 0x41 到 0x5A 和 'a' 到 'z',编号为 0x61 到 0x7A。因此,掩码0x6 中的位始终设置为小写字符,而不是大写字符。因此代码绝对不可移植,因为它采用经典的 ASCII 编码(...另一方面,这非常常见)。

要检查两个字符串是否具有相同大小写的字母,则不允许任何字符串派生自任何其他给定字母的大小写。所以我们可以存储第一个字母对应的位组合,并将其他所有内容与之进行比较。

代码遍历第一个字符串,根据大小写掩码检查所有字母,然后对第二个字符串执行相同操作。如果有什么不匹配的,它就会停止。

这个有点神秘的代码的优点是性能。它不处理不是字母的情况,因此检查比isupper/islower 函数更快。总而言之,在 x86_64 上检查时大约有 40 条指令,分支量保持在最低限度,它一次检查一个字符串而不是比较它们,这可能对数据缓存的使用有益。

完整的测试代码:

#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");
}

输出:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-08
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多