Include file read from terminal into function using #include - c++

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.

Related

how to pass on some output from a c++ program to the shell so that it can be used in the shell

Is there any good way i can make some data created by my c++ program available to the shell after exiting the program?
I have a c++ program, inside which i have a string containing a path:
std::string path = "/home/some/path"
I want this path to be available after the c++ program exits main and i am returned to the shell, so that i can use that path (e.g. cd to that path).
I have considered/tried the following approaches:
I tried making an environment variable in c++ program using setenv(). However the environment variable only exists while in the c++ program, and it is apparently not possible to make those changes visible in the shell after exiting the program.
(considered) writing the path to a temporary file, so that a bash script could later access the details of the path from it. However i have read many suggestions to not do that due to security vulnerabilities.
I tried calling the bash script from within the c++ program, using system(). This does not work if i try to cd to that directory (exiting the program will keep me in the same directory as before).
I figure that if i am desperate, i could have my program cout the path, and use the solutions as described here:
$ ./program | tee output.txt
Then the path is stored inside the file. This works technically, but has the undesirable effect of creating a file and printing the path to the screen, and is basically creating a temporary file.
another option to, again, cout in my program, and use command substitution. running in the shell
$ var=$(./program)
storing the path in var. This didnt work because my program does many things including requiring user input before calling
std::cout<< path << std::endl;.
Particularly, i have observed this approach to not display a curses window, which is required for the program.
the only solution that has worked is piping the output to tee.
Environment variables are only an input, they cannot be used to return any information from a program.
You are already using std::cin and std::cout for user input, and std::cerr should be reserved for error messages. However, you can have the shell open more filedescriptors, and have your program write to those. However, doing this with pure C++ is not possible. But if you don't mind using POSIX C functions:
#include <cstdio>
int main() {
FILE *f = fdopen(3, "w");
fprintf(f, "some path\n");
}
And then use it like so:
./program 3> output.txt
This of course creates an undesirable file. I don't think there is any way to store the output from an extra filedescriptor directly to a variable in bash. However, you could create a temporary file inside /dev/shm, so it will never be written to disk, or create a FIFO object and redirect the output from the program to the FIFO, and then read it back. For some examples of how to do this, see this question.
You could write the output that you want the user to see to stderr instead of stdout. Only output what you need your shell script to see to stdout:
#include <iostream>
int main() {
std::clog << "Enter data: "; // clog prints to stderr like cerr
std::string line;
std::getline(std::cin, line);
std::cout << line << '\n';
}
Then this will work:
var=$(./program)

How to pass a value from a C++ executable to a Rails app?

I have a Rails app that runs a C++ executable from the command line. I'm able to print the C++ cout to the command line, but I'd like to assign it back to a variable, output = in a Rails controller.
Is this possible?
Below is a simplified example of my Rails controller action and C++ .cpp to help explain the question.
Rails controller:
def get_variable
system("cd ~/workspace/OutputTest/src && ./output.bin")
end
Note I've already compiled and created a C++ executable file named output.bin.
C++ file:
#include <iostream>
using namespace std;
int main() {
cout << "Hello world!!!";
return 0;
}
I'm familiar with Rails (not necessarily running files from the command line through Rails), but a complete newb to C++.
Any guidance would be very appreciated. If there is another approach I should be taking completely, that would also be very helpful to know.
I would prefer not to do this inline, as I'd like to do a lot more in C++ once I can solve this initial step.
UPDATE
The best solution I've come up with so far is writing a string to a .txt in C++, and then using File.read() in Rails. But it doesn't feel scalable, or give flexibility over data structure.
So I'm still wondering if there is a more straightforward way, like somehow keeping the value in memory for Rails to access it. Not sure though.
Maybe you have already tried this, but there is a backtick operator in ruby, which returns the output of a command as a string.
example:
def system_date
`date`
end
puts system_date #=> "Wed Nov 16 18:59:28 CET 2016"
in your case it would be
def get_variable
`~/workspace/OutputTest/src/output.bin`
end
The best idea I thought of is running the C++ app, piping (|) the input to rails (if that works) and doing $stdin.gets(). I'm not a ruby expert, and I haven't used it much, but I think it should work. Try
./cppapp | rubyapp
on a bash terminal.
You can capture an output of your programm with pipe:
test.cpp:
#include <iostream>
int main() {
std::cout << "Hello world!!!";
return 0;
}
Compile it: $ g++ test.cpp -o hello
test.rb:
var = IO.popen("./hello") do |cmd|
cmd.read
end
puts var
#=> "Hello world!!!"
More information about pipe reading can be found in documentation: IO.popen
You can use the back-tick operator to capture the output of command line executions in ruby.
irb(main):008:0> x = `echo foo`
=> "foo\n"

System() function, and calling internet explorer from it, DevC++

I tried making a program that'd take website info, then feed it to system() to start website. I'm aware that characters like (\, ",') don't get fed to the output directly, so I used escape sequences.
I wrote this program, but the command prompt just refuses to go past C:\ path. But if I copy paste the command displayed by my program, internet explorer gets launched. But the case isn't so for my program. Can anybody tell me where is the error?
Here is my code:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
cout<<"Please enter the website you wish to visit: ";
string website,web;
cin>>web;
web= " " + web;
website = "\"%ProgramFiles%\\Internet Explorer\\iexplore\""+web;
cout<<"\n"<<website<<endl<<endl<<endl;
system(website.c_str());
return 0;
}
You are using an environment variable, %ProgramFiles%, in your system command-line; these are specific to the MS-DOS prompt environment, and generally not available in system implementations.
I suggest replacing that with the full path, such as \"C:\Program Files\Internet Explorer\iexplore\", and see if that works.
If that works, then your implementation doesn't implicitly replace environment variables the way a full Command Prompt does, so you will need to query the environment variable separately and construct the path before you run system. See getenv for one possible way (I'm not sure what mingw32 supports, so you may have other options as well).
If that doesn't remedy the problem, I suggest checking if you can launch something simpler, like notepad.exe, to verify that there is nothing interfering with launching an application in general, such as your environment path or permissions.
Pass it in double double quotes:
website = "\"\"%ProgramFiles%\\Internet Explorer\\iexplore\"\""+web;
The system("something") call actually runs the command interpreter cmd in a way similar (but probably not identical) to cmd /c something. This has implications when there are spaces in the command name, see e.g this. I cannot tell exactly why single double quotes work when there's no environment variable involved, and do not work otherwise, but the fact is, double double quotes do work.
If you want to launch the user's preferred browser, consider calling
system("start http://" + websitename);
instead.
Get that environment variable value first.
#include <iostream>
#include <ShlObj.h>
int main() {
char pathToPf[MAX_PATH];
if (S_OK == SHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, pathToPf))
std::cout << pathToPf << std::endl;
return 0;
}
See SHGetFolderPath documentation...
Note that I was lazy and using the ASCII version of this function. Use it without the A postfix and deal with the conversation ;)

Compile a program with local file embedded as a string variable?

Question should say it all.
Let's say there's a local file "mydefaultvalues.txt", separated from the main project. In the main project I want to have something like this:
char * defaultvalues = " ... "; // here should be the contents of mydefaultvalues.txt
And let the compiler swap " ... " with the actual contents of mydefaultvalues.txt. Can this be done? Is there like a compiler directive or something?
Not exactly, but you could do something like this:
defaults.h:
#define DEFAULT_VALUES "something something something"
code.c:
#include "defaults.h"
char *defaultvalues = DEFAULT_VALUES;
Where defaults.h could be generated, or otherwise created however you were planning to do it. The pre-processor can only do so much. Making your files in a form that it will understand will make things much easier.
The trick I did, on Linux, was to have in the Makefile this line:
defaultvalues.h: defaultvalues.txt
xxd -i defaultvalues.txt > defaultvalues.h
Then you could include:
#include "defaultvalues.h"
There is defined both unsigned char defaultvalues_txt[]; with the contents of the file, and unsigned int defaultvalues_txt_len; with the size of the file.
Note that defaultvalues_txt is not null-terminated, thus, not considered a C string. But since you also have the size, this should not be a problem.
EDIT:
A small variation would allow me to have a null-terminated string:
echo "char defaultvalues[] = { " `xxd -i < defaultvalues.txt` ", 0x00 };" > defaultvalues.h
Obviously will not work very well if the null character is present inside the file defaultvalues.txt, but that won't happen if it is plain text.
One way to achieve compile-time trickery like this is to write a simple script in some interpreted programming language(e.g. Python, Ruby or Perl will do great) which does a simple search and replace. Then just run the script before compiling.
Define your own #pramga XYZ directive which the script looks for and replaces it with the code that declares the variable with file contents in a string.
char * defaultvalues = ...
where ... contains the text string read from the given text file. Be sure to compensate for line length, new lines, string formatting characters and other special characters.
Edit: lvella beat me to it with far superior approach - embrace the tools your environment supplies you. In this case a tool which does string search and replace and feed a file to it.
Late answer I know but I don't think any of the current answers address what the OP is trying to accomplish although zxcdw came really close.
All any 7 year old has to do is load your program into a hex editor and hit CTRL-S. If the text is in your executable code (or vicinity) or application resource they can find it and edit it.
If you want to prevent the general public from changing a resource or static data just encrypt it, stuff it in a resource then decrypt it at runtime. Try DES for something small to start with.

How to run a bash script from C++ program

Bash scripts are very useful and can save a lot of programming time. So how do you start a bash script in a C++ program? Also if you know how to make user become the super-user that would be nice also. Thanks!
Use the system function.
system("myfile.sh"); // myfile.sh should be chmod +x
#include <stdio.h>
#include <stdlib.h>
// ....
system("my_bash_script.sh");
Since this is a pretty old question, and this method hasn't been added (aside from the system() call function) I guess it would be useful to include creating the shell script with the C binary itself. The shell code will be housed inside the file.c source file. Here is an example of code:
#include <stdio.h>
#include <stdlib.h>
#define SHELLSCRIPT "\
#/bin/bash \n\
echo -e \"\" \n\
echo -e \"This is a test shell script inside C code!!\" \n\
read -p \"press <enter> to continue\" \n\
clear\
"
int main() {
system(SHELLSCRIPT);
return 0;
}
Basically, in a nutshell (pun intended), we are defining the script name, fleshing out the script, enclosing them in double quotes (while inserting proper escapes to ignore double quotes in the shell code), and then calling that script's name, which in this example is SHELLSCRIPT using the system() function in main().
The only standard mandated implementation dependent way is to use the system() function from stdlib.h.
Also if you know how to make user become the super-user that would be nice also.
Do you want the script to run as super-user or do you want to elevate the privileges of the C executable? The former can be done with sudo but there are a few things you need to know before you can go off using sudo.
StackOverflow: How to execute a command and get output of command within C++?
StackOverflow: (Using fork,pipe,select): ...nobody does things the hard way any more...
Also if you know how to make user become the super-user that would be nice also. Thanks!
sudo. su. chmod 04500. (setuid() & seteuid(), but they require you to already be root. E..g. chmod'ed 04***.)
Take care. These can open "interesting" security holes...
Depending on what you are doing, you may not need root. (For instance: I'll often chmod/chown /dev devices (serial ports, etc) (under sudo root) so I can use them from my software without being root. On the other hand, that doesn't work so well when loading/unloading kernel modules...)