C Style String палиндромный детектор (без учета регистра) в C ++ - PullRequest
0 голосов
/ 02 марта 2020

Я пытался создать программу, которая получает от пользователя строку в стиле C и отвечает, палиндром или нет. Я построил функцию (purg), которая вынимает все строчные буквы (и превращает прописные в строчные). И другой, который возвращает истину или ложь, если это палиндром или нет. Функция 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 ]

2 голосов
/ 02 марта 2020

После быстрого просмотра кода - кажется, вы заменяете все не алфавитные символы c на '\ 0', а затем ожидаете, что строка, содержащая случайные символы '\ 0', пройдет тест палиндрома, который проверяет для равенства символов трактуйте '\ 0' как обычный символ, который должен совпадать с зеркалом '\ 0' с другой стороны.

Кроме того, вы передаете строку полной длины, которая включает в себя '\ 0 'символов для функции isit, но в качестве длины указывайте только количество незамещенных символов.

Причина, по которой ваша строка отображается правильно, заключается в том, что при печати' \ 0 ' Просто ничего не делает. Посмотрите на содержимое ini с помощью отладчика, и вы увидите, что оно действительно завалено этими замененными символами '\ 0'.

Попробуйте дать ему строку, которая не содержит никаких алфавитов c символы, это должно пройти, если я прав.

1 голос
/ 02 марта 2020

Сначала давайте разделим ваш код на две разные функции с двумя разными целями, чтобы мы могли поговорить о них по отдельности:

Удалить не буквы из строки

Ваш код:

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 голосов
/ 02 марта 2020

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