C 可以假定我要存储字符的数组吗?

Can C presume which array I want to store my characters?

我正在编写代码来检查数组是否为回文数组:

Write a program that reads a message, then checks whether it's a palindrome
(the letters in the message are the same from left to right as from right to left):

Enter a message: He lived as a devil, eh?
Palindrome

Enter a message: Madam, I am Adam.
Not a palindrome

当我进入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;
}

在检查回文之前,您必须删除白色 spaces 和标点符号。例如,如果您使用 civic?,则它不是回文,因为 ?。另一方面,如果你使用 civ ic,它不是回文,因为白色 space。

  1. 将所有字母转换为大写或小写。
  2. 删除白色 spaces。
  3. 删除标点符号。
  4. 是否检查回文。

您可以使用 # include <string.h>

  1. 首先你必须使用 scanf() 接受白色字符串 space.
printf("Enter a string = ");
scanf("%[^\n]%*c", word);
  1. 然后您必须将该字符串转换为大写或小写,因为 a != A。我们知道 civic 是回文,但 Civic 不是回文('Civic != civiC) 因为大写字母有不同的 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++;
    }
  1. 另一种情况是你输入civ ic白字space,回文字是ci vic。可以看到civ ic != ci vic。你必须在你的程序中删除白色 spaces 。而且你还必须删除标点符号,因为如果你使用 civic, 它的反向词是 ,civic'. You can seecivic, != ,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++;
    }
  1. 最后一件事是我们必须反转我们的字符串并且需要检查我们反转的字符串是否等于我们的原始字符串。如果为真,我们的字符串就是回文。如果它是假的,我们的字符串就不是回文。
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

对于初学者,您应该将变量 c 声明为类型 int。用户可以中断输入过程,在这种情况下函数 getchar returns 整数值 EOF 你应该检查是否发生了这种情况。

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

while 语句的条件有错误

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

您必须使用逻辑与运算符 &&.

而不是按位运算符 &

正如我已经说过的,您应该检查 while 语句的条件是否用户中断了输入。例如

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

toupperisalpha 调用的参数应转换为 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

请注意,您可以只使用一次函数调用 fgets

,而不是使用多次调用函数 getchar 的循环
fgets( message, sizeof( message ), stdin );

if ( fgets( message, sizeof( message ), stdin ) != NULL )
{
    // check whether the entered string is a palindrome
}