Hello everyone.
Generally, the staff has recommended us to use Boost to parse the file, but I've installed it and not succeeded to implement anything with it.
So I have to parse a CSV file line-by-line, where each line is of 2 columns, separated of course by a comma. Each of these two columns is a digit. I have to take the integral value of these two digits and use them to construct my Fractal objects at the end.
The first problem is: a line can start with white-spaces and it's okay, my solution is okay with that, but a line can also end with white-space (that is, after the second digit) - here my parser treats it as if it's an invalid input.
The second problem is: The file can look like for example so:
This format of file is okay. But my solution prints the respective 1,1 fractal 3 times, where a correct solution has to print it only once.Code:1,1 <HERE WE HAVE A NEWLINE> <HERE WE HAVE A NEWLINE>
The third problem is: The file can look like:
Code:1,1 <HERE WE HAVE A NEWLINE> 1,1
This is supposed to be an invalid input but my solution treats it like a correct one - and just skips over the middle NEWLINE.
Maybe you can guide me how to fix these issues, it would really help me as I'm struggling with this exercise for 3 days from morning to evening.
This is my code:
Code:#include <iostream> #include "Fractal.h" #include <fstream> #include <stack> #include <sstream> const char *usgErr = "Usage: FractalDrawer <file path>\n"; const char *invalidErr = "Invalid input\n"; const char *VALIDEXT = "csv"; const char EXTDOT = '.'; const char COMMA = ','; const char MINTYPE = 1; const char MAXTYPE = 3; const int MINDIM = 1; const int MAXDIM = 6; const int NUBEROFARGS = 2; int main(int argc, char *argv[]) { if (argc != NUBEROFARGS) { std::cerr << usgErr; std::exit(EXIT_FAILURE); } std::stack<Fractal *> resToPrint; std::string filepath = argv[1]; // Can be a relative/absolute path if (filepath.substr(filepath.find_last_of(EXTDOT) + 1) != VALIDEXT) { std::cerr << invalidErr; exit(EXIT_FAILURE); } std::stringstream ss; // Treat it as a buffer to parse each line std::string s; // Use it with 'ss' to convert char digit to int std::ifstream myFile; // Declare on a pointer to file myFile.open(filepath); // Open CSV file if (!myFile) // If failed to open the file { std::cerr << invalidErr; exit(EXIT_FAILURE); } int type = 0; int dim = 0; while (myFile.peek() != EOF) { getline(myFile, s, COMMA); // Read to comma - the kind of fractal, store it in s ss << s << WHITESPACE; // Save the number in ss delimited by ' ' to be able to perform the double assignment s.clear(); // We don't want to save this number in s anymore as we won't it to be assigned somewhere else getline(myFile, s, NEWLINE); // Read to NEWLINE - the dim of the fractal ss << s; ss >> type >> dim; // Double assignment s.clear(); // We don't want to save this number in s anymore as we won't it to be assigned somewhere else if (ss.peek() != EOF || type < MINTYPE || type > MAXTYPE || dim < MINDIM || dim > MAXDIM) { std::cerr << invalidErr; std::exit(EXIT_FAILURE); } resToPrint.push(FractalFactory::factoryMethod(type, dim)); ss.clear(); // Clear the buffer to update new values of the next line at the next iteration } while (!resToPrint.empty()) { std::cout << *(resToPrint.top()) << std::endl; resToPrint.pop(); } myFile.close(); return 0; }