Как убрать пробелы и проверить, является ли строка палиндромом? - PullRequest
2 голосов
/ 29 марта 2019

Я пытаюсь выяснить, как удалить пробелы, а затем проверить, является ли строка с удаленными пробелами палиндромом.

Я пробовал обе вещи по отдельности, и я не могу заставить их работать вместе.

int check_palindrome(char *);

int main()
{
    char s1[20];
    printf("Enter the string...\n");
    gets(s1);

    int x;
    x=check_palindrome(s1);
    x?printf("%s = is a Palindrome\n", s1):printf("%s = is Not a Palindrome\n", s1);
}

int check_palindrome(char *s)
{
    int i,j;
    for(i=0;s[i];i++);

    for(i=i-1,j=0;i>j;i--,j++)
    {
        if(s[i]!=s[j])
        {
            return 0;
        }
    }
    if(s[i]==s[j])
    {
        return 1;
    }
}

Этот код работает для проверки палиндрома, но он не работает, есливвод начинается с заглавной буквы, или если он имеет пробелы.Например, я ожидаю, что результат «медсестры бежит» будет «медсестры бегут - палиндром», но фактический результат - «медсестры бегут не палиндром», из-за пробела между ними и ожидаемого выхода «папа»«Папа - это палиндром», но возвращается «Папа - не палиндром».

Ответы [ 4 ]

3 голосов
/ 29 марта 2019

Если вам не нужна измененная строка, вы можете сэкономить много работы и просто игнорировать пробелы и регистр в своем сравнении, например, так:

int ispalindrome = 1;
while (s < e && ispalindrome) {
        while (*s == ' ') s++;
        while (*e == ' ') e--;
        if (tolower(*s++) != tolower(*e--))
                ispalindrome = 0;
}

с s, указывающим на начало, и e, указывающим на конец (последний символ) строки.

Edit:

Я только что понял, что есть угловой случай, когда доступ к массиву вне границ может произойти, если вся строка состоит только из пробелов. Затем второй пробел пропускается через «левый» конец массива. Так что измени это на

        while (*e == ' ' && e > s) e--;

Обратите внимание, что в этом случае ispalindrome будет ложным. Определено, является ли строка empty палиндромом или нет.

1 голос
/ 29 марта 2019

Я бы начал с форматирования строки, чтобы упростить анализ, удалив все специальные / пробельные символы, а затем преобразовав все буквы в верхний или нижний регистр.

0 голосов
/ 29 марта 2019

Как убрать пробелы и проверить, является ли строка палиндромом?

В вашем вопросе две части: (1)" Как убрать пробелы "?и (2) [Как] " проверить, является ли строка палиндромом? ".Вы должны подойти к проблеме в два отдельных шага.

Удаление пробелов из строки можно сделать одним из двух способов: (1) удалить пробелы на месте в исходной строке (предполагается, что ваш оригинал является изменяемой строкой, а не String Literal ) или (2) удаляет пробелы при заполнении второй строки непробельными символами из первой, сохраняя первую строкубез изменений (работает независимо от того, является ли оригинал изменяемым).Ваш самый безопасный выбор - последний.

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

void removespace (char *dest, const char *src)
{
    size_t n = 0;
    while (*src) {
        if (!isspace(*src))
            dest[n++] = *src;
        src++;
    }
    dest[n] = *src;     /* nul-terminate */
}

Переход ко второмучасть вашей проблемы, если у вас возникают проблемы, когда вы поворачиваете голову, используя указатели start и end , чтобы перебирать концы строки до середины, чтобы проверить, является ли строкаПалиндром, вы можете сделать то же самое со строковыми индексами.Кроме того, всякий раз, когда вам нужно проверить, является ли что-то пробелом или преобразовать регистр символов, используйте макросы isspace() или tolower() / toupper(), предоставленные в ctype.h.(в противном случае ВЫ несете ответственность за ВСЕ необходимые условные проверки)

Простая реализация checkpalindrome() с использованием строковых индексов может выглядеть так:

int checkpalindrome (const char *s)
{
    size_t n = 0, len = strlen (s);

    while (len-- > n)   /* loop over each start/end lowercase char */
        if (tolower (s[n++]) != tolower (s[len]))
            return 0;

    return 1;
}

Теперь в вашей реализации main() чтение вашей строкиот пользователя Никогда, никогда, никогда не используйте gets().Он настолько небезопасен и подвержен переполнению буфера, что был удален из стандартной библиотеки в C11.Смотрите Почему get () настолько опасен, что его никогда не следует использовать! .Просто используйте fgets() вместо этого и обрежьте конец строки из буфера, заполненного fgets, переписав конец строки символом nul-terminating .(strcspn() удобно для этого).

Если положить его целиком (и использовать ваш троичный для управления выводом "is" или "is not"), вы можете сделать:

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

#define MAXC 1024   /* if you need a constant, define one (or more) */

void removespace (char *dest, const char *src)
{
    size_t n = 0;
    while (*src) {
        if (!isspace(*src))
            dest[n++] = *src;
        src++;
    }
    dest[n] = *src;     /* nul-terminate */
}

int checkpalindrome (const char *s)
{
    size_t n = 0, len = strlen (s);

    while (len-- > n)   /* loop over each start/end lowercase char */
        if (tolower (s[n++]) != tolower (s[len]))
            return 0;

    return 1;
}

int main (void) {

    char s[MAXC], nospace[MAXC];

    fputs ("enter a string: ", stdout);
    if (!fgets (s, MAXC, stdin)) {  /* Never, Ever use gets() */
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }
    s[strcspn (s, "\r\n")] = 0; /* trim line-ending */
    removespace (nospace, s);   /* remove whitespace from s */

    printf ("'%s' => %s a palindrome.\n",
            s, checkpalindrome (nospace) ? "is" : "is not");

    return 0;
}

( примечание: Никогда не экономьте на размере буфера! )

Пример использования / вывода

$ ./bin/checkpalindrome
enter a string: a
'a' => is a palindrome.

(вы можете изменить способ обработки строки из одного символа в соответствии с вашими потребностями)

$ ./bin/checkpalindrome
enter a string: aa
'aa' => is a palindrome.

$ ./bin/checkpalindrome
enter a string: ab
'ab' => is not a palindrome.

$ ./bin/checkpalindrome
enter a string: aba
'aba' => is a palindrome.

$ ./bin/checkpalindrome
enter a string: abc
'abc' => is not a palindrome.

$ ./bin/checkpalindrome
enter a string: A man a plan a canal Panama
'A man a plan a canal Panama' => is a palindrome.

Просмотрите все и дайте мне знать, если у вас есть вопросы.

0 голосов
/ 29 марта 2019

Мне нравится ваш лаконичный стиль. Так что ответ должен соответствовать.

1.) Заглавная буква меняет логику:

if(s[i]==s[j]) 
continue;
if(s[i]==s[j]+DIFF_a_A) continue;
if(s[i]+DIFF_a_A==s[j]) continue;
return false;

с #define DIFF_a_A ('A' - 'a')

2.) Заготовки поместите приращения в цикл:

for(i=i-1,j=0;i>j;){
    if(s[i] == ' ') i--, continue;
    if(s[j] == ' ') j++, continue;
        ...
    i--,j++;
}

Подходит ли это вашему стилю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...