我正在尝试检查输入数字是否为回文。我是通过字符串而不是整数来完成的。所以,我正在接收一个字符串并将其反转为另一个字符串。但是,当我使用字符串比较函数时,它没有给我 0,说明字符串不相同。即使当我输入例如“1001”时,输入字符串和反向字符串都显示 1001。我已经用其他方法解决了这个问题,但我试图具体了解这个方法有什么问题。
#include <stdio.h>
#include <string.h>
int main(void)
{
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
numLen = strlen(input) - 1;
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
reverse[i] = input[numLen - 1 - i];
if (i == numLen - 1)
{
reverse[i + 1] = '\0';
}
}
printf("The reverse number is: %s\n", reverse);
printf("The original number is: %s\n", input);
int result = strcmp(input, reverse);
printf("Result of strcmp gives us: %d\n", result);
if (strcmp(input, reverse) == 0)
{
printf("These numbers are palindromes\n");
}
else
{
printf("These numbers are not palindromes\n");
}
return 0;
}
问题是您没有正确处理字符串。您应该覆盖 '\n'
与 \0
.
...
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0'; // getting the length of the
// string without `\n`
// and overwriting with `\0`
numLen = strlen(input) ; // now you don't need to put the -1
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
....
除了这两个变化之外,其他一切都保持不变。你把它完全颠倒过来了。然后你使用了 strcmp
正确的方法。但是额外的\n
在我显示的代码中被删除。
(仍然)为什么有效?
现在给你一个更好的主意。你很好地形成了反转的字符串。但是原始字符串有 \n
在其内部。
printf("The reverse number is: (%s)\n", reverse);
printf("The original number is: (%s)\n", input);
在前面的程序中,您只需编写这两行。你会明白你错在哪里。
关于提供输入 1001
Enter 它给出了这个输出。
The reverse number is: (1001)
The original number is: (1001
)
什么是strcspn
在做什么?
我正在使用 strcspn
函数得到了没有\n
的长度并用 \0
覆盖它.
0 1 2 3 4 5 --> indices
1 0 0 1 \n \0 --> strcspn(input,"\n") returns 4.
1 0 0 1 \0 \0 --> input[strcspn(input,"\n")]='\0'
你可以像这样简单地做,而不需要复制和其他一切。
没有额外的内存 - 就地回文检查
bool checkPal(const char *s){
for(int i = 0, j= strlen(s)-1; i< strlen(s) && j>=0 ; i++)
if(s[i] != s[j])
return false;
return true;
}
int main(void)
{
char input[100];
char reverse[100];
printf("Enter a number\n");
if( fgets(input, 100, stdin) )
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0';
int numLen = strlen(input) ;
printf("Length of string is: %d \n", numLen);
printf("These numbers are %spalindromes\n", checkPal(input)?"not ":"");
return 0;
}
一种更简洁的方式来编写 checkPal()
会是,
bool checkPal(const char *first){
const char *last = first + strlen(first);
while (first < last) {
if (*first++ != *--last) {
return false;
}
}
return true;
}
last
指向 \0
特点。在我们开始比较之前,减法是必要的。要清楚地了解发生了什么,您必须知道优先级和一些规则。
first<last
部分是显而易见的。我们一直在比较,直到达到我们 first > last
的地步。 (对于偶数长度的字符串)或 first = last
(对于奇数长度的字符串)。
if
有点棘手。 *first++
涉及两个运营商。 *
(间接)和 ++
(后增量)。
和++
的优先级高于取消引用 *
.
所以 *first++
将是 - 首先是递增的。然后你可能会认为我们第一次漏掉了一个字符,但事实并非如此。后缀表达式的值是我们做 first++
之前的值.现在您有了第一个字符。
同理*--last
将具有相同的效果,只是前缀表达式的值是操作后的值。所以你正在考虑最后一个字符。
如果匹配,我们继续。 first
和 last
已经包含修改后的值。我们对较小的子字符串中的其余字符重复相同的逻辑。
如果发生不匹配,我们会立即返回。 (因为它不是回文)。