[C ++中的C样式字符串回文检测器(不区分大小写)

问题描述 投票:0回答:3

我一直在尝试创建一个从用户那里获取C样式字符串并回答回文的程序。我建立了一个函数(清除),该函数可以取出所有非小写字母(并将大写字母变成小写字母)。如果是回文,则另一个返回true或false。 purg函数可以按预期打印修改后的字符串(例如,“ Race 111 car”打印为“ racecar”),但是回文功能不能将修改后的字符串标记为回文,这是怎么回事?

#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;
}
c++ function pointers c-strings palindrome
3个回答
2
投票

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

另外,您将包含'\ 0'字符的全长字符串传递给isit函数,但仅给出未替换字符的数目作为长度。

您的字符串看起来正确打印的原因是,当您打印'\ 0'时,它什么都不做。用调试器查看ini的内容,您会发现它真的被那些替换为'\ 0'的字符所取代。

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


1
投票

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

清除字符串中的非字母

您的代码:

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

0
投票

C用于回文测试的不区分大小写功能的示例。您可以按原样使用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;
}
© www.soinside.com 2019 - 2024. All rights reserved.