2

I want to read and write csv files using C++.
The constraint is that I have to write the path in the console.
For example, if I want to read a file, I have to write in the console : Read "filePath"
And if I want to write a file : Write "filePath" "delimiter"
I have made functions that work, but without indicating the path in the console.

Here is my main function :

int main()
{
    SudokuGrid sudokuGrid;
    bool done = false;
    string command;
    while (!done) {
        cout << "Enter a command :" << endl;
        cin >> command;
        if (command == "Read") {
            sudokuGrid.readGridFromCSVFile("Sudoku.csv");
            cout << endl << "Grid read with success !" << endl << endl;
        }
        else if (command == "Write") {
            sudokuGrid.writeCSVFileFromGrid("Sudoku3.csv", *";");
            cout << endl << "The file has been created !" << endl << endl;
        }
        else if (command == "Display") {
            cout << "Here is the grid !" << endl << endl;
            sudokuGrid.printGrid();
        }
        else if (command == "Exit") {
            done = true;
        }
        else if (command == "Help") {
            cout << "TODO" << endl;
        }
        else {
            cout << "Incorrect Command" << endl << endl;
        }
    }
    return 0;

It works but my problem is that I write the file path directly in the main function, but I want to be able to write it in the console.

I have tried :

cin >> command >> csvFilePath;
if (command == "Read") {
    sudokuGrid.readGridFromCSVFile(csvFilePath);
    cout << endl << "Grid read with success !" << endl << endl;
    sudokuGrid.printGrid();
}

It works but only with two inputs (the command "Read" and the file path) but I also want to be able to do it with one input (Display) or three inputs (Write, file path and delimiter)

  • 1
    Hi ! As SO is not a code provider service but a Q&A plateform about specific problems, you should add what you have tried and done to attempt to solve your problem. Also try to add a [minimal, reproductible example](https://stackoverflow.com/help/minimal-reproducible-example). If you have any doubt on how to improve your question, you may also check [how to ask](https://stackoverflow.com/help/how-to-ask). – DrosvarG Oct 01 '19 at 08:25
  • In your case, if you already made functions that work, providing them and explaining why you don't manage to call them using console may lead to more and faster useful answers – DrosvarG Oct 01 '19 at 08:28
  • Congrats, you now have a fully answerable and complete question. +1 – DrosvarG Oct 01 '19 at 09:26

1 Answers1

1

You could use std::getline() (doc) instead of std::cin + operator>>.

This way you will be able to get the whole entered command in a string, no matter how many arguments you give. Then you can split your string and store each argument in a std::vector<std::string>.

SudokuGrid sudokuGrid;
bool done = false;
std::string command;
while (!done) {
    cout << "Enter a command :" << endl;     
    std::getline(std::cin, command); // Get the whole command, with arguments

    // Spliting string using Vincenzo Pii answer in given link
    size_t pos = 0;
    std::vector<std::string> arguments;
    while ((pos = command.find(" ")) != std::string::npos) { // this loop destroy command and split it into arguments
        arguments.push_back(command.substr(0, pos)); 
        command.erase(0, pos + 1); // 1 is the size of the delimiter entered in find
    }
    arguments.push_back(command);

Your command would then be the first string of your vector, allowing you to keep your if-else conditions and deal with arguments in them.
For exemple for "Read" condition, you will now have :

if (arguments.at(0) == "Read") {
    sudokuGrid.readGridFromCSVFile(arguments.at(1));
    cout << endl << "Grid read with success !" << endl << endl;
}
DrosvarG
  • 473
  • 2
  • 13
  • By the way, as I used getline, make sure you don't use `std::cin` or else make sure you deal with [this issue](https://stackoverflow.com/questions/33316564/mixing-cin-and-getline-input-issues) – DrosvarG Oct 01 '19 at 09:28
  • Thank you for your answer. But it raises an exception std::out_of_range on the line : if (arguments.at(0) == "Read") – CongelateurSama Oct 01 '19 at 09:56
  • @CongelateurSama What was the input ? – DrosvarG Oct 01 '19 at 10:03
  • Read C:\\Users\\Hugo\\Desktop\\Sudoku.csv or Read "C:\\Users\\Hugo\\Desktop\\Sudoku.csv" – CongelateurSama Oct 01 '19 at 10:05
  • @CongelateurSama Strange I don't manage to reproduce, make sure that `arguments` is in the right scope. Your if-else conditions still have to be in the `while(!done)` loop. Maybe try to use a debugger to check if `command` and `arguments` are correctly set. Also keep in mind that I kept `std`s because I didn't use namespace. If you do used `namespace std`, you may need to remove them – DrosvarG Oct 01 '19 at 11:16
  • @CongelateurSama Which C++ standard do you use ? (C++11?14?17?) I think that operator `==` doesn't exist for `std::string`s until C++17. You should have a go with `arguments.at(0).compare("Read") == 0` instead – DrosvarG Oct 01 '19 at 11:23
  • I use the latest C++ standard (C++17). I tried ```arguments.at(0).compare("Read") == 0``` and I got the same exception. – CongelateurSama Oct 01 '19 at 11:46
  • Erf, once again I don't manage to reproduce, try to control `command` and `arguments` values with a debugger. Probably unrelated with the exception but you may need to add `push_back(command);` after the while loop to get the last argument too, see edit – DrosvarG Oct 01 '19 at 12:21
  • It finally worked with the addition of ```push_back(command);``` Thank you so much ! – CongelateurSama Oct 01 '19 at 12:49
  • No problem, this is the purpose of SO ! Keep in mind that you can (and should) accept an answer that worked for you, letting everyone know that this answer is a workaround for your problem, which help for referencing and may help fellow users who have similar problem – DrosvarG Oct 01 '19 at 12:58
  • Thank you for your advices about SO too ! – CongelateurSama Oct 01 '19 at 13:13