0

Disclosure: I am a student right now, so if you see any bad habits in my code, feel free to point them out. I have questions about both the ofstream and ifstream portions of my code.

In the ofstream, the user can create their own shopping list and name it (which will end up being the file name). Once their list is created, the file will save with the data.

Here my question: How do I automatically assign a file type to a file a user named? Here is my current code for it:

void createList(double price[100], double quantity[100], string item[100], double tax, int list_size) {
    ofstream saved_list;
    string listname;
    string fileApplicator = ".txt";

    cout << "What would you like to save this list as?: ";
    getline(cin, listname.append(fileApplicator));
    saved_list.open(listname.c_str());

As for the ofstream part of my code, I want the user to be able to select which file they want read based on the name of the file.

Here's my question: When I run the code, the file fails to open every time. I have a current file saved as safeway.txt but it will not open when I attempt it. Here is the code for it:

void reviewList(void) {
    ifstream saved_list;
    string listname;
    string fileApplicator = ".txt";
    char viewAnother = 'Y';
    do {
        cout << "Which list would like to open: ";
        getline(cin, listname.append(fileApplicator));
        saved_list.open(listname.c_str());
        if (saved_list.is_open()) {

......//other code
            }
            cout << "Would you like to view a different list (Y/N): ";
            cin >> viewAnother;
            viewAnother = toupper(viewAnother);
            if (viewAnother == 'N')
                break;
        }
        else {
            cout << "List not found. Please try again.\n";

        }
    } while (viewAnother == 'Y');
}
  • 3
    Bad habit. Looks like you're `using namespace std;`. This can lead to nigh inscrutable bugs. Use it with caution. Details: [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721) – user4581301 Apr 15 '21 at 19:16
  • 1
    One common reason for files failing to open is misjudging where the [Working Directory](https://en.wikipedia.org/wiki/Working_directory) is – user4581301 Apr 15 '21 at 19:18
  • @user4581301 I appreciate this. Unfortunately my school is having us learn the ```using namespace std;```, which I disagree with, so I am going to have to go out of my way to learn where to apply ```std::``` instead. Not a big deal though, all part of the learning process. – user15639808 Apr 15 '21 at 19:19
  • Unrelated: In modern c++ the many file opening routines all take `std::string` so there is no need for the `.c_str()` in `saved_list.open(listname.c_str());` if your compiler was released in the last 10-or-so years and has support for a modern C++ Language Standard enabled. – user4581301 Apr 15 '21 at 19:20
  • 1
    Strange teaching requirements happen to the best of us. You know it's a problem and you know to avoid it. Most don't so I figured it was worth bringing up. – user4581301 Apr 15 '21 at 19:21
  • What do you mean by *How do I let the user determine the file type of a file they name?* You appear to have hard-coded the extension to txt, is that what you mean by type? – user4581301 Apr 15 '21 at 19:24
  • 3
    I think one of your bugs is here: `getline(cin, listname.append(fileApplicator));`. English version: append the file extension to `listname`, then overwrite the current contents of `listname` with user input. Adding the extension probably needs to be done separately after the file name has been gotten from the user. – user4581301 Apr 15 '21 at 19:30
  • @user4581301 Basically, I wanted to automatically have each file they name be a .txt file. Looking back in retrospect, I should have reworded the question to "How do I automatically assign a file type to the persons named file?" As in, all the user needs to type is the name of the file, not the extension. As you can see, I am trying to ```append``` the extension .txt, but when I attempted running it, it did not save as a .txt. – user15639808 Apr 15 '21 at 19:31
  • 1
    You need to do the append after the getline() not as part of it. However with that said, what if the user typed the extension instead of omitting it? You may want to add logic to append if there is no extension typed by the user. – drescherjm Apr 15 '21 at 19:32
  • 2
    Recommendation: Test the stream state after all IO transactions. It really sucks to think you got data from the stream, behave like you got data from the stream, and watch the program do something utterly stupid because it didn't really get input from the stream. Order of operations should always be 1) read input, 2) test that input was read, 3) use input. Skip a step or do it out of order and sooner or later you'll expose the bug.. – user4581301 Apr 15 '21 at 19:33
  • @drescherjm I just changed my code to this: ``` getline(cin, listname); listname = listname.append(fileApplicator);``` but it still is not automatically saving it as a .txt. – user15639808 Apr 15 '21 at 19:34
  • 2
    `listname.append(fileApplicator);` should be sufficient after `getline(cin, listname);` maybe this is working but your file explorer is hiding the extension from you because `.txt` is a known type – drescherjm Apr 15 '21 at 19:36
  • 1
    Feel free to [edit the question](https://stackoverflow.com/posts/67114753/edit) to make it more readable/understandable. Just be cautious about changing the nature of the question such that existing, correct answers are rendered invalid or redundant. In other words, don't totally change the question or move the goalposts, but do feel free to reword confusing phrasing. – user4581301 Apr 15 '21 at 19:36
  • @drescherjm Just tried that, still didn't work. – user15639808 Apr 15 '21 at 19:39
  • Did it not save a file or appear to not add the extension? – drescherjm Apr 15 '21 at 19:40
  • @drescherjm A "File" saves. As in literally a file with data, but I still have to choose what application I want to open it up with. It's not saving as a text document – user15639808 Apr 15 '21 at 19:41
  • 1
    In that case we need a more-complete code example. That should work, so something else is going wrong. I recommend constructing a [mre] that focusses on the file naming. If making the MRE doesn't end prematurely with you giving your head a shake and solving the problem yourself (the intended outcome of making a MRE), add the MRE to the question. – user4581301 Apr 15 '21 at 19:41
  • 1
    Is this Windows where the file type depends on the extension or Unix-based where the file type depends on the content? –  Apr 15 '21 at 19:42
  • Is the extension still missing? Is this a Windows-based system where Explorer could be hiding the extension from you? – user4581301 Apr 15 '21 at 19:45
  • In that case my guess is `fileApplicator` does not contain ".txt" any more for some unknown reason. – drescherjm Apr 15 '21 at 19:46
  • This is Windows-based. Explorer is showing file extensions on my computer. Just tested the MRE code, named a file "File", and it still only saved as "File", not "File.txt". – user15639808 Apr 15 '21 at 19:50
  • `getline(cin, listname.append(fileApplicator));` still has the extension being added to the string before getting the string from the user. You need `getline(cin, listname);` and then `listname.append(fileApplicator);` A function's arguments are all computed before the function is called (but if you have multiple arguments, [they may not necessarily be computed in the order you expect](https://en.cppreference.com/w/cpp/language/eval_order)). – user4581301 Apr 15 '21 at 19:51
  • @user4581301 and dreschergm, you were both correct. creating the ```listname.append(fileApplicator);``` DOES work in my MRE code, but for some reason didn't in my original code. I will take a look in to that, but at list I know that this way works. Thank you! I will try applying this method to my second question to see if it works the same way. – user15639808 Apr 15 '21 at 19:55
  • @user15639808 the first thing I noticed looking at you code is the opening brace is not on its own line. PERSONALLY I think it makes code harder to read, Also while ('char' == 'Y') is bad news, I suspect the user will start hammering the Y key and asking why its not working, because they don't have caps lock on :) – Code Gorilla Apr 16 '21 at 08:47

1 Answers1

2

Solution to this problem: getline(cin,listname.append(fileApplicator)); is the error. The append needs to be processed AFTER the getline, like this:

getline(cin,listname);
listname.append(fileApplicator);

This will allow the user to not only name a file and have it automatically saved as the programmer's desired file type but will also automatically select the desired file to be read without the user needing to enter the extension (at least on Windows OS's). I.E.: User can enter "Filename" rather than "Filename.txt".

Thank you @user4581301 and @drescherjm for helping to solve this issue!