C ++递归和指针问题

问题描述 投票:2回答:3

首先,这是一项任务。

需要什么:

1.Take in string input
2. copy string (stripping out white space, punctuation, and 
   covert all characters to uppercase in the process)
3. Then determine if this copied string is a palindrome.

确定回文所需的方法:

Base Case:  string length is <= 1
General Case: if first letter != last letter, false, otherwise
               point to next letter and write '\0' to last letter and
               call the method again

例如:

RACECAR\0   R==R
ACECA\0     A==A
CEC\0       C==C
E\0         E <= 1  TRUE!

我无法让我的isPalindrome功能正常工作。据我所知,其他所有事情都是现实的。我真的认为问题在于我的递归调用。我已经调试了2天了,我无法弄清楚返回错误的原因。任何帮助将不胜感激。我不是在寻找帮助,也许只是对这段代码的额外关注。谢谢。

#include <iostream>
#include <string>
#include <cctype>   
using namespace std;

int charCount(char  * copy)
{
    int count = 0;

    for (int i = 0; copy[i] != '\0'; i++)
    {
        count++;
    }

    return count;
}

bool isPalindrome(char *copy)
{
    bool result = false;
    int size = charCount(copy);

    char * last = &copy[size - 1];

    if (size <= 1)
    {
        result = true;
    }

    if (copy != last)
    {
        result = false;
    }

    else
    {
        ++copy;
        last = '\0';
        isPalindrome(copy);
    }

    return result;
}

void stringCopy(char * source, char * destination)
{
    int sourceIndex = 0;
    int destIndex = 0;

    while (source[sourceIndex] != '\0')
    {
        while (!(isalnum(source[sourceIndex])) && source[sourceIndex] != '\0')
        {
            sourceIndex++;
        }

        if (source[sourceIndex] == '\0')
        {
            break;
        }

        if (isalpha(source[sourceIndex]))
        {
            destination[destIndex] = toupper(source[sourceIndex]);
        }

        if (isdigit(source[sourceIndex]))
        {
            destination[destIndex] = source[sourceIndex];
        }

        sourceIndex++;
        destIndex++;
    }

    destination[destIndex] = '\0';
}

int main()
{
    string input = "";

    cout << "Enter a string: ";
    getline(cin, input);

    char * source = &input[0];
    int sourceSize = charCount(source);

    char * copy = new char[sourceSize];

    stringCopy(source, copy);

    int copySize = charCount(copy);

    if (isPalindrome(copy))
    {
        cout << input << " is a palindrome!" << endl;
    }

    else
    {
        cout << input << " is not a palindrome" << endl;
    }

    return 0;
}
c++ pointers recursion palindrome
3个回答
1
投票

四个错误

首先你有三种情况,但你只想要一个执行,所以它应该是一个if ... else if ... else ...语句,而不是你拥有的if ... if ... else ...语句。

其次,你的比较是不正确的,因为你正在比较指针而不是它们指向的字符。

当您尝试缩短指向不指向字符的指针的字符串时,第三个错误类似于第二个错误。

最后,您忘记将递归调用的结果分配给result变量。相当常见的新手错误。

这是我的努力(未经测试的代码)

bool isPalindrome(char *copy)
{
    bool result = false;
    int size = charCount(copy);

    char * last = &copy[size - 1];

    if (size <= 1)
    {
        result = true;
    }
    else if (*copy != *last) // else if and *copy != *last, not copy != last
    {
        result = false;
    }
    else
    {
        ++copy;
        *last = '\0'; // *last not last
        result = isPalindrome(copy); // capture return value from recursive call
    }

    return result;
}

一个函数中的四个错误可能看起来很多,但这些错误很容易修复。整体代码质量非常好。

现在为了额外的功劳,看看你是否可以编写一个不会破坏字符串的版本。因为您指定*last = '\0',所以在工作时更改字符串。


1
投票

复制!=最后

这些变量是char的指针。在比较之前,您需要取消引用它们。

尝试:* copy!= * last


0
投票

这不会针对代码中的任何问题,也不会显示如何根据分配编写代码。代码仅用于完整性,以展示如何使用c ++已经提供的工具解决问题,而无需重新发明轮子。

std::copy_ifstd::transform是你的stringCopystd::equal与向后和向前运算符基本上是你在isPalindrome做的。无论如何,对这种情况使用递归并不是一个好主意。

#include <string>
#include <algorithm>
#include <iostream>


bool is_palindrom( const std::string &input ) {
    std::string copy;

    // copy everything except spaces and punctations using:
    // copy_if, isspace and ispunct
    std::copy_if(input.begin(), input.end(), std::back_inserter(copy), [] (int ch) -> bool {
        return !::isspace(ch) && !::ispunct(ch);
    });

    // transform to uppercase
    std::transform(copy.begin(), copy.end(), copy.begin(), ::toupper);

    // check if palindrom using iterators and revers iterators
    // copy.end()  - halfway is valid as std::string::iterator is a random access iterator
    size_t halfway = copy.size() / 2;
    bool isPalindrom = std::equal(copy.begin(),  copy.end()  - halfway, 
                                  copy.rbegin(), copy.rend() - halfway);

    return isPalindrom;
}

int main() {
    std::cout <<  is_palindrom("2aba2")  << std::endl; // 1
    std::cout <<  is_palindrom("2 ab a2")  << std::endl; // 1
    std::cout <<  is_palindrom("2 abb a2")  << std::endl; // 1
    std::cout <<  is_palindrom("abca")  << std::endl; // 0
}
© www.soinside.com 2019 - 2024. All rights reserved.