Home > Back-end >  Remove repeated code in function definition
Remove repeated code in function definition

Time:11-01

this is my first question, so I may miss the "correct structure".

Anyway, I have a header file, with a function. This function (void readFile()) is defined in a cpp file. Within this definition I have code which repeats itself a lot.

If it was in main, I would simply declare a new function, define the repeatable in it, and then call everytime the function. But since it's in a non-main cpp file, I am having issues with this process.

Basically, what my function does, is read through a file char by char, and saves the data to different objects, based on the text.

My code looks like:

source.open("bookings.txt", std::ios::in);
char c;
source.get(c); 
            while (c != '|'){
                CurrentID.push_back(c);
                source.get(c);
            }
object.setID(CurrentID)

This code repeats itself, replacing only the line of "object.setID". I tried declaring function "search(std::ifstream x, char y, std::string z);" with definition

void Search(std::ifstream x, char y, std::string z){
    x.get(y); // next after |
    while (y != '|'){
        z.push_back(y);
        x.get(y);
    }
} 

But if I try to call this function within my "void readFile()" definition, like this:

// First block as a repeatable

source.get(c); 
            while (c != '|'){
                CurrentID.push_back(c);
                source.get(c);
            }
object->setID(CurrentID)
CurrentID.clear();

// second block as a function, with repeatable code commented out

void Search(std::ifstream quelle, char c, std::string &CurrentID);

            /* source.get(c); 
            while (c != '|'){
                CurrentID.push_back(c);
                source.get(c);
            }*/
            object->setPrice(stof (CurrentID));
            CurrentID.clear();

It jumps from "CurrentID.clear()" in first block, directly to "object->setPrice" in second block, ignoring the existence of the void Search function. Any proposition how to make the function work, or maybe other way, to remove repeated code?

CodePudding user response:

I don't know if this will exactly answer your question. If not, please post your entire code, especially the readFile function.

Let's say you want a readFile function to:

  • parse an input stream, and
  • fill the fields ID (string) and price (float) of a list of object structs,
  • the values in the stream being separated by a | character, and,
  • using a second function readToken for the repeated code (i.e., read from the input stream until the separator is found and return a string).

The code below does that. Notice:

  • you define readFile and readToken as separate functions, and
  • both change the state of the input stream.

[Demo]

#include <iostream>
#include <sstream>
#include <string>  // stof
#include <vector>

struct object {
    std::string id;
    float price;
};

std::string readToken(std::istringstream& iss) {
    std::string ret{};
    char c{};
    while (true) {
        iss >> c;
        if (not iss.eof() and c != '|') {
            ret.push_back(c);
        } else {
            return ret;
        }
    }
}

std::vector<object> readFile(std::istringstream& iss) {
    std::vector<object> ret{};
    while (not iss.eof()) {
        auto id = readToken(iss);
        auto price = std::stof(readToken(iss));
        ret.emplace_back(id, price);
    }
    return ret;
}

int main() {
    std::istringstream input{"ID1|25.5|ID2|3.14"};
    auto objects = readFile(input);
    for (const auto& o : objects) {
        std::cout << o.id << ", " << o.price << "\n";
    }
}


// Outputs:
//
//   ID1, 25.5
//   ID2, 3.14

A simpler way to do this would be to have std::getline read tokens:

[Demo]

std::vector<object> readFile(std::istringstream& iss) {
    std::vector<object> ret{};
    while (not iss.eof()) {
        std::string id{};
        std::getline(iss, id, '|');

        std::string price_str{};
        std::getline(iss, price_str, '|');
        auto price = std::stof(price_str);

        ret.emplace_back(id, price);
    }
    return ret;
}
  • Related