c - 如何在c中使用指针获取回文?

标签 c pointers palindrome

很抱歉,我不能流利地使用英语,因为我不会说英语。

我想要得到回文,例如“一个人,一个计划,一条运河,巴拿马!”或“我看到的是汽车还是猫?”

今天学习了C语言中的指针。所以我编写了代码来获取回文。

#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;
}

但是,存在逻辑错误。 当我输入任何内容时,输出总是回文。

不知道哪里出错了。

例如, 为了得到“一个人,一个计划,一条运河,巴拿马!”,我删除了(忽略)“空格”和“标点符号”,将大写字母改为小写字母。 (阿马纳普拉纳卡纳尔巴拿马) 但是,当我输入“abcdef”时,我还得到“[abcedf] 是回文。”

最佳答案

我不是在这里判断您的代码的效率(请参阅评论以获取有关如何改进算法的一些建议),但您的代码中有许多可以修复的“简单”错误。

下面的代码是您自己的最小修改,可以使用,其中我进行了更改,其中包含三斜杠 (///) 注释:

#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;
}

当您了解所需更改背后的原因时,我可能会发布一个“附录”,建议一些效率/风格改进。

附录:

好的,您在问题中声明您正在研究 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
}

和以前一样,请随时要求对所使用的代码或概念进行任何进一步的澄清和/或解释。

关于c - 如何在c中使用指针获取回文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58858550/

相关文章:

python - 为什么列表理解生成的列表是空的

c# - 如何找到给定字符串中最长的回文?

C - 不寻常的数组初始化

c - 具有结构的链表

c++ - int (*p)[3] 和 int *p[3] 有什么区别?

c - 基本内存地址混淆

java - 从两个三位数的乘积中优化最大的回文数?

c - 未父窗口无法设置HMENU ID?

c - 当我用 char 指针复制字符串时返回 null

c++ - 如何检查指针是否仍然指向 C++ 中的有效内存?