finding out the path to a file at runtime - c++

In a program I open a file say file.dat at runtime. The problem is when i run the executable it expects the file to be in the directory from where it is executed. I want the program to look into the same directory where the executable is present. What modifications should I make in my program (or in the build system).
For example consider this program:
int main()
{
std::ifstream ip("file.dat");
// do something.
return 0;
}
I am working on Ubuntu with g++-4.6 compiler and CMake build system. Since the project supports out-of-source build that means the program executable can be anywhere depending upon the directory where the cmake was invoked from.
Thanks for the help...

On many systems, the argv[0] parameter will have the path used to execute the program. Whether or not this is the full path of the program depends on how it was invoked.
int main (int argc, char *argv[]) {
std::string progname(argv[0]);
std::string datafile;
if (progname.find_last_of('/') != std::string::npos)
datafile = progname.substr(0, progname.find_last_of('/')+1);
datafile += "file.dat";
std::ifstream ip(datafile.c_str());
//...
}

On Linux reading /proc/self/exe is the best way to go.
char app_path[1024];
ssize_t len = ::readlink("/proc/self/exe", app_path, sizeof(app_path)-1);
if (len != -1) {
app_path[len] = '\0';
} else {
// handle error
}
For other OS, see: https://stackoverflow.com/a/1024937/105015

Related

How to insert parameters to command prompt when starting a program in c++?

I have no idea how to work with command prompt. I don't even know which parameters I should write. Here's the code we were given:
//random example function
void KMP(const string& text, const string& sample) {
ofstream file("iz.txt");
file<<"Test: "<<sample;
file.close();
}
int main(int argc, const char *const argv[]) {
if (argc != 3) {
return -1;
}
string text = inputText(argv[2]);
string sample = argv[1];
out.open("out.txt");
if (!out) {
return -2;
}
KMP(text, sample); //KMP algorithm function that I finished coding in my program (it would be too long to copy-paste all here), but I don't know how to call it in command prompt.
return 0;
}
How can I start the program with command prompt
The passing of command line arguments is not specified by the C++ language. It is specified by the shell of the operating system that you are using. Quite commonly, program's execution follows this pattern:
./path/to/executable argument1 argument2
First, you need to compile the program.
In command prompt-
Go to the respective path. Now,
g++ /yourfilename.cpp/ -o main
Now to run the file,
./main parameter1 parameter2

Is there are a way to find out whether the input is streaming into the program from a file or not?

In Windows, there exists a console trick
someprogram.exe < input.txt
which makes the program to get the input from input.txt whenever there is a input request.
I want my program to behave differently when the input is read from another file. Is there are a way to do that? How?
I don't think so(not sure though), but here is an alternative (error checking omitted):
int main(int argc, char **argv)
{
std::istream * pstream = &std::cin;
std::ifstream fin;
if (argc > 1)
{
fin.open(argv[1]);
pstream = &fin;
}
// use pstream instead of cin
}
Then you pass the name of the file as a command line argument.
Yes, use the function isatty available on most platforms. Looks like it is now called _isatty in windows (not sure why).

Problems using .open with ifsteam objects

The best way to explain my problem is probably just to show you my code, because it's as simple as it gets.
#include <iostream>
#include <fstream>
int main (int argc, const char * argv[])
{
std::ifstream in;
std::string line;
in.open("test.txt");
if (in.fail()) std::cout << "failed. \n";
getline(in, line);
std::cout << line;
return 0;
}
So when I run this, console is returning "failed." instead of opening up the file called test.txt — which is in the same folder as my .xcodeproj file and is also displayed in my Xcode navigator.
I'm not sure what I'm misunderstanding about this process, but I suspect it will be something simple.
Thanks! :)
The file is in the same directory as your .xcodeproj file? Well, there's your problem right here.
By default, the working directory of a process launched from Xcode will be the output directory (that is, the directory where the program is). Depending on your Xcode version, it's probably going to be in <Project Directory>/build/Debug.
Try moving the file there.

How do I run my code from the command line?

i have following code
#include <iostream>
using namespace std;
int main(int argc,char arg[]){
int a=arg[1];
int b=arg[2];
int c=a+b;
cout<<c<<endl;
return 0;
}
i am using windows 7 microsoft visual c++ 2010
how run it from command line?
Open a command prompt from the Start Menu. Use the CD command to change directories to where your exe is. type the name of your exe followed by the arguments.
foo.exe 1 2
or just
foo 1 2
Expect the output (once you've fixed your numerous code errors):
3
Once you compile this you get an executable. Navigate to the directory containing the executable and run it.
Go to google and look for a windows console tutorial. You need to start it from the console. Alternatively you can assign command line in the project properties. I'd recommend learning to do both.
BTW, this code almost certainly does not do what you think it does.
The compiled output of your program will be in the Debug or Release folder inside the solution folder (at least with default project settings). Just change to that directory and run the .exe file.
Open the Visual Studio Command Prompt (you can find it in the Start Menu)
cd to your source file directory
type:
cl.exe <your file name>.cpp
It will create a file .exe
Once your code is setup properly it would be something like this.
MyApp 2 3
Or similar
Navigate to the directory where the executable (.exe) is located. Then type the executable's name followed by two integer parameters.
C:\TestProg\> TestProg 5 6
The problems in your original example are corrected here:
#include <iostream>
#include <sstream>
int main(int argc, char *arg[])
{
std::stringstream sa;
std::stringstream sb;
int a;
int b;
int c;
if (argc >= 3)
{
// Convert string parameter into an integer.
sa.str(arg[1]);
sa >> a;
if (!sa)
{
return 1; // error
}
// Convert string parameter into an integer.
sb.str(arg[2]);
sb >> b;
if (!sb)
{
return 1; // error
}
}
else
{
return 1; // error
}
c = a + b;
std::cout << c << std::endl;
return 0;
}

Get full path of executable of running process on HPUX

I want to get the full path of the running process (executable) without having root permission using C++ code. Can someone suggest a way to achieve this.
on Linux platforms i can do it by using following way.
char exepath[1024] = {0};
char procid[1024] = {0};
char exelink[1024] = {0};
sprintf(procid, "%u", getpid());
strcpy(exelink, "/proc/");
strcat(exelink, procid);
strcat(exelink, "/exe");
readlink(exelink, exepath, sizeof(exepath));
Here exepath gives us the full path of the executable.
Similarly for windows we do it using
GetModuleFileName(NULL, exepath, sizeof(exepath)); /* get fullpath of the service */
Please help me how to do it on HP-UX since there is no /proc directory in HP-UX.
First, I'd like to comment on your Linux solution: it is about 5 times as long as it needs to be, and performs a lot of completely unnecessary operations, as well as using 1024 magic number which is just plain wrong:
$ grep PATH_MAX /usr/include/linux/limits.h
#define PATH_MAX 4096 /* # chars in a path name */
Here is a correct minimal replacement:
#include <limits.h>
...
char exepath[PATH_MAX] = {0};
readlink("/proc/self/exe", exepath, sizeof(exepath));
Second, on HP-UX you can use shl_get_r() to obtain information about all loaded modules. At index 0, you will find information about the main executable. The desc.filename will point to the name of the executable at execve(2) time.
Unfortunately, that name is relative, so you may have to search $PATH, and may fail if the application did putenv("PATH=some:new:path") or if the original exename was e.g. ./a.out and the application has performed chdir(2) since.
On HP-UX, use pstat:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#define _PSTAT64
#include <sys/pstat.h>
int main(int argc, char *argv[])
{
char filename[PATH_MAX];
struct pst_status s;
if (pstat_getproc(&s,sizeof(s),0,getpid()) == -1) {
perror("pstat_getproc");
return EXIT_FAILURE;
}
if (pstat_getpathname(filename,sizeof(filename),&s.pst_fid_text) == -1) {
perror("pstat_getpathname");
return EXIT_FAILURE;
}
printf("filename: %s\n",filename);
return EXIT_SUCCESS;
}
The earlier answer referring to the Unix Programming FAQ was right. The problem, even with the Linux /proc answer, is that the path to the executable may have changed since the exec(). In fact, the executable may have been deleted. Further complications arise from considering links (both symbolic and hard) -- there may be multiple paths to the same executable. There is no general answer that covers all cases, since there may not be a path remaining, and if there is one it may not be unique.
That said, using argv[0] with some logic, as advocated by cjhuitt earlier, will probably do what you want 99.9% of the time. I'd add a check for a path containing "/" before doing the relative path check (and note, you must do that before any cwd() calls). Note that if your calling program is feeling mischievous, there's a host of things that can be done between fork() and exec() to mess this up. Don't rely on this for anything that could affect application security (like location of configuration files).
For what purpose do you need the executable path? Bear in mind, as I put in my earlier post, that there is no guarantee that a path to the executable will exist, or that it will be unique.
I have done this before in a general case. The general idea is to grab argv[0], and do some processing on it:
int main( int argc, char** argv )
{
string full_prog_path = argv[0];
if ( full_prog_path[0] == "/" )
{ // It was specified absolutely; no processing necessary.
}
else
{
string check_cwd = getcwd();
check_cwd += argv[0];
if ( FileExists( check_cwd ) )
{ // It was specified relatively.
full_prog_path = check_cwd;
}
else
{ // Check through the path to find it
string path = getenv( "PATH" );
list<string> paths = path.split( ":" );
foreach( test_path, paths )
{
if ( FileExists( test_path + argv[0] ) )
{ // We found the first path entry with the program
full_prog_path = test_path + argv[0];
break;
}
}
}
}
cout << "Program path: " << full_prog_path << endl;
return 0;
}
Obviously, this has some assumptions that might break at some point, but it should work for most cases.