Okay, for a homework assignment my professor wants us to write a program in C++ that converts from miles to km. I did all that, the program runs. However, he has this special way of calling the program:
The program's usage options are based
on the NAME of the BINARY FILE. If
the program name is 'km2miles', the
program interprets the command line
argument as a kilometer value to
convert to miles. If the name is
'miles2km', then it interprets as
miles being converted to km. Since the
first command line argument, argv[0]
is always the program's name, you can
use its value to decide which function
to call.
I only have 3 files in this project (he tells us to ONLY have these 3):
convert.cpp
distance.cpp
distance.h
Distance .h and .cpp have the different functions to convert Mi to Km and Vice Versa, the convert.cpp has the main function. However, the only way I know how to call this program (after compiling it) is to say:
./convert 10
Where 10 is the number to convert. He says it should be called like this:
$ km2miles 100
and
$ miles2km 60
I have no idea how to get the program to act differently by having a different name... especially when that name doesn't even run the program! Help would be appreciated.
You can:
specify a name when you build it, and build it twice
on Windows: copy convert miles2kms; copy convert kms2miles
on UNIX/Linux: cp convert miles2kms; cp convert kms2miles
on UNIX/Linx (better): make a link or symbolic link: ln -s convert miles2kms; ln -s convert kms2miles.
Inside your program, you should be doing something like:
#include <string>
#include <iostream>
int main(int argc, const char* argv[])
{
std::string program_name = argv[0];
if (argc != 2) {
std::cerr << "usage: " << program_name << " <value>\n";
return 0;
}
if (/* TODO: what would go here? */)
...
else
...
}
The instructions already tell you how:
Since the first command line argument, argv[0] is always the program's name, you can use its value to decide which function to call.
especially when that name doesn't even run the program!
If you're using gcc, by default it generates a binary named a.out, but you can rename it to be whatever you want. (Or you can specify the name of the output file via the -o command-line option.)
Well, he gave you one clue with the argv[0] thing.
Did you perhaps discuss symbolic links at some point in your class?
Difficult for me to give more hints without actually giving away the answer.
If you don't want to recompile the same code into 2 different executable files then you may need to use a symbolic link:
http://en.wikipedia.org/wiki/Symbolic_link
Related
I have written a code which reads in mathematical functions from a text file which are in a C++ compatible format and applies mathematical operations to them. This is a brief summary of the code. I am aware that #include is a preprocessor directive so once the contents of the file have been read in it compiles the code via a bash script each time.
double myfunc(long double x){
return
#include "/.../filename"
}
int main{
"Maths stuff happens here"
}
This works as intended, but I want to be able to speed the process up and read the filename from the terminal rather than entering it into the script each time. To do this I tried using the following:
int g_argc;
char **g_argv;
void process_command_()
{
filename=argv[1]
}
double myfunc(long double x){
return
#include filename
}
int main{
"Maths stuff happens here"
}
It was somewhat of a stretch to think this would work, but I am unsure of how to read the filename from the terminal into my function as though I had typed it in myself due to the function being outside of int main(). I have looked around StackExchange and have found similar problems but none of the solutions has worked for my case.
Any help is greatly appreciated.
Edit for clarity This code is a numerical integration code which takes a very large integrand as input from a text file and the integration is done using the CUBA library. I moved the process from Maple into C++ to get a speed and accuracy increase. The script works wonderfully and can replicate known values ~ 400 times faster than what Maple/Mathematica can do.
Perhaps the easiest way for you would be this.
double myfunc(long double x){
return
#include MY_FILENAME
}
Then when you the compiler in process_command(), pass it an additional argument:
"-DMY_FILENAME=/path/to/your/file"
This is a string you need to build out of argv[1] or whatever stores your filename.
If you invoke a bash script that invokes the compiler, you need to pass your filename as an argument to the script, and arrange for the script to pass it along with -DMY_FILENAME= to the compiler itself.
WhiZTiM's comment/link made me realise this is a really silly question, so apologies for wasting your time. What I want can be done in the bash script. I just define a placeholder in the main.cpp
double myfunc(long double x){
return
#include <filename>
}
Next I put together a simple bash script to copy the main.cpp run file to the directory where the input .txt file is and using sed's find and replace command it switches the filename in main.cpp for the actual file which is taken from the terminal:
input_file=( "$PWD/${#}" )
cp ${HOME}/.../main.cpp $PWD
sed -i "s|filename|${input_file}|g" main.cpp
And then compile and run commands at the end of the script.
Thank you for all your help with this question. I can't believe I didn't see the solution was so simple.
I am trying to get the current running file name in C++. I wrote a simple code that uses both argv[0] and boost current_path() method. The file is compiled into executable file mainWindow.
#include "boost/filesystem.hpp"
int main(int argc, char* argv[])
{
boost::filesystem::path full_path( boost::filesystem::current_path() );
std::cout << full_path.string() << "\n";
std::cout << argv[0] << "\n\n";
return 0;
}
Interestingly the output of each method is different.
argv[0] output is:
../VENTOS/src/loggingWindow/mainWindow
current_path() output is:
/home/mani/Desktop/VENTOS_Redpine
I am not running my program (mainWindow) directly from the terminal. Another application is calling my program and I guess that's why the output is different. Am I right on this?
My second question is: Without using the argv[0] option and relying only on the boost filesystem methods, how can I get the same result as argv[0]?
argv[0] only contains the command used to execute the the program. This may contain the path. It may contain a relative path. It may contain no path at all. It might not even contain the executable name thanks to symlinks etc.... It might even be empty if the hosting system chooses to provide nothing. It can't be trusted, so you don't want to use this as a basis for evaluating other methods.
boost::filesystem::current_path fails you because it only returns the current working directory. This may or may not be the location of the executable because it depends on the directory from which the program was run and whether or not the working directory has been changed by the program. To be honest I'm not sure if there is a sure-fire way to get the process name and path from Boost. There wasn't a few years ago, but time has a way of marching on, you know?
There are a slew of questions covering how to get the executable and path (Finding current executable's path without /proc/self/exe looks promising but is stale. That time marching thing again.) but all are platform-specific you may have to do some ifdef or linker wizardry to make this work.
lets say we have a cal.exe file (a simple addition calculator programmed programmed in c++).
lets say that the console output screen first displays enter the first number: and waits for the user to input an integer value. I am willing to create a c++ program that would "pass on" the required value to the running process (cal.exe) as an input (playing the role of a user). I would also like to have the output from the cal.exe file to be displayed and interpreted by my program.
I havent got the slightest idea how to proceed with this. Is there any open source library that would help me accomplish this? If there is, could you name a few?
I have just learned object oriented programming in c++ last year in my school and I am not used to these kind of stuff in programming; so please excuse me if this question is silly.
update:
lets consider 2 processes a.exe and b.exe running. could you tell me a possible way to program b.exe which provides a integer input to a.exe (a console process) as if it was from the user?
You can do this by accepting command line arguments.something like this
int main ( int argc, char *argv[] )
{
enter code here
return 0;
}
Where,
First argument to main function (argc) refers to the number of arguments being passed to the program at run-time.
Second (char *argv[] )refers to a string containing the arguments that are passed (char * is treated as String also ).
Argument names may vary as per the user specifications.
For details Refer:
http://www.cplusplus.com/articles/DEN36Up4/
And for nesting of programs you can use system("name of child program goes here") Function under stdlib.h.
For details Refer:
http://www.cplusplus.com/reference/cstdlib/system/
I have a C++ program that accepts three inputs: an integer for width, an integer for height, and a filename. Right now, I compile, and run the program like this (assuming I named it prog):
>prog
// hit enter
>128 128 output.ppm
This results in a successful output, but the program description says the proper command-line syntax is:
>prog w h filename
That's all it says. Does this imply that my program should be able to start on the same line? Perhaps it implicitly means you hit enter after typing the program name, but if not, is there a way to actually do this?
Your program needs to parse command line parameters. Looking at the specification, the expected workflow is
>prog 128 128 output.ppm
//hit enter after the parameters
Look here to learn more.
You're approaching the problem incorrectly. You are taking your input via std::cin after your program has been started. Your program specification states that the input should be given as part of the command. Consider a command like ls -l - the -l is part of the command and is passed to the program to parse and act upon.
You need to allow a command like prog 128 128 output.ppm to be run, so the user would type that and then press enter to run the program. How do you get access to the command line arguments within your C++ program? Well, that's what the argc and argv parameters of the main function are for. Your main function should look like this:
int main(int argc, char* argv[]) { ... }
The argc argument gives you the number of arguments passed in the command line (it will be 4, in the example given) which is also the size of the argv array. Each element is an argument from the command. For example, argv[0] will be "prog", argv[1] will be "128", and so on. You need to parse these values and, depending on their values, change the functionality of your program.
You can pass command via the argument in the main function:
int main(int argc, char *argv[]) {
}
argc is the number of arguments and argv is an array of arguments.
I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!