简体   繁体   English

具有尾递归功能的堆栈溢出C ++

[英]Stack Overflow with tail recursion function c++

What The Code Does: 该代码的作用:
The code below is supposed to format .cpp files for a printer, by limiting the number of chars in each line of code without losing any code. 下面的代码应该通过限制每行代码中的字符数而不丢失任何代码来格式化打印机的.cpp文件。 The code is supposed to go through the file char by char. 该代码应该逐个通过char文件。 It does so by opening an ifstream then using the get method to get each char till the EOF is found. 通过打开ifstream然后使用get方法来获取每个字符,直到找到EOF为止。 As each char is grabbed it is pushed to a std::string ( vector ) as each char is pushed, a line char count is incremented. 抓取每个字符时,将其推入一个std::stringvector ),然后增加行字符数。 If a new line char is found before the line char count is larger than it's max size, it is reset and continues on the next line. 如果在行字符计数大于最大大小之前找到了新的行字符,它将被重置并在下一行继续。 If the line char count is 2 less than the max char count before a '\\n' char is found a \\ , \\n , ' ' 's(x tab count) are appended to the end of the string being written to. 如果在找到'\\n' n'char之前,行的char计数比最大char计数少2,则将\\\\n' ' '的(x制表符计数)追加到要写入的string的末尾。 Then the rest of the line is appended to the string . 然后,将行的其余部分附加到string Though, if the last char added to the string is not a ' ' char then the string has all the chars between it's end and the closest to the left ' ' char removed and placed at the start of the new line, after the 5 ' ' chars on the new line. 但是,如果添加到string的最后一个字符不是' ' char,则该string会删除其末尾和最接近左侧' '之间的所有字符' ' char并放置在新行的开头,即5 ' '在新行字符。 The last bit is where I think the error is. 最后一点是我认为错误所在的位置。

Sample Line: (pretend is bigger than max char count) 示例行:(假装大于最大字符数)

LongLong123 longLineOfCode;\n;

Sample Output: 样本输出:

Bad: 坏:

LongLong123 longLineOfCo\\n
      de;\n

Good: 好:

LongLong123\\n
      longLineOfCode;\n

The Error: 错误:

Unhandled exception at 0x55CC1949 (ucrtbased.dll) in SubmitFormater.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00F02000). SubmitFormater.exe中0x55CC1949(ucrtbased.dll)的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000000,0x00F02000)。 occurred 发生了

Sample Command line: 示例命令行:

110 5 "C:/Users/holycatcrusher/Documents/OC 2018 Fall/222/Labs/COSC_222_Data_Structures_Cpp/SubmitFormater.cpp"

The 110 is the number of chars that can be in a line, the 5 is the number of chars the tab is (5 blank spaces), and the long string is the address of the file to be formatted (make a copy of file as upon error the file entered will be destroyed). 110是可以在一行中的字符数,5是制表符的字符数(5个空格),长字符串是要格式化的文件的地址(将文件复制为出错时,输入的文件将被销毁)。 I am using the code that makes up this project as sample input (a copy of it). 我正在使用构成该项目的代码作为示例输入(它的副本)。


The code: 编码:

/* SubmitFormater.cpp
    This file was created by Bradley Honeyman
    Oct 25, 2018

    This file is used to format submit files for COSC 222 asignments

*/

#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdbool.h>
#include <stddef.h>

#define _CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>

std::string *processFile(std::ifstream *input, int maxCharCount, int tabSpaceSize, char delimiter, std::string *code, int lineCharCount);
int toInt(char *input);

int main(int argc, char **argv) {

    std::cout << "Running 222 formatter" << std::endl << "by: Bradley Honeyman" << std::endl;

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    //make sure there is the min number of commands
    if (argc < 3) {
        std::cout << "Ensure there is a specified max line length and at least one file to modify!" << std::endl;
        return 0;
    }

    for (int i = 3; i < argc; i++) {

        //open file and make sure it opens
        std::ifstream input;
        input.open(argv[i]);
        if (!input.is_open()) {
            std::cout << "Could not open the input file: " << argv[i] << std::endl;
            return EXIT_FAILURE;
        }

        //process code
        std::string *code = new std::string();
        processFile(&input, toInt(argv[1]), toInt(argv[2]), ' ', code, 0);

        //check for error 
        if (code == NULL) {
            return EXIT_FAILURE;
        }

        //output
        input.close();
        std::ofstream out(argv[i]);
        if (!out.is_open()) {
            std::cout << "could not write to output file" << std::endl;
            return EXIT_FAILURE;
        }

        //print to file
        std::cout << code->c_str() << std::endl;
        out << code->c_str();

        //close out delete code pointer
        out.close();
        delete code;

    }

    return 0;
}

/*
    formats a file by placing \\\n the custom tab whereever the length of a line is bigger than the max
    also a delimiter is used, so words aren't cut in half
*/
#define FORMAT_CHAR_COUNT 2
std::string *processFile(std::ifstream *input, int maxCharCount, int tabSpaceSize, char delimiter, std::string *code, int lineCharCount) {

    //std::cout << "Processing" << std::endl;

    //get char and check if is end of file
    char current = input->get();
    //std::cout << "\'" << current << "\'" << std::endl;
    if (input->eof()) {
        return code;
    }

    //incerment char count then check if are at furthest possible position
    lineCharCount++;
    //std::cout << lineCharCount << std::endl;
    if (current == '\n') {
        lineCharCount = 0;

        //check if are at max char count, split code and put to new line
    } else if (lineCharCount >= maxCharCount && current != '\\') {

        //if not at the end of the line go back to the closest delimiter to break
        std::string *pre = new std::string("");
        bool fail = false;
        if (current != '\n' && code->at(code->size() - 1)) {
            code->push_back(current);
            int i = code->size() - 1;
            int back = 0;
            for (i; i >= 0; i--) {
                pre->push_back(code->at(i));
                back++;
                if (back > maxCharCount - tabSpaceSize - FORMAT_CHAR_COUNT) {
                    std::cout << "Can not format file because there isn't a place close enough to break at a delimiter!" << std::endl;
                    fail = true;
                    break;
                }
            }

            //check for fail
            if (!fail) {

                //add delimiter if it needs to be
                if (pre->size() > 0 && pre->at(pre->size() - 1) != delimiter) {
                    pre->push_back(delimiter);
                }

                //reverse prepending string, and remove code that is to be prepended
                std::reverse(pre->begin(), pre->end());
                code->assign(code->substr(0, code->size() - back - 1));

            }
        }

        //insert \ then new line then tab then set char count to tab size + pre size + 1 for char to be added
        code->push_back('\\');
        code->push_back('\n');
        for (int i = 0; i < tabSpaceSize; i++) { code->push_back(' '); } //create tab
        code->append(pre->c_str());
        lineCharCount = tabSpaceSize + 1 + pre->size();
        pre->clear();
        delete pre;

    }

    //add char to code and run again
    code->push_back(current);

    return processFile(input, maxCharCount, tabSpaceSize, delimiter, code, lineCharCount);
}

/*
    converts string to an int
*/
int toInt(char *input) {
    int i = 0;
    int out = 0;
    while (input[i] != '\0') {
        out = (out * 10) + (input[i] - '0');
        i++;
    }
    return out;
}


Also, you can use the code above code as the sample .cpp file. 另外,您可以将上面的代码用作示例.cpp文件。 Do remember to use a copy though, because the program will modify the file! 不过请记住要使用副本,因为程序会修改文件!

Call Stack Part 1 and 2 (click images to be able to read them) 调用堆栈的第1部分和第2部分 (单击图像即可读取它们)

调用堆栈的第一部分 调用堆栈的第二部分



Note: 注意:
The cause of the problem is covered in the conversation. 问题的原因已包含在对话中。

After the amount of talking that went on this post I think It is worth posting what ended up being the solution for me. 经过这篇文章的大量讨论之后,我认为值得发布最终成为我解决方案的东西。 Also a few notes on what I concluded. 还有一些关于我得出的结论的注释。

Code: 码:

   /* SubmitFormater.cpp
    This file was created by Bradley Honeyman
    Oct 25, 2018

    This file is used to format submit files for COSC 222 asignments

*/

#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdbool.h>
#include <stddef.h>

#define _CRTDBG_MAP_ALLOC  
#include <stdlib.h>  
#include <crtdbg.h>

std::string *processFile(std::ifstream *input, int maxCharCount, int tabSpaceSize, char delimiter, std::string *code, int lineCharCount);
int toInt(char *input);

int main(int argc, char **argv) {

    std::cout << "Running 222 formatter" << std::endl << "by: Bradley Honeyman" << std::endl;

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    //make sure there is the min number of commands
    if (argc < 3) {
        std::cout << "Ensure there is a specified max line length and at least one file to modify!" << std::endl;
        return 0;
    }

    for (int i = 3; i < argc; i++) {

        //open file and make sure it opens
        std::ifstream input;
        input.open(argv[i]);
        if (!input.is_open()) {
            std::cout << "Could not open the input file: " << argv[i] << std::endl;
            return EXIT_FAILURE;
        }

        //process code
        std::string *code = new std::string();
        processFile(&input, toInt(argv[1]), toInt(argv[2]), ' ', code, 0);

        //check for error 
        if (code == NULL) {
            return EXIT_FAILURE;
        }

        //output
        input.close();
        std::ofstream out(argv[i]);
        if (!out.is_open()) {
            std::cout << "could not write to output file" << std::endl;
            return EXIT_FAILURE;
        }

        //print to file
        out << code->c_str();

        //close out delete code pointer
        out.close();
        delete code;

    }

    return 0;
}

/*
    formats a file by placing \\\n the custom tab whereever the length of a line is bigger than the max
    also a delimiter is used, so words aren't cut in half
*/
#define FORMAT_CHAR_COUNT 2
std::string *processFile(std::ifstream *input, int maxCharCount, int tabSpaceSize, char delimiter, std::string *code, int lineCharCount) {

    //get char and check if is end of file
    char current = input->get();
    if (input->eof()) {
        return code;
    }

    //incerment char count then check if are at furthest possible position
    lineCharCount++;
    //std::cout << lineCharCount << std::endl;
    if (current == '\n') {
        lineCharCount = 0;

        //check if are at max char count, split code and put to new line
    } else if (lineCharCount >= maxCharCount && current != '\\') {

        //if not at delimiter push everything to the right of the nearest delimiter to the left to pre
        int back = 0;
        std::string pre("");
        if (current != delimiter) {
            for (int i = code->size() - 1; i >= 0; i--) {
                back++;
                if (code->at(i) == delimiter) {
                    pre.push_back(code->at(i));
                    break;

                } else {
                    pre.push_back(code->at(i));

                }

            }

            //remove what was added to pre from code
            std::reverse(pre.begin(), pre.end());
            code->assign(code->substr(0, code->size() - back));

        }

        //insert \ then new line then tab then set char count to tab size + pre size + 1 for char to be added
        code->push_back('\\');
        code->push_back('\n');
        for (int i = 0; i < tabSpaceSize; i++) { code->push_back(' '); } //create tab
        code->append(pre);
        lineCharCount = tabSpaceSize + 1 + pre.size();

    }

    //add char to code and run again
    code->push_back(current);
    return processFile(input, maxCharCount, tabSpaceSize, delimiter, code, lineCharCount);
}

/*
    converts string to an int
*/
int toInt(char *input) {
    int i = 0;
    int out = 0;
    while (input[i] != '\0') {
        out = (out * 10) + (input[i] - '0');
        i++;
    }
    return out;
}



Notes: 笔记:

  • The code only runs when compiled as a release version in VS 该代码仅在VS中作为发行版编译时运行
  • There was a logical error in the while loop while循环中存在逻辑错误
  • Compiler Optimization seems to solve the problem 编译器优化似乎可以解决问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM