尝试通过使用字符串来检查数字是否为回文
Trying to check if a number is a palindrome through the use of strings
我正在尝试检查输入的数字是否为回文。我是通过字符串而不是整数来完成的。所以,我正在接收一个字符串并将其反转为另一个字符串。但是,当我使用字符串比较函数时,它没有给我 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] = '[=10=]';
}
}
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;
}
问题是您没有正确处理字符串。你应该用 [=17=]
.
覆盖 '\n'
...
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")]='[=10=]'; // getting the length of the
// string without `\n`
// and overwriting with `[=10=]`
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
的长度,并用 [=17=]
覆盖了它。
0 1 2 3 4 5 --> indices
1 0 0 1 \n [=13=] --> strcspn(input,"\n") returns 4.
1 0 0 1 [=13=] [=13=] --> input[strcspn(input,"\n")]='[=13=]'
你可以像这样简单地做,而不需要复制和其他任何东西。
无需额外内存 - 进行回文检查
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")]='[=14=]';
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
指向 [=17=]
字符。在我们开始比较之前,减法是必要的。要清楚地了解发生了什么,您必须知道优先级和一些规则。
first<last
部分很明显。我们一直比较到 first > last
(对于偶数长度的字符串)或 first = last
(对于奇数长度的字符串)。
if
有点棘手。 *first++
涉及两个运算符。 *
(间接)和++
(post增量)。
并且 ++
的优先级高于取消引用 *
。
所以 *first++
将是 - 首先递增。然后你可能会认为我们第一次漏掉了一个字符,但事实并非如此。 postfix 表达式的值是我们执行 first++
之前的值。所以现在你有了第一个角色。
同理*--last
除了前缀表达式的值为运算后的值外,效果相同。所以你在考虑最后一个字符。
如果匹配,我们继续。 first
和 last
已包含修改后的值。我们对较小的子字符串中的其余字符重复相同的逻辑。
如果出现不匹配,我们会立即 return。 (因为它不是回文)。
对不起,我的错。试试这个:
#include <stdio.h>
#include <string.h>
// A function to check if a string str is palindrome
void isPalindrome(char str[])
{
// Start from leftmost and rightmost corners of str
int l = 0;
int h = strlen(str) - 1;
// Keep comparing characters while they are same
while (h > l)
{
if (str[l++] != str[h--])
{
printf("%s is Not Palindromen", str);
return;
}
}
printf("%s is palindromen", str);
}
// Driver program to test above function
int main()
{
isPalindrome("abba");
isPalindrome("abbccbba");
isPalindrome("geeks");
return 0;
}
这个有用吗?
一个变体,递归版本,没有更多的字符串作为参数(或原始字符串的副本)
int pal(char *s) {
int n = strlen(s);
if (n <= 1) return 1;
if (s[0] != s[n-1]) return 0;
s[n-1] = '[=10=]';
return pal(++s);
}
return 0:不是回文,1:是回文
请注意字符串已更改,因此如果有问题(或者如果字符串是在静态区域中创建的),您可以这样调用它
char *copy = malloc(strlen(string)+1); // string is original string
strcpy(copy, string);
int ispal = pal( copy );
printf("Is %s a palindrome\n", ispal ? "":"not");
我正在尝试检查输入的数字是否为回文。我是通过字符串而不是整数来完成的。所以,我正在接收一个字符串并将其反转为另一个字符串。但是,当我使用字符串比较函数时,它没有给我 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] = '[=10=]';
}
}
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;
}
问题是您没有正确处理字符串。你应该用 [=17=]
.
'\n'
...
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")]='[=10=]'; // getting the length of the
// string without `\n`
// and overwriting with `[=10=]`
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
的长度,并用 [=17=]
覆盖了它。
0 1 2 3 4 5 --> indices
1 0 0 1 \n [=13=] --> strcspn(input,"\n") returns 4.
1 0 0 1 [=13=] [=13=] --> input[strcspn(input,"\n")]='[=13=]'
你可以像这样简单地做,而不需要复制和其他任何东西。
无需额外内存 - 进行回文检查
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")]='[=14=]';
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
指向 [=17=]
字符。在我们开始比较之前,减法是必要的。要清楚地了解发生了什么,您必须知道优先级和一些规则。
first<last
部分很明显。我们一直比较到 first > last
(对于偶数长度的字符串)或 first = last
(对于奇数长度的字符串)。
if
有点棘手。 *first++
涉及两个运算符。 *
(间接)和++
(post增量)。
并且 ++
的优先级高于取消引用 *
。
所以 *first++
将是 - 首先递增。然后你可能会认为我们第一次漏掉了一个字符,但事实并非如此。 postfix 表达式的值是我们执行 first++
之前的值。所以现在你有了第一个角色。
同理*--last
除了前缀表达式的值为运算后的值外,效果相同。所以你在考虑最后一个字符。
如果匹配,我们继续。 first
和 last
已包含修改后的值。我们对较小的子字符串中的其余字符重复相同的逻辑。
如果出现不匹配,我们会立即 return。 (因为它不是回文)。
对不起,我的错。试试这个:
#include <stdio.h>
#include <string.h>
// A function to check if a string str is palindrome
void isPalindrome(char str[])
{
// Start from leftmost and rightmost corners of str
int l = 0;
int h = strlen(str) - 1;
// Keep comparing characters while they are same
while (h > l)
{
if (str[l++] != str[h--])
{
printf("%s is Not Palindromen", str);
return;
}
}
printf("%s is palindromen", str);
}
// Driver program to test above function
int main()
{
isPalindrome("abba");
isPalindrome("abbccbba");
isPalindrome("geeks");
return 0;
}
这个有用吗?
一个变体,递归版本,没有更多的字符串作为参数(或原始字符串的副本)
int pal(char *s) {
int n = strlen(s);
if (n <= 1) return 1;
if (s[0] != s[n-1]) return 0;
s[n-1] = '[=10=]';
return pal(++s);
}
return 0:不是回文,1:是回文
请注意字符串已更改,因此如果有问题(或者如果字符串是在静态区域中创建的),您可以这样调用它
char *copy = malloc(strlen(string)+1); // string is original string
strcpy(copy, string);
int ispal = pal( copy );
printf("Is %s a palindrome\n", ispal ? "":"not");