如何在忽略区分大小写和标点符号的情况下检查C中的回文结构?

0 c case-sensitive palindrome punctuation

我正在尝试编写一个忽略标点符号和区分大小写的回文,1使用数组,第2使用指针.我的问题是我无法弄清楚如何.代码似乎除此之外还可以正常工作.我还写了一个小写的大写函数,但我认为它无论如何都不行.

这是我使用数组的第一个代码.

int is_palindrome1(const char phrase[], int length)
{
  int first = phrase[0];
  int last = phrase[length - 1];

  for (length = 0; phrase[length] != '\0'; length++)
  {
    while (last > first)
    {
      if ((phrase[first]) != (phrase[last]))
      {
        return 0;
      }
      last--;
      first++;
    }
    break;
  }
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

这是我使用指针的第二个回文代码.

int is_palindrome2(const char *phrase, int length)
{
  int i;
  length = strlen(phrase);

  for (i = 0; i < length / 2; i++)
  {
    if (*(phrase + i) != *(phrase + length - i - 1))
    {
      return 0;
    }
  }
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

这是我的小写大写函数.

char lower_to_upper(char lower, char upper)
{
  if (lower >= 'a' && lower <= 'z')
  {
    upper = ('A' + lower - 'a');
    return upper;
  }
  else
  {
    upper = lower;
    return upper;
  }
}
Run Code Online (Sandbox Code Playgroud)

Bil*_*nch 5

所以.让我们分步进行.

最简单的is_palindrome函数:

这看起来与您的代码非常相似.除了您修复的一些语法问题.请注意,se指向字符串的第一个和最后一个字符.

bool is_palindrome(const char *phrase, unsigned length) {
    const char *s = phrase + 0;
    const char *e = phrase + length - 1;

    while (s < e) {
        if (*s != *e)
            return false;
        s += 1;
        e -= 1;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

让我们添加小写/大写比较:

最简单的方法是将所有有效字符转换为大写.看起来你在谈论一个lower_to_upper()功能时也有这个想法.

唯一的问题是,你的函数有一个非常奇怪的签名(为什么是upper一个参数?).所以,一个简单的解决方法是使用内置函数toupper().

bool is_palindrome(const char *phrase, unsigned length) {
    const char *s = phrase + 0;
    const char *e = phrase + length - 1;

    while (s < e) {
        if (toupper(*s) != toupper(*e))
            return false;
        s += 1;
        e -= 1;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

那些其他角色(如空格)怎么样

现在.最后一部分是你想忽略空格和标点符号.而不是措辞这样的说法,这可能是更好的谈论,我们的人物想比较.我认为您只想比较字母数字字符.这些是az,AZ和0-9.要测试一个角色是否是其中之一,我们可以构建一个自定义函数,或者我们可以使用内置函数isalnum()来执行此操作:

bool is_palindrome(const char *phrase, unsigned length) {
    const char *s = phrase + 0;
    const char *e = phrase + length - 1;

    while (s < e) {
        if (!isalnum(*s)) {
            s++;
        } else if (!isalnum(*e)) {
            e--;
        } else if (toupper(*s) == toupper(*e)) {
            s++;
            e--;
        } else {
            return false;
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

最后的一些想法:

请注意,在每个循环过程中,我们无论是移动s,e或两者一步.这确保了我们最终将完成循环.我们的条件s < e也确保一旦我们到达字符串的"中间",我们就完成了.我把中间放在引号中,因为对于字符串"ab a",中间是第二个字符.

语言是复杂的野兽:

在大多数(所有?)系统中,英语的编码相当简单.但其他语言并不总是那么简单.在评论中,chux对此有一个建议:

一个区域设置可能具有从低到高的多对一映射,反之亦然,使用往返如果(tolower(toupper(*s)) != tolower(toupper(*e)))处理.

我个人并不那么担心,因为我觉得在我们担心这一点的同一点上,我们也应该担心文本是如何编码的.是UTF-8吗?还有别的吗?这可能超出了教师的期望.