Joseph Morgan
Joseph Morgan

Reputation: 249

ifstream and ofstream: How do I perform multiple modifications to a file?

I've been googling this question for a few hours and can't seem to find anything that addresses it.

I'm reeaaaally hazy on file operations in C++, but I've spent about 20 of the last 36 hours reading documentation and forum questions trying to get a project for a friend together.

Say I've got a file called raw_questions.txt, and I'd like to make some changes to it. This file is a study guide for an exam, and has a question followed by 4 multiple-choice answers. I want to remove blank lines and add some tokens to allow another program I'm working on to parse it. I've written a formatter program to perform those operations. The operations are:

  1. Remove blank lines from source file as it appears it's double-spaced
  2. Add a delimiter character ('@') to the end of each question and answer.
  3. Using the delimiter, read each question and answer in as a string and append it to an output file with a token at the beginning of question or answer, which will let my other program know whether a line contains a question or answer.

My question: I'm stuck at how to move from one operation to the next. My current approach is to read each line into a string, perform the operation on the string, and to add the new string to an output file. Using this approach, to perform the next operation I have to open the previous operation's output file as my new input file, and make a new output file for that operation. I feel like there's got to be a better way, but like I said, I'm pretty hazy on file operations in C++. What should I be doing in this situation?

I've considered creating an ifstream and ofstream that both point to the same file, and hoping that when the ifstream file is opened, it will store a temporary copy in memory. Then, after I read line by line and write to my ofstream object, when it closes it will overwrite my old file. I don't know if that makes any sense, and I don't think that's even how fstream works.

The code that I have so far:

#include <fstream>
#include <string>
#include "Debug.h"

Debug debugger;

void remove_empty_lines (std::ifstream& input, std::ofstream& output);
void insert_delimiter (std::ifstream& input, std::ofstream& output, char delimiter);
void create_output (std::ifstream& input, std::ofstream& output);

int main() {
    debugger.set_active();

    char delimiter = '@';

    std::ifstream input;
    std::ofstream output;
    input.open("questions_source.txt");
    output.open("questions_intermidiate.txt");

    remove_empty_lines (input, output);

}

void remove_empty_lines (std::ifstream& input, std::ofstream& output) {
    while (!input.eof()) {
        std::string line;

        std::getline(input, line);
        if (line != "") {
            output << line << std::endl;
        }
    }
}

void insert_delimiter(std::ifstream& input, std::ofstream& output) {
}

// This function doesn't quite work, WIP - Please ignore
void create_output(std::ifstream& input, std::ofstream& output) {
    std::string line;

    for (int i = 1; !input.eof(); i++) {
        debugger.out("Inserting tokens.");
        bool found = false;
        while (!found) {
            getline (input, line);
            if (i < 10) {
                if (line[1] == ')') {
                    line.erase (0, 3);
                    output << "[" << i << "]" << line << std::endl;
                    debugger.out("Found line: " + line);
                    found = true;
                }
            } else if (i < 100) {
                if (line[2] == ')') {
                    line.erase (0, 4);
                    output << "[" << i << "]" << line << std::endl;
                    debugger.out("Found line: " + line);
                    found = true;
                }
            }
        }

        for (int j = 0; j < 4; j++) {
            getline (input, line);
            if (line[1] == ')') {
                line.erase (0, 3);
                output << "[" << i << "a]" << line << std::endl;
            }
        }

    }
}

I'm also trying to teach myself git at the moment, so I happen to have the project I'm working on hosted on github here. I don't know if the context will make what I'm trying to do make sense, but I'm posting it just in case.

Bonus question: I've been racking my brain, but I haven't come up with a solution to adding the delimiter. Answers seem to be one line long, so I can probably just add the delimiter to the end of any line starting with "A)" etc., but some of the questions are much longer. My thought is to find any occurrence of "A)" and add the delimiter to the end of the line above it, but I can't think of how to do that. Can anyone point me in the right directions for member functions of fstream that might help?

Thanks for reading.

Upvotes: 0

Views: 912

Answers (1)

rici
rici

Reputation: 241911

Streams do not magically read the entire file into memory. If that is what you want to do, you should just do that: my guess is that your file is considerably smaller than your available memory, and it might be easier to perform all the operations in place using standard C++ containers.

Upvotes: 1

Related Questions