如何在c中使用指针获取回文?
How to get palindromes using pointer in c?
很抱歉,我不会说英语,所以不能流利地使用英语。
我想要得到"A man, a plan, a canal, Panama!"或者"Was it a car or a cat I saw?"
这样的回文
今天学习了C中的Pointer。所以我编写了代码来获取回文。
#include <ctype.h>
/**
* @brief : Check if the given str is a palindrome
* @return: 1 if the given str is a palindrome, zero otherwise
* @param : str - pointers to the null-terminated byte string to check
*/
int ispalindrome(char *str)
{
int i, j;
char *pal;
for(i=0 ; *str!=0; i++) {
if(ispunct(*str)){ //if *str is punctuation mark, do not anything.
str++;
}
else if(isupper(*str)){ //if *str is a capital letter, change it to small letter and *pal=*str
*pal = tolower(*str);
str++;
pal++;
}
else //if *str is a small letter or a digit, *pal=*str
*pal = *str;
str++;
pal++;
}
for(j=0; pal[j]==pal[i-(j+1)] && j<=i/2; j++) //compare pal
;
if(j>i/2)
return 1;
return 0;
}
int main(void)
{
char buffer[1024];
int i;
gets(buffer);
printf("[%s] is ", buffer);
if (ispalindrome(buffer))
puts("a palindrome");
else
puts("not a palindrome");
return 0;
}
但是,逻辑错误。
当我输入任何东西时,输出总是回文。
不知道哪里出错了
例如,
对于 get "A man, a plan, a canal, Panama!",我删除(忽略)'space' 和 'punctuation marks',将大写字母更改为小写字母。 (amanaplanacanal巴拿马)
但是,当我输入 'abcdef' 时,我也得到了“[abcedf] 是回文。”
我不是来评判您代码的效率的(请参阅评论以获取有关如何改进算法的一些建议),但您的代码中有许多 'simple' 错误可以修复。
下面的代码是您自己的 最小 修改,我所做的更改带有三斜杠 (///) 注释:
#include <stdio.h>
#include <ctype.h>
int ispalindrome(char* str)
{
int i, j, k = 0; /// We need "k" to count the length of our PROCESSED string
char testBuffer[1024]; /// We need an ACTUAL BUFFER for our processed string ...
char* pal = &testBuffer[0];/// ... and start with "pal" pointing to the first element!
for (i = 0; *str != 0; i++) {
if (ispunct(*str) || isspace(*str)) { ///if *str is punctuation mark OR A SPACE, do not anything.
str++;
}
else if (isupper(*str)) { //if *str is a capital letter, change it to small letter and *pal=*str
*pal = tolower(*str);
str++;
pal++;
++k; /// Increase length of test string!
}
else { ///if *str is a small letter or a digit, *pal=*str
*pal = *str;
str++;
pal++;
++k; /// Increase length of test string!
}/// I think you forgot to include the { and }!
}
/// You left 'pal' pointing to a yet-to-be-filled character ...
pal = &testBuffer[0];/// We MUST reset "pal" to point at the BEGINNING of testBuffer!
/// "k" is the length of our processed string … NOT "i"...
for (j = 0; pal[j] == pal[k - (j + 1)] && j <= k / 2; j++) //compare pal
;
if (j > k / 2) return 1;/// Again, use "k" not "i"
return 0;
}
int main(void)
{
char buffer[1024];
// int i; /// This is never used!
// gets(buffer); /// This is an obsolete (and dangerous) function...
fgets(buffer, 1024, stdin); /// Use this instead!
printf("[%s] is ", buffer);
if (ispalindrome(buffer))
puts("a palindrome");
else
puts("not a palindrome");
return 0;
}
当您了解所需更改背后的原因后,我可能会 post 一个 'appendix' 建议一些 efficiency/style 改进。
附录:
好的,您在问题中声明您正在研究 C
中的指针,所以这里是您的代码版本,可以让您了解字符串指针可以做什么和不能做什么。我并不是说这是最有效的方法,但希望能帮助您理解基本概念:
int ispalindrome(const char* str) // Not required, but use of "const" is good to prevent accidentally changing
{ // something you shouldn't be changing (see next comment)
char* testBuffer = malloc(strlen(str)); // It maybe tempting to just re-use the given "str" buffer, but doing
if (testBuffer == NULL) return 0; // so would spoil any later display by the calling program!
// We should always check the return value of "malloc" but what do do in case of error is up to you
char* lastTest = testBuffer; // Keeps track of the index to the last character in test string
while (*str) // We could use while (*str != 0) but this does the same and is more succinct!
{
if (isalnum(*str)) // Rather than check for what we don't what, check for what we do want ...
{ // The "isalnum" function is TRUE for any letter or digit, FALSE otherwise
*lastTest++ = tolower(*str); // The "tolower" funtion will leave uppercase and digits unchanged
// Note: The "++" (post-increment) operator will increase "lastTest" AFTER we have assigned to it
}
++str; // Move to the next character in our input string
}
// At this point, "lastTest" points to one beyond the last character in our processed string. We can loop using
// this as a pointer to our 'right-hand' compare (after we decrement it) and a 'local' pointer to our 'left-hand'
// compare (initialised to the first element of "testBuffer") ...
char* lhCompare;
for (lhCompare = testBuffer; (--lastTest > lhCompare) && (*lastTest == *lhCompare); ++lhCompare)
;
// Note: It is perfectly 'correct' and legal in C to compare two pointers to the same type! So, rather than
// keeping track of string lengths and indexes, we can just compare the 'lastTest' and 'rhCompare' addresses
// to see if we have reached/crossed the middle of the test string.
free(testBuffer); // Always call "free" to release memory allocated by "malloc" when you're done with it
// In the test below, we can still use the pointer values, even though the memory they refer to is no longer
// valid. But we CANNOT dereference them, with something like: char a = *lhCompare to get the 'middle' letter!
return (lhCompare >= lastTest); // Comparison will be TRUE (= 1) if our letters all match, FALSE (0) otherwise
}
如前所述,请随时要求进一步说明and/or对所用代码或概念的解释。
很抱歉,我不会说英语,所以不能流利地使用英语。
我想要得到"A man, a plan, a canal, Panama!"或者"Was it a car or a cat I saw?"
这样的回文今天学习了C中的Pointer。所以我编写了代码来获取回文。
#include <ctype.h>
/**
* @brief : Check if the given str is a palindrome
* @return: 1 if the given str is a palindrome, zero otherwise
* @param : str - pointers to the null-terminated byte string to check
*/
int ispalindrome(char *str)
{
int i, j;
char *pal;
for(i=0 ; *str!=0; i++) {
if(ispunct(*str)){ //if *str is punctuation mark, do not anything.
str++;
}
else if(isupper(*str)){ //if *str is a capital letter, change it to small letter and *pal=*str
*pal = tolower(*str);
str++;
pal++;
}
else //if *str is a small letter or a digit, *pal=*str
*pal = *str;
str++;
pal++;
}
for(j=0; pal[j]==pal[i-(j+1)] && j<=i/2; j++) //compare pal
;
if(j>i/2)
return 1;
return 0;
}
int main(void)
{
char buffer[1024];
int i;
gets(buffer);
printf("[%s] is ", buffer);
if (ispalindrome(buffer))
puts("a palindrome");
else
puts("not a palindrome");
return 0;
}
但是,逻辑错误。 当我输入任何东西时,输出总是回文。
不知道哪里出错了
例如, 对于 get "A man, a plan, a canal, Panama!",我删除(忽略)'space' 和 'punctuation marks',将大写字母更改为小写字母。 (amanaplanacanal巴拿马) 但是,当我输入 'abcdef' 时,我也得到了“[abcedf] 是回文。”
我不是来评判您代码的效率的(请参阅评论以获取有关如何改进算法的一些建议),但您的代码中有许多 'simple' 错误可以修复。
下面的代码是您自己的 最小 修改,我所做的更改带有三斜杠 (///) 注释:
#include <stdio.h>
#include <ctype.h>
int ispalindrome(char* str)
{
int i, j, k = 0; /// We need "k" to count the length of our PROCESSED string
char testBuffer[1024]; /// We need an ACTUAL BUFFER for our processed string ...
char* pal = &testBuffer[0];/// ... and start with "pal" pointing to the first element!
for (i = 0; *str != 0; i++) {
if (ispunct(*str) || isspace(*str)) { ///if *str is punctuation mark OR A SPACE, do not anything.
str++;
}
else if (isupper(*str)) { //if *str is a capital letter, change it to small letter and *pal=*str
*pal = tolower(*str);
str++;
pal++;
++k; /// Increase length of test string!
}
else { ///if *str is a small letter or a digit, *pal=*str
*pal = *str;
str++;
pal++;
++k; /// Increase length of test string!
}/// I think you forgot to include the { and }!
}
/// You left 'pal' pointing to a yet-to-be-filled character ...
pal = &testBuffer[0];/// We MUST reset "pal" to point at the BEGINNING of testBuffer!
/// "k" is the length of our processed string … NOT "i"...
for (j = 0; pal[j] == pal[k - (j + 1)] && j <= k / 2; j++) //compare pal
;
if (j > k / 2) return 1;/// Again, use "k" not "i"
return 0;
}
int main(void)
{
char buffer[1024];
// int i; /// This is never used!
// gets(buffer); /// This is an obsolete (and dangerous) function...
fgets(buffer, 1024, stdin); /// Use this instead!
printf("[%s] is ", buffer);
if (ispalindrome(buffer))
puts("a palindrome");
else
puts("not a palindrome");
return 0;
}
当您了解所需更改背后的原因后,我可能会 post 一个 'appendix' 建议一些 efficiency/style 改进。
附录:
好的,您在问题中声明您正在研究 C
中的指针,所以这里是您的代码版本,可以让您了解字符串指针可以做什么和不能做什么。我并不是说这是最有效的方法,但希望能帮助您理解基本概念:
int ispalindrome(const char* str) // Not required, but use of "const" is good to prevent accidentally changing
{ // something you shouldn't be changing (see next comment)
char* testBuffer = malloc(strlen(str)); // It maybe tempting to just re-use the given "str" buffer, but doing
if (testBuffer == NULL) return 0; // so would spoil any later display by the calling program!
// We should always check the return value of "malloc" but what do do in case of error is up to you
char* lastTest = testBuffer; // Keeps track of the index to the last character in test string
while (*str) // We could use while (*str != 0) but this does the same and is more succinct!
{
if (isalnum(*str)) // Rather than check for what we don't what, check for what we do want ...
{ // The "isalnum" function is TRUE for any letter or digit, FALSE otherwise
*lastTest++ = tolower(*str); // The "tolower" funtion will leave uppercase and digits unchanged
// Note: The "++" (post-increment) operator will increase "lastTest" AFTER we have assigned to it
}
++str; // Move to the next character in our input string
}
// At this point, "lastTest" points to one beyond the last character in our processed string. We can loop using
// this as a pointer to our 'right-hand' compare (after we decrement it) and a 'local' pointer to our 'left-hand'
// compare (initialised to the first element of "testBuffer") ...
char* lhCompare;
for (lhCompare = testBuffer; (--lastTest > lhCompare) && (*lastTest == *lhCompare); ++lhCompare)
;
// Note: It is perfectly 'correct' and legal in C to compare two pointers to the same type! So, rather than
// keeping track of string lengths and indexes, we can just compare the 'lastTest' and 'rhCompare' addresses
// to see if we have reached/crossed the middle of the test string.
free(testBuffer); // Always call "free" to release memory allocated by "malloc" when you're done with it
// In the test below, we can still use the pointer values, even though the memory they refer to is no longer
// valid. But we CANNOT dereference them, with something like: char a = *lhCompare to get the 'middle' letter!
return (lhCompare >= lastTest); // Comparison will be TRUE (= 1) if our letters all match, FALSE (0) otherwise
}
如前所述,请随时要求进一步说明and/or对所用代码或概念的解释。