提问者:小点点

C风格字符串回文检测器(不区分大小写)


我一直在尝试创建一个程序,从用户那里获取一个C样式的字符串,并回答它是否是回文。我已经构建了一个函数(purg),它可以取出所有非小写字母(并将大写字母变为小写字母)。另一个函数返回true或false,如果它是回文或非回文。purg函数可以按预期打印修改后的字符串(例如“111赛车”被打印为“赛车”),但是回文函数没有将修改后的字符串标记为回文,这是怎么回事?

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;

bool isit(char *test, int u){
   char *well = test;
   bool chk = false;

   for (int i = 0; i<2; i++) {
     if (well[i] != well[u-i-1]) {
       return false;
     }
     cout << well[i];
   }
   return true;
}

void purg(char *ini){
  int x = 0;
  bool answ;
  char *elim = ini;

  for (int i = 0; ini[i] != '\0'; i++) {
    if (ini[i] >= 'A' && ini[i] <= 'Z') {
      elim[i] = ini[i] + 32;
      x++;
    } else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
      elim[i]='\0';
    } else{
      x++;
    }
    cout << elim[i]; //This reliably prints the answer I expect ("11race car_!" to "racecar")
  }
  answ = isit(&elim[0], x); //Is this passed correctly?
  cout << endl;
  if (answ == true){
    cout << "It is a palindrome." << endl; //(user inputs like "RACecar", "racecar111", "racecar" and "WAAAAW111" are correct)
  } else {
    cout << "No palindrome here..." << endl; //("race car", "1racecar", and "d1o1d" are not, but they print as expected "racecar" and "dod")
  }
}

int main(){
   string str;//I'm not supposed to use C++ strings, should I replace this with char str[512]={}?

   cout<<"Give me a string"<<endl;
   getline(cin,str);

   purg(&str[0]);   
   return 0;
}

共3个答案

匿名用户

快速浏览代码后-似乎您将所有非字母字符替换为'\0',然后期望包含随机'\0'字符的字符串通过回文测试,该测试测试字符相等,将'\0'视为必须与另一侧的镜像'\0'匹配的常规字符。

此外,您将包含“\0”字符的全长字符串传递给isit函数,但仅将未替换字符的数量作为长度。

您的字符串似乎打印正确的原因是,当您打印'\0'时,它什么也不做。使用调试器查看ini的内容,您会发现它实际上散落着那些替换的'\0'字符。

尝试给它一个不包含任何非字母字符的字符串,如果我是正确的,它应该通过。

匿名用户

首先让我们将您的代码分成两个不同的函数,具有两个不同的目的,因此我们可以分别讨论它们:

void purge(char *ini) {
  int x = 0;
  bool answ;
  char *elim = ini;

  for (int i = 0; ini[i] != '\0'; i++) {
    if (ini[i] >= 'A' && ini[i] <= 'Z') {
      elim[i] = ini[i] + 32;
      x++;
    } else if (!(ini[i] >= 'a' && ini[i] <= 'z')) {
      elim[i]='\0';
    } else{
      x++;
    }
  }
}

x应该做什么?看起来它应该跟踪有效字符的数量,但你永远不会使用它。事实上,如果我们运行一个测试:

char s[256] = "a!bc";
purge(s);
ASSERT_EQ("abc", s); // This fails, purge changed the string s into just "a".

好吧,通过使用x

void purge(char *str) {
  int x = 0;

  for (int i = 0; ini[i] != '\0'; i++) {
    if (str[i] >= 'A' && str[i] <= 'Z') {
      str[x] = str[i] - 'A' + 'a';
      x++;
    } else if (str[i] >= 'a' && str[i] <= 'z') {
      str[x] = str[i];
      x++;
    }
  }
  // Make sure we null terminate the new string.
  str[x] = '\0';
}
bool is_palindrome(char *test, int u){
   char *well = test;
   bool chk = false;

   for (int i = 0; i<2; i++) {
     if (well[i] != well[u-i-1]) {
       return false;
     }
     cout << well[i];
   }
   return true;
}
  1. 错误的变量名。u应该是什么?well应该是什么?
  2. 为什么你只从i=0…2循环?
bool is_palindrome(char *str, int str_length) {
  for (int i = 0; i < str_length / 2; i++) {
    if (str[i] != str[str_length - i - 1]) {
      return false;
    }
  }
  return true;
}

通过将代码重写为两个独立的函数,我们可以开始在此代码中添加测试。例如,我们可以使用google的单元测试基础设施来执行以下操作:

TEST(MyTests, Purge_Nothing) {
  char a[256] = "abc";
  purge(a);
  EXPECT_EQ(std::string("abc"), a);
}

TEST(MyTests, Purge_Non_Letters_At_Front) {
  char a[256] = "!abc";
  purge(a);
  EXPECT_EQ(std::string("abc"), a);
}

TEST(MyTests, Purge_Non_Letter_In_Middle) {
  char a[256] = "ab!c";
  purge(a);
  EXPECT_EQ(std::string("abc"), a);
}

TEST(MyTests, Purge_Non_Letters_At_End) {
  char a[256] = "abc!";
  purge(a);
  EXPECT_EQ(std::string("abc"), a);
}

TEST(MyTests, Purge_Uppercase) {
  char a[256] = "Abc!";
  purge(a);
  EXPECT_EQ(std::string("abc", a);
}

TEST(MyTests, Palindrome) {
  EXPECT_TRUE(is_palindrome("abcba");
  EXPECT_TRUE(is_palindrome("abba"));
  EXPECT_TRUE(is_palindrome("aba"));
  EXPECT_TRUE(is_palindrome("aa"));
  EXPECT_TRUE(is_palindrome("z"));
  EXPECT_TRUE(is_palindrome(""));
  EXPECT_FALSE(is_palindrome("abcda");
  EXPECT_FALSE(is_palindrome("abda");
  EXPECT_FALSE(is_palindrome("abd");
  EXPECT_FALSE(is_palindrome("ad");
}

匿名用户

回文测试的大小写不敏感函数示例。您可以在C代码中按原样使用它。

#include <string.h>
#include <ctype.h>

int is_palindrome(const char * str) {
    const char * tail = str + strlen(str) - 1;

    for ( ; str < tail && toupper(*str) == toupper(*tail); ++str, --tail )
        ;

    return str >= tail;
}

相关问题