Variables in quotation marks C++ - c++

Let me begin by saying that I could not find an identical question, but my search keywords were fairly generic, and so if you know of a thread that answers my question, point it out to me and I'll close this thread.
I'm re-writing a bash script of mine in c++ to help me get a firmer grasp on the language. The problem I'm running into is as follows:
string input = "/wam/wxx.cpp";
string output = "/wam/wxx.exe";
system ("/MinGW/bin/g++.exe input -o output");
(This is just a small illustration; in my actual code the variables are user-input)
Obviously I am passing the words 'input' and 'output' to my compiler instead of the variables of those names. I have tried
system ("/MinGW/bin/g++.exe" input "-o" output);
as well as other combinations of quoting/not quoting, none of which work either. The system command wants quotation marks, so is there a way to have my variables properly recognized in those quotes? (Currently I am saving these variables to a text file, then loading them into a bash script that runs the compiler, which defeats the purpose of me writing this in c++ to begin with.)
Thanks in advance!
EDIT: To clarify, I am
using namespace std

Since they are (presumably) std::string, you can just paste them together with +, like this:
std::string cmd = "/MinGW/bin/g++.exe";
std::string fullcmd = cmd + " " + input + " -o " + output;
system(fullcmd.c_str());
You need fullcmd.c_str() since system takes a C style string, not a C++ style string.

This should help:
string input = "/wam/wxx.cpp";
string output = "/wam/wxx.exe";
string command = "/MingW/bin/g++.exe "
command += input;
command += " -o "
command += output;
system(command.c_str());
You need std::string::c_str() to convert strings to char arrays, and you can't add an std::string to a string literal, however, you can add a literal to a std::string, or an std::string to an std::string.

Related

Config File using Environment Variables

I have a .cfg file and I'd like to use an environment variable to configure one of the fields.
directory=${HOME}/folder1/
However, when I parse this config, it's reading ${HOME} as a string, which is obviously not what I want.
I wrote my own parser in C++, in case I need to do something special. Right now it is a very basic read and parse.
void Config_Parser::parse_config_by_delimiter(string config, string delimiter) {
ifstream infile(config);
while (infile >> line) {
key = line.substr(0, line.find(delimiter));
value = line.substr(line.find(delimiter)+1);
if (this->config_settings.find(key) != this->config_settings.end()) {
cout << "Cannot use config... same key is set multiple times" << endl;
}
this->config_settings.insert({key, value});
}
}
The code seems to work fine for all other config settings (anything not using an environment variable), so I don't think its a problem with the code. But, I am a C++ noobie, so it's here anyways.
When I parse and print out the value:
Actual output: ${HOME}/folder1/
Expected/desired output: /home/my_dir/folder1/
Untested
You can use wordexp to do posix shell-like expansion of strings.
The function wordexp() performs a shell-like expansion of the string
s and returns the result in the structure pointed to by p.
You will need to #include <wordexp.h>
You also probably want to specify the flag WRDE_NOCMD to prevent subshell command execution.
http://man7.org/linux/man-pages/man3/wordexp.3.html
Is the following configuration syntax acceptable to you?
directory = getenv("HOME") + "/folder1/";
If so, then a configuration file parser library I wrote called Config4* can do what you want. You can find it on http://www.config4star.org.
I recommend you scroll down the web page to "Download the Manuals" and retrieve Config4* Getting Started Guide and Config4* C++ API Guide. Chapters 2 (overview of syntax) and 3 (overview of API) of the "Getting Started" guide should be more than sufficient to get you up and running.

C++ : Trigger a python script stored on my machine, from inside a C++ script

I would like to trigger a python script from my C++ script. The python script is independent, I do not need to pass it anything from C++, I also do not need anything returned to C++.
I would also like to pause execution of the C++ script until the python script has finished.
I have tried the embedding solutions and the wrapping solutions offered online, but I am looking for something much simpler.
I have attempted the following.
include cstdlib
system("py "C:\path\python_script.py"");
This attempt has problems with the double quotation mark syntax.
I then attempted this to deal with the double quotation mark probem.
include cstdlib
system("py " + char(34) + "C:\path\python_script.py" + char(34));
I then received the error "expression must have integral or unscoped enum type". It seems as though you can't concatenate strings this way in C++?
For my final attempt, I tried to concatenate the string in pieces.
include cstdlib
string path1 = "py ";
string path2 = "C:\path\python_script.py";
string path = python_path1 + char(34) + python_path2 + char(34);
system(path);
I now receive the error "no suitable conversion function from "std::string" to "const char" exists".
Any help would be greatly appreciated.
As other answer tell you add \ to escape the " and also double escape your \ path separator :
system("py \"C:\\path\\python_script.py\"");
You can try system("py \"C:\path\python_script.py\"");.
This way you escape the quotation mark and can write it into a string.
Have a look at this post
Try string stream
#include <sstream>
std::stringstream ss;
ss << "py ";
ss << "\"C:\path\python_script.py\"";
system(ss.str().c_str());

echo (shell) and C language

I have a program written in C language. In this program, I have an integer variable QS. The value of this variable changes during execution of the program
In this program written in C, I want to display this variable QS using the echo command shell
I heard about the system () function of the diaper C gives hand to use the terminal or console
system ("echo $ QS") when I do that, the variable QS is not recognized and it displays nothing.
Do you have any specific answers on how I could do this? and how to recognize the variable in C language?
I know that with a simple printf, I can display this variable, but what I want is to use echo.
Thank you in advance for your answers.
Shell can not access your program variable values. You have to set the value into the environment first. There are different ways to do this. One of them is (works in linux/unix)
int main()
{
char chProgramVar[] = "hello world" ;
setenv("ShellVar", chProgramVar, 1) ;
system("echo $ShellVar") ;
}
As others have said, the shell can't access your program variables. You can use sprintf to insert the value into the command that you will execute using system:
char command[BUFSIZ];
sprintf(command, "echo %d", QS);
system(command);
The shell you're spawning with the system(3) call has no idea about any of the variables in your C program. The easiest way to do what you want is to export your data as an environment variable. Since the environment is inherited by the call to system(3), you can just set the variable with setenv(3). However, you must first format it as a string:
int QS = ...;
char QSStr[32]; // Longest integer string is INT_MIN = -2147483648, assuming
// that sizeof(int) == 4
snprintf(QSStr, sizeof(QSStr), "%d", QS); // Convert to string
setenv("QS", QSStr); // Set the environment variable)
...
system("echo $QS"); // Will print the value of QS
You have to format the number as a character byte. The number "4" has a different integer representation as a printed character.
Use printf to print the number, or sprintf to reformat it as a character into a new buffer. Then you can print the new buffer using system echo (for whatever reason).
char s[16]; // might be too small
sprintf(s, "%d", integer_var);
// s is the string

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.

C++ system() not working when there are spaces in two different parameters

I'm trying to run a .exe that requires some parameters by using system().
If there's a space in the .exe's path AND in the path of a file passed in parameters, I get the following error:
The filename, directory name, or volume label syntax is incorrect.
Here is the code that generates that error:
#include <stdlib.h>
#include <conio.h>
int main (){
system("\"C:\\Users\\Adam\\Desktop\\pdftotext\" -layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\"");
_getch();
}
If the "pdftotext"'s path doesn't use quotation marks (I need them because sometimes the directory will have spaces), everything works fine. Also, if I put what's in "system()" in a string and output it and I copy it in an actual command window, it works.
I thought that maybe I could chain some commands using something like this:
cd C:\Users\Adam\Desktop;
pdftotext -layout "week 4.pdf"
So I would already be in the correct directory, but I don't know how to use multiple commands in the same system() function.
Can anyone tell me why my command doesn't work or if the second way I thought about would work?
Edit: Looks like I needed an extra set of quotation marks because system() passes its arguments to cmd /k, so it needs to be in quotations. I found it here:
C++: How to make a my program open a .exe with optional args
so I'll vote to close as duplicate since the questions are pretty close even though we weren't getting the same error message, thanks!
system() runs command as cmd /C command. And here's citation from cmd doc:
If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:
1. If all of the following conditions are met, then quote characters
on the command line are preserved:
- no /S switch
- exactly two quote characters
- no special characters between the two quote characters,
where special is one of: &<>()#^|
- there are one or more whitespace characters between the
two quote characters
- the string between the two quote characters is the name
of an executable file.
2. Otherwise, old behavior is to see if the first character is
a quote character and if so, strip the leading character and
remove the last quote character on the command line, preserving
any text after the last quote character.
It seems that you are hitting case 2, and cmd thinks that the whole string C:\Users\Adam\Desktop\pdftotext" -layout "C:\Users\Adam\Desktop\week 4.pdf (i.e. without the first and the last quote) is the name of executable.
So the solution would be to wrap the whole command in extra quotes:
//system("\"D:\\test\" nospaces \"text with spaces\"");//gives same error as you're getting
system("\"\"D:\\test\" nospaces \"text with spaces\"\""); //ok, works
And this is very weird. I think it's also a good idea to add /S just to make sure it will always parse the string by the case 2:
system("cmd /S /C \"\"D:\\test\" nospaces \"text with spaces\"\""); //also works
I got here looking for an answer, and this is the code that I came up with (and I was this explicit for the benefit of next person maintaining my code):
std::stringstream ss;
std::string pathOfCommand;
std::string pathOfInputFile;
// some code to set values for paths
ss << "\""; // command opening quote
ss << "\"" << pathOfCommand << "\" "; // Quoted binary (could have spaces)
ss << "\"" << pathOfInputFile << "\""; // Quoted input (could have spaces)
ss << "\""; // command closing quote
system( ss.str().c_str() ); // Execute the command
and it solved all of my problems.
Good learning from here on the internals of System call.Same issue reproducible(of course) with C++ string, TCHARs etc.
One approach that always helped me is SetCurrentDirectory() call. I first set current path and then execute. This has worked for me so far. Any comments welcome.
-Sreejith. D. Menon