簡體   English   中英

具有尾遞歸功能的堆棧溢出C ++

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

該代碼的作用:
下面的代碼應該通過限制每行代碼中的字符數而不丟失任何代碼來格式化打印機的.cpp文件。 該代碼應該逐個通過char文件。 通過打開ifstream然后使用get方法來獲取每個字符,直到找到EOF為止。 抓取每個字符時,將其推入一個std::stringvector ),然后增加行字符數。 如果在行字符計數大於最大大小之前找到了新的行字符,它將被重置並在下一行繼續。 如果在找到'\\n' n'char之前,行的char計數比最大char計數少2,則將\\\\n' ' '的(x制表符計數)追加到要寫入的string的末尾。 然后,將行的其余部分附加到string 但是,如果添加到string的最后一個字符不是' ' char,則該string會刪除其末尾和最接近左側' '之間的所有字符' ' char並放置在新行的開頭,即5 ' '在新行字符。 最后一點是我認為錯誤所在的位置。

示例行:(假裝大於最大字符數)

LongLong123 longLineOfCode;\n;

樣本輸出:

壞:

LongLong123 longLineOfCo\\n
      de;\n

好:

LongLong123\\n
      longLineOfCode;\n

錯誤:

SubmitFormater.exe中0x55CC1949(ucrtbased.dll)的未處理異常:0xC00000FD:堆棧溢出(參數:0x00000000,0x00F02000)。 發生了

示例命令行:

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

110是可以在一行中的字符數,5是制表符的字符數(5個空格),長字符串是要格式化的文件的地址(將文件復制為出錯時,輸入的文件將被銷毀)。 我正在使用構成該項目的代碼作為示例輸入(它的副本)。


編碼:

/* 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;
}


另外,您可以將上面的代碼用作示例.cpp文件。 不過請記住要使用副本,因為程序會修改文件!

調用堆棧的第1部分和第2部分 (單擊圖像即可讀取它們)

調用堆棧的第一部分 調用堆棧的第二部分



注意:
問題的原因已包含在對話中。

經過這篇文章的大量討論之后,我認為值得發布最終成為我解決方案的東西。 還有一些關於我得出的結論的注釋。

碼:

   /* 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;
}



筆記:

  • 該代碼僅在VS中作為發行版編譯時運行
  • while循環中存在邏輯錯誤
  • 編譯器優化似乎可以解決問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM