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
andreadToken
as separate functions, and - both change the state of the input stream.
#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:
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;
}