passing input value from bash script to a c++ executable - c++

I have a c++ code which requires an input value. I would like to have a bash script to run my c++ executable file automatically. My bash script is below:
#!/bin/bash
g++ freshness.cpp -g -o prob
for((i=0;i<30;i++))
{
./prob<$2 ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
}
./cal result.txt
rm result.txt
My main.cpp is below:
int main(int argc,char*argv[])
{
map<int, struct Router> nodes;
cout<<"creating routers..."<<endl;
Create_router(argv[1],nodes);
cout<<"creating topology..."<<endl;
LoadRouting(argv[2],nodes);
cout<<"simulating..."<<endl;
Simulate(argv[3],nodes);
return 0;
}
There is a cin in Create_router(argv[1],nodes), like cin>>r_size;
Many thanks in advance.

./prob < $2
means to redirect the input of the program to a file whose name is in the $2 variable.
If $2 is the actual input data, not a filename, then you should use a here-string:
./prob <<< "$2" ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
or a here-doc:
./prob <EOF ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
$2
EOF
or pipe the input to the program:
printf "%s\n" "$2" | ./prob ../../data/new_r.txt ../../data/new_p.txt ../../data /t_$1.txt >> result.txt
The here-string method is the simplest, but it's a bash extension. The other methods are portable to all POSIX shells.

Related

Reading input using command in c++

I am trying to read a string into my program from the terminal. So the command I want to use is eg g++ -g -std=c++11 main.cpp -o out to compile, then ./out < file.txt to run my program. But I, however, get an error when I use a < symbol when running my program.
int main(int argc, char** argv){
cout << "Checking this " << argv[1] << endl;
return 0;
}
I want my program to output Checking this file.txt but I want to run it this way, ./out < file.txt NOT THIS AWAY ./out file.txt
This is not possible with this configuration. You would have to run the program as ./out file.txt and then have the program read in from file.txt which will have the file name stored in argv[1] assuming this order.
POSIX compliant shells when you run ./out < file.txt will just give your program the contents of file.txt in stdin. The < file.txt part is not visible to your program.

How to use a wildcard expression within system()

The following command runs fine on my embedded Linux (Beaglebone Black):
echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots
But not when using this small C++ program:
#include <stdlib.h>
#include <string>
int main {
system(std::string("echo bone_pwm_P9_21 > /sys/devices/bone_capemgr.?/slots").c_str());
return 0;
}
The problem involves the '?' question mark, that is used as a wildcard.
When the question mark, in the std::string that is passed to system(), is replaced with a normal character, the system() function evaluates the command perfect.
Solutions I've tried without success:
replace ? with \?
replace ? with *
Apart from your code not being compilable, this fails because system(3) runs sh, often a minimal shell provided by dash or busybox.
Meanwhile, your interactive login uses bash, ksh or some other more comfy shell.
dash and busybox sh do not do glob expansion on redirections, while bash and ksh do. Here's a demonstration of the behavior you want courtesy of bash:
$ touch file.txt
$ bash -c 'echo "bash contents" > *.txt'
$ cat file.txt
bash contents
Meanwhile, the problem you're having with e.g. dash:
$ dash -c 'echo "and now dash" > *.txt'
$ ls
*.txt file.txt
$ cat '*.txt' # Instead of expanding, the path was taken literally
and now dash
$ cat file.txt
bash contents
To fix this, you can (in order of preference)
Write your C program in C code instead of shell script
Call a better shell with execve.
Rewrite to not write to a glob, e.g. echo "stuff" | tee *.txt > /dev/null
Call a better shell with system, e.g. bash -c "echo stuff > *.txt"
NOTE: As πάντα ῥεῖ pointed out the system() command calls the shell which will usually do the expansion when presented with the correct wildcard: *. This answer is thereful more appropriate if you want the control to make each system() call separately or if the underlying shell is limited.
Original answer:
Perhaps you could use wordexp for this to construct your strings before you make the system() call:
#include <string>
#include <vector>
#include <iostream>
#include <wordexp.h>
std::vector<std::string> expand_env(const std::string& var, int flags = 0)
{
std::vector<std::string> vars;
wordexp_t p;
if(!wordexp(var.c_str(), &p, flags))
{
if(p.we_wordc)
for(char** exp = p.we_wordv; *exp; ++exp)
vars.push_back(exp[0]);
wordfree(&p);
}
return vars;
}
int main()
{
for(auto&& s: expand_env("$HOME/*")) // <= Note the wildcard '*'
std::cout << s << '\n';
}
In your specific case you could perhaps use something like this:
int main()
{
std::vector<std::string> devices = expand_env("/sys/devices/bone_capemgr.*/slots");
for(std::vector<std::string>::size_type i = 0; i < devices.size(); ++i)
system(("echo bone_pwm_P9_21 > " + devices[i]).c_str());
}

Piping input to an already running cpp program?

include
Lets assume that this is the code I am running:
int main(int argc, char **argv) {
bool running = true;
string lineInput;
while (running)
{
while (cin >> lineInput)
{
cout << lineInput;
}
}
return 0;
}
What I would like to have happen is that I can call start a program from terminal by typing "./myProgram" That part is fairly straight forward. The part I'm not sure how to do is make it so that I can at a later point in time type echo "some text to echo" | myProgram and be able to have my program then print that text back out to the terminal.
Right now I can only make it work if I type:
echo "blah blah blah" | ./myProgram
So my goal is to have two separate steps. One where I start my program, and a second when I pipe it some input to use
I'm thinking you could do this with a named pipe.
mkfifo mypipe
./myProgram < mypipe &
cat file1.txt file2.txt file3.txt > mypipe
You can use mkfifo, and just read from that in the program as from an ordinary file.
There's also
pipe or socket_pair (bi-directional)

Pipe an input to C++ cin from Bash

I'm trying to write a simple Bash script to compile my C++ code, in this case it's a very simple program that just reads input into a vector and then prints the content of the vector.
C++ code:
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<string> v;
string s;
while (cin >> s)
v.push_back(s);
for (int i = 0; i != v.size(); ++i)
cout << v[i] << endl;
}
Bash script run.sh:
#! /bin/bash
g++ main.cpp > output.txt
So that compiles my C++ code and creates a.out and output.txt (which is empty because there is no input). I tried a few variations using "input.txt <" with no luck. I'm not sure how to pipe my input file (just short list of a few random words) to cin of my c++ program.
You have to first compile the program to create an executable. Then, you run the executable. Unlike a scripting language's interpreter, g++ does not interpret the source file, but compiles the source to create binary images.
#! /bin/bash
g++ main.cpp
./a.out < "input.txt" > "output.txt"
g++ main.cpp compiles it, the compiled program is then called 'a.out' (g++'s default output name). But why are you getting the output of the compiler?
I think what you want to do is something like this:
#! /bin/bash
# Compile to a.out
g++ main.cpp -o a.out
# Then run the program with input.txt redirected
# to stdin and the stdout redirected to output.txt
./a.out < input.txt > output.txt
Also as Lee Avital suggested to properly pipe an input from the file:
cat input.txt | ./a.out > output.txt
The first just redirects, not technically piping. You may like to read David Oneill's explanation here: https://askubuntu.com/questions/172982/what-is-the-difference-between-redirection-and-pipe

Trace Words in Shell Script

I am trying to find malloc-free series. Consider that we have 1000s of test cases. People may forget to free ptr. Please help me in optimizing the script.
Sample File Under test
Test(func_class,func1)
{
int i,j;
char* ptr = (char*) malloc(sizeof(char));
free(ptr);
}
Test(func_class,func1)
{
int i,j;
char* ptr = (char*) malloc(sizeof(char));
/ Memory Leak /
}
Script under development :
export MY_ROOT=`pwd`
_COUNT=0
pwd
_COUNT_WORD=0
filename=test.c
cat $filename | while read line
do
echo "Reading Line = $LINE"
for word in $line
do
_COUNT_WORD=$(($_COUNT_WORD+1))
echo $_COUNT_WORD $word
if [ "$word" == "malloc\(sizeof\(char\)\);" ]; then
_MALLOC_FLAG=1 #this part of the code is not reached
echo "Malloc Flag Hi"
echo $word[2]
fi
done
_COUNT_WORD=0
done
I have some issue in matching the malloc regex. I know the script needs a lot of modifications as we have to find the pattern of individual person writing malloc.
There are other ways to check:
Using awk:
awk '/malloc/ || /free/{count++;}END{printf "%d",count}' fileundertest
This will search for "malloc" and "free" words in file and will print out the count. if count is even you can say for every malloc there is free.
Using grep:
grep -c "malloc" fileundertest
This will count the malloc word in file
Similarly,
grep -c "free" fileundertest
To list out the line number
grep -n "malloc" fileundertest