2

我制作了一个程序,通过从 .txt 文件中读取来搜索回文,然后将输出放到单独的 .txt 文件中。

它的工作原理与大约 50 个左右的字符一样。但是,如果我将大量单词复制并粘贴到 .txt 文件中以供其读取,则在运行时它将显示“由于 StackOverFlowException 而终止进程”。然后它会打开一个名为 chkstk.asm 的文件,并有一个箭头指向一个名为“test dword ptr [eax], eax ; probe page”的东西。接下来,一个框会出现一个中断并继续选项,并说:“palindrone.exe 中发生了 'System.StackOverflowException' 类型的未处理异常”

我目前正在努力改变事物以使用指针等,并可能将事物存储在向量中。但是,我仍然不确定错误的原因是什么,我想知道它为什么会起作用以及需要更改什么,以便我可以让它读取和处理大块文本。没有指针是它工作不正常的原因吗?

#include <iostream>
#include <string>
#include <ctype.h>
#include <iterator>
#include <algorithm>
#include <fstream>

using namespace std;

/**
    Recursivly reverses a string
    @ param word, the word being entered
    @ last_char, the last character currently in the string
    @ go, the recursive function to return the character and continue inside itself
**/
string string_reverse(string word)
{
    if (word.length() - 1 > 0)
    {
        char last_char = word[word.length()-1];
        word.erase(word.length()-1);
        string go = string_reverse(word);
        return go.insert(0, 1, last_char);
    }
    else  
        return word.substr(0,1);
}

/**
@param in, the input as the original string
@param la, the reverse string
**/
bool equals(string in, string la)
{
    if(in == la)
        return true;
    else 
        return false;
}

/**
processes the pal
**/
void process_pal(ofstream &outfile, string in, string la, bool sam)
{
    if (sam == true)
    {
        outfile << in << " EQUAL to backwards: " << la << "\n";
    }
    else
        outfile << in << " NOT equal to backwards: " << la << "\n";
}

/**
    Removes all Numbers, white spaces, and invalid symbols with !isalpha
    @param sentence, the sentence being entered
    @ it, the iterator to iterator through the sentence checking for invlaid sysmbols
**/
string remover(string sentence)
{
    string::iterator it = sentence.begin();

    while (it != sentence.end())
    {
         while( it != sentence.end() && !isalpha(*it))
         {
             it = sentence.erase(it);
         }
         if (it != sentence.end())
             ++it;
    }
return sentence;
}

/**
    Increments to find paladrome by starting at 3 from 0, then moving right 1 by 3 each time util
    it goes to the end. Once it hits the end, it will increment by four and do the same thing till
    it has become the full length of the text.
**/
void find_pal(ofstream &outfile, string input, int pos, int lin)
{
    int max_length = input.length()+1;
    int pos_last = max_length - lin;
    if(lin < input.length()){
        string sub_fwrd = input.substr(pos,lin);
        string sub_bck = string_reverse(sub_fwrd);
        bool same = equals(sub_fwrd, sub_bck);
        process_pal(outfile, sub_fwrd, sub_bck, same);
        pos++;
        if (pos == pos_last){
            pos = 0;
            lin++;
        }
        find_pal(outfile, input, pos, lin);
}
}

int main()
{
    bool con = true;
    while (con == true)
    {
        string input;
        ifstream infile;
        infile.open ("file_read.txt");    
        getline(infile,input); // Saves the lines from the file in string input.
        infile.close();

        transform(input.begin(), input.end(), input.begin(), ::tolower); // Goes to all Lower Case

        string inputer = remover(input); // Removes unwanted symbols, numbers, spaces, etc
        input = inputer; // Updates our orignal string input

        ofstream outfile ("file_out.txt");
        int pos = 0;
        int lin = 3;
        find_pal(outfile, input, pos, lin); // Start the palindron function up to sift       through purmutations

        string full_input = string_reverse(input); // Final Purmutation of reverse
        bool same = equals(input, full_input);
        process_pal(outfile, input, full_input, same); // Final analyzing process_pal

        string go;
        outfile.close();    
        cout << "Continue? y/n " << endl; // Continue on or not
        getline(cin, go);
        if(go != "y")
            con = false;
    }
    system("pause");
    return 0;
}
4

1 回答 1

1

在 C/C++ 中有一个堆栈和一个堆。堆栈通常是一个固定大小的内存段,它可能比您想象的要小(默认值可能在 1-2MB 左右),而堆是内存的一个动态部分,它会一直增长直到超过总逻辑 RAM服务器。

对您的问题的简短回答是,每次嵌套函数调用时,您都会在所谓的“堆栈帧”中分配更多的内存。因此,如果您有“主要调用 A 调用 B 再次调用 B”,那么您有 4 个堆栈帧。如果您有一个随着输入大小而增长的递归方法,那么您将开始分配大量堆栈帧,最终您将遇到堆栈溢出异常(堆栈大小已超过固定限制)。

所以,一般来说,你的问题的根本原因是你的递归嵌套太深。有几种方法可以解决这个问题。评论中提到的一种常见方法是简单地放弃递归。另一种方法是使用尾递归,它避免在每次调用时添加新的堆栈帧,并允许您保持递归语义。

话虽如此,我应该提一下,如果您要切换到指针,您可能会看到一点好处。这是因为堆栈帧的大小取决于函数参数和局部变量的大小。指针可能小于您传入的其他结构,并可能导致更小的堆栈帧。但是,这不是您的问题的根本原因。

于 2013-04-18T04:02:34.863 回答