Может ли C предполагать, какой массив я хочу хранить для своих символов? - PullRequest
0 голосов
/ 25 января 2020

Я пишу код, который проверяет, является ли массив палиндромом или нет:

Напишите программу, которая читает сообщение, а затем проверяет, является ли палиндром
(буквы в сообщении такие же слева направо, как справа налево):

Введите сообщение: Он жил как дьявол, а?
Палиндром

Введите сообщение: Мадам, я Адам.
Не палиндром

Когда я ввел He lived as a devil, eh?,
, он дает мне вывод Not a palindrome,
, но реальный вывод должен быть palindrome.

Ниже приведен код, который я пробовал до сих пор.

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

#define MAX_LEN 100

int main(void) {

    char message[MAX_LEN];
    char c, *p = message, *q;

    printf("Enter a message: ");

    while ((c = toupper(getchar())) != '\n' & p < message + MAX_LEN) {
        if (isalpha(c))
            *p++ = c;
    }
    p--;

    for (q = message; q < p; q++, p--) {
        if (*p != *q) {
            printf("Not a palindrome\n");
            return 0;
        }
    }
    printf("Palindrome\n");
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 26 января 2020

Для начала вы должны объявить переменную c как имеющую тип int. Пользователь может прервать процесс ввода, и в этом случае функция getchar возвращает целочисленное значение EOF, и вы должны проверить, произошло ли это.

char *p = message, *q;
int c;

В условии оператора while есть ошибка

while ((c = toupper(getchar())) != '\n' & p < message + MAX_LEN) {

Вместо побитового оператора & вы должны использовать логический оператор AND &&.

Как я уже сказал, вы должны проверить в условии оператора while, пользователь прервал ввод. Например,

while (  p < message + MAX_LEN && ( c = toupper(getchar())) != EOF && c != '\n') {
    if (isalpha(c))
        *p++ = c;
}

Аргумент вызова toupper или isalpha должен быть преобразован в тип unsigned char. В противном случае в общем случае без приведения такой вызов может вызвать неопределенное поведение.

Желательно не исключать из введенных чисел строки. Так что лучше хотя бы вызвать функцию isalnum вместо функции isalpha.

Пользователь может ввести пустую строку, в этом случае это уменьшение указателя

p--;

также может вызывать неопределенное поведение.

И лучше, когда программа имеет одну точку для выхода.

Программа может выглядеть следующим образом

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

#define MAX_LEN 100

int main(void) 
{
    char message[MAX_LEN];

    printf( "Enter a message: " );

    char *p = message;

    for ( int c; p < message + MAX_LEN &&  ( c = getchar() ) != EOF && c != '\n';   )
    {
        if( isalnum( ( unsigned char )c ) )
        {
            *p++ = toupper( ( unsigned char )c );
        }           
    }

    int palindrome = 1;

    if ( p != message )
    {
        for ( char *q = message; palindrome && q < --p; ++q )
        {
            palindrome = *q == *p;
        }           
    }

    printf( "The entered message is %spalindrome\n", 
            palindrome ? "" : "not " );

    return 0;
}

Вывод может выглядеть, например, как

Enter a message: He lived as a devil, eh?
The entered message is palindrome

или как

Enter a message: Madam, I am Adam
The entered message is not palindrome

Обратите внимание, что вместо использования al oop с многочисленными вызовами функции getchar вы можете использовать только один вызов функции fgets

fgets( message, sizeof( message ), stdin );

или

if ( fgets( message, sizeof( message ), stdin ) != NULL )
{
    // check whether the entered string is a palindrome
}
2 голосов
/ 26 января 2020

Перед проверкой палиндрома необходимо удалить пробелы и знаки препинания. Например, если вы используете civic?, это не палиндром из-за ?. С другой стороны, если вы используете civ ic, это не палиндром из-за пробелов. Там для

  1. Преобразование всех букв в верхний или нижний регистр.
  2. Удалить пробелы.
  3. удалить знаки препинания.
  4. Проверить палиндром или нет.

Вы можете сделать это, используя # include <string.h>

  1. Прежде всего, вы должны использовать scanf(), которые принимают строка с пробелом.
printf("Enter a string = ");
scanf("%[^\n]%*c", word);

Затем вам нужно преобразовать эту строку в верхний или нижний регистр, потому что a != A. Мы знаем, что civic является палиндромом, но Civic не является палиндромом ('Civi c! = Civi C), поскольку заглавные буквы имеют разные значения ASCII, а строчные буквы имеют разные значения ASCII.

  • (a - z) -: 97 - 122
  • (A - Z) -: 65 - 90

В моем случае я перевел строчные буквы в прописные.

while(strlen(word) >= i)
    {
        if(word[i] >= 97 && word[i] <= 122) 
        {
            word[i] = word[i] - 32; 
        }

        i++;
    }
Другой случай - ваш, если вы введете civ ic с пробелом, его палиндромное слово будет ci vic. Вы можете увидеть civ ic != ci vic. Там вы должны удалить пробелы в вашей программе. А также вы должны удалить знаки препинания, потому что если вы используете civic,, то обратное слово будет ,civic'. You can see civi c,! =, Civic`.
int len = strlen(word);

    while(a < len)
    {
        for(i = 0; i < len; i++)
        {
            if(word[i] == ' ' || !(word[i] >= 'A' && word[i] <= 'Z'))
            {
                for(j = i; j < len; j++)
                {
                    word[j] = word[j+1];
                }
                len--;
            }
        }
        a++;
    }
Наконец, мы должны обратить нашу строку и должны проверить, равна ли наша обратная строка нашей исходной строке. Если это правда, наша строка - палиндром. Если оно ложно, наша строка не является палиндромом.
for(i = 0; i < len; i++)
    {
        if(word[i] == word[len - 1])
        {
            len--;
        }
        else
        {
            printf("%s is not a palindrome\n", word);
            return 0;
        }
    }

    printf("%s is a palindroeme\n", word);

Это полный код после объединения вышеуказанных частей

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

int main (void)
{
    char word[100];
    int i = 0;
    int j, x = 0;
    int a = 0;

    printf("Enter a string = ");
    scanf("%[^\n]%*c", word);

    while(strlen(word) >= i)
    {
        if(word[i] >= 97 && word[i] <= 122) 
        {
            word[i] = word[i] - 32; 
        }

        i++;
    }

    printf("After converting it to uppercase = %s\n", word);

    int len = strlen(word);

    while(a < len)
    {
        for(i = 0; i < len; i++)
        {
            if(word[i] == ' ' || !(word[i] >= 'A' && word[i] <= 'Z'))
            {
                for(j = i; j < len; j++)
                {
                    word[j] = word[j+1];
                }
                len--;
            }
        }
        a++;
    }

    printf("After removing spaces = %s\n", word);

    for(i = 0; i < len; i++)
    {
        if(word[i] == word[len - 1])
        {
            len--;
        }
        else
        {
            printf("%s is not a palindrome\n", word);
            return 0;
        }
    }

    printf("%s is a palindroeme\n", word);

    return 0;

}

Первый тест Вывод -:

Enter a string = He lived as a devil, eh?
After converting it to uppercase = HE LIVED AS A DEVIL, EH?
After removing spaces = HELIVEDASADEVILEH
HELIVEDASADEVILEH is a palindroeme

Второй тестовый вывод -:

Enter a string = Madam I am Adam.
After converting it to uppercase = MADAM I AM ADAM.
After removing spaces = MADAMIAMADAM
MADAMIAMADAM is not a palindrome
...