0

I am trying to build a small CLI software that requests data from the NASA API APOD.

Everything works fine until I want to open the external text file that I wrote into with the default textedit (I am on a Mac) on the computer.

Here is the code for the function that handles that part:

void SaveJSONIntoTextFile(std::string &date, std::string &content) {
    std::string nameOfFile;
    if (date.empty()) {
        nameOfFile = "apod" + currentDate();
    } else {
        nameOfFile = "apod" + date;
    }

    std::ofstream file_out;
    file_out.open(nameOfFile + ".txt", std::ios::out);
    file_out << content;
    file_out.close();
}

I've read the C++ docs and multiple forums. The problem is that I do not want to open the file just to write in it, I want to be able to open the file with the default textedit.

For example, when the user types in a terminal: ./apod --date 2023-05-16, I want my code to do the request, received the JSON from the API, write the JSON into a text file with the given name (all the previous points work just fine), and then open the text file with textedit or any other app that displays a text file.

When I try a simple:

std::cout << file_out << std::endl;

It doesn't work either, because as I saw in my class, I think it's a problem of operator overloading, which I do not understand at all :/

I've also tried the answers from this post: How to open a text file

Greg Dag
  • 3
  • 4
  • Can you clarify what exactly you're trying to achieve in the end here? I see that your _current_ question is 'how to open the file with a text editor', which can be done (exact method is OS specific though) but the obvious question would be 'why do you need to do that from C++ instead of just opening the file in your text editor'? – Cubic May 16 '23 at 13:50
  • Good question :) no idea, is an exercise that I've been given. I am a first year CS student so I try to code as much as I can to understand and to get better at programming so I take every small project I can. It should be possible to open it with the code right? I know how to double click on a file but that's not fun :p So my end result would be that a text reader open itself to read the text file with the JSON in it. – Greg Dag May 16 '23 at 13:55
  • 1
    This doesn't address the question, but get in the habit of initializing objects with meaningful values rather than default-initializing them and immediately overwriting the default values. In this case that means changing `std::ofstream file_out; file_out.open(nameOfFile + ".txt", std::ios::out);` to `std::ofstream file_out(nameOfFile + ".txt");` (I also removed the redundant `std::ios::out`). Also, you don't need to call `file_out.close();`. The destructor will do that. – Pete Becker May 16 '23 at 13:56
  • 1
    Also, don't get in the habit of using `std::endl`; almost always you don't need the extra stuff that it does. `'\n'` ends a line. – Pete Becker May 16 '23 at 13:58
  • Thanks for the hint Pete Becker. I know that I have a lot of bad habits for the moment. – Greg Dag May 16 '23 at 13:59
  • Opening the file written in a different program is a problem entirely unrelated to reading/writing the text file and has nothing to do with operator overloading. Also this kind of functionality is OS dependent, so MacOS should imho be mentioned more prominently... – fabian May 16 '23 at 14:07
  • Hi @PeteBecker ! I was looking over the internet about your comment on the '\n' instead of 'std::endl' and I do not find any reason why. Could you please explain or give me a link to a ressource that give details on that? Thanks – Greg Dag May 24 '23 at 08:56
  • @GregDag — [`std::endl`](https://en.cppreference.com/w/cpp/io/manip/endl). – Pete Becker May 24 '23 at 18:14
  • @PeteBecker Thank you. So if I understand well, it is just a matter of optimization and performances? So if I write a little program I do not care at all but it is a good habit to get? Excuse my simple questions, I am still learning and C++ is hard to understand sometime. – Greg Dag May 26 '23 at 07:48
  • @GregDag — that’s pretty much it, although I’d remove the word “just”. Don’t do things that aren’t needed. Code with lots of little time wasters will be slow, and when you decide that it’s too slow you’re faced with the difficult task of finding all those time wasters and changing them. Profiling often won’t identify little things like that, and you end up having to review all the code in your application to find the weak spots. – Pete Becker May 26 '23 at 17:46
  • @GregDag — here’s another way to think about it. If you weren’t allowed to use `std::endl` what would you do? Would you write `std::cout << “Hello, world!\n”; std::cout.flush(); std::cout << “Hello, world!\n”; std::cout.flush();`? If so, what’s the reason for the calls to `flush()`? – Pete Becker May 26 '23 at 18:29
  • @PeteBecker — Ok ok I see why this is a good habit. Thanks a lot for the advice! – Greg Dag May 28 '23 at 07:45

1 Answers1

0

On Mac, you can open a file with whatever "default" way to handle the file type is set up with using the open program, so in a terminal it'd be just open example.txt.

From C++ you can invoke open via std::system from <cstdlib>.

So for example,

#include <cstdlib>

int main()
{
  std::system("open /tmp/test.txt");
}

will open the /tmp/test.txt file in your system editor (on macOS, on other operating systems you may need something other than open like xdg-open). std::system here executes a string in an operating-system specific way (most of the time, including in macOS, it'll just start a shell and execute the string in there). I'll leave it up to you to adjust this for your example.

Cubic
  • 14,902
  • 5
  • 47
  • 92
  • Thanks a lot, it worked perfectly ! So know I just have to figure out how I can pass the name of the file dynamically and not a `const char *` as `std::system` wants. – Greg Dag May 16 '23 at 14:07
  • @GregDag the `const char*` can be dynamic. You already have a `std::string` in your example, that has a `.c_str()` method. – Cubic May 16 '23 at 14:08
  • You are the best man !! Thank you very much, everything work now :) I've learned a lot. Best – Greg Dag May 16 '23 at 14:14