-1

I am writing C++ programs and code is organized as below

main.cpp
source/newfile.cpp
header/newfile.h
files/file.txt

main.cpp calls newfile.cpp. From newfile.cpp I want to navigate to files/file.txt and write some content there. My code looked like this..

#include <iostream>
#include <fstream>

using namespace std;

class abc {

    void function () {
         ofstream file ("../files/file.txt");
         file << "I want to write here " << endl;
         file.close ();

    }

}

I don't want to use argv[0] or boost. The reason I want to use relative path is because I am trying to create an application that would be common to most OSes and using relative path can help me skip the problem of determining OS. So can you please let me know how to do this?

JMD
  • 337
  • 4
  • 16

1 Answers1

1

There is generally no anything.cpp in the target environment (unless you put it there explicitly but the fact remains, it's not the source file that's running), all you have is executables.

There are ways to get the path of the executable so, if it's in a bin subdirectory, you can still go relative from that. But that's usually a bad idea in multi-user environments since they usually share the executable in a single location.

That's why Windows worked so hard to give us things like c:\users and UNIX has $HOME (along with the bin/var/etc areas to ease software control).

The code as you have it will work relative to your current directory, which will work well provided it's set correctly. So, if you have:

toplevel
|
+--- bin
|
+--- files

and you're running in bin, you will get the correct file. However, I'd still maintain it's not necessarily such a good idea.

There's plenty of other ways of doing it, such as providing full path on the command line or in an environment variable. But, if you want full automatic directory selection, it'll have to be from information you can get, such as current directory, user's home directory, executable path or so on.


If you can guarantee that the location won't change in the target environment, there are also ways to get the path at source time (during compilation).

The first step to try is using the __FILE__ macro which gives you the presumed source file name. If this contains the path (not mandated), you could use that to work out the directory it's in. You can test if it contains the path with something like:

#include <iostream>
int main (void) {
    std::cout << __FILE__ << '\n';
    return 0;
}

If you don't get the full path using that method, there's nothing stopping you from providing it yourself, such as changing your compilation command to something like:

gcc -DSRCDIR1=\"$(dirname $PWD/qq.c)\" -DSRCDIR2=\"$(dirname qq.c)\" -o qq qq.c

(though qq.c would be something like $< in a makefile rule).

You could then use code such as:

#include <iostream>
int main (void) {
    std::cout << ((SRCDIR2[0] != '/') ? SRCDIR1 : SRCDIR2) << '\n';
    return 0;
}

to select the right directory (absolute or relative-turned-into-absolute).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I agree. At the end its all executables. But my objective is to write content into files.txt present in files directory. And the code snippet that attempts to write into file.txt, I want it to be in newfile.cpp which is in source directory. With this, would you be able to help me write to the path where I want to without using absolute path information. – JMD Mar 10 '15 at 22:34
  • @user1998463: "And the code snippet that attempts to write into file.txt, I want it to be in newfile.cpp which is in source directory". Please make sure to understand it does not matter where the source code is that writes to file.txt. The path to "../files/file.txt" is rooted in the process's current directory (by default, this is where your running application is). So for this to work, you need to put your application into the source/ or header/ folders according to your file tree that you provided, probably not what you want. – David Ching Mar 11 '15 at 00:18
  • Thank you paxdiablo. This helps – JMD Mar 11 '15 at 02:42