3

I'm trying to come up with a work around to perform a few math functions for a script since bash apparently cannot do anything other than integer math (or can it even do that?).

The script I'm coming up with needs to write a series of macros which will eventually be used for a simulation program. I'm currently just trying to output positions of a particle source which are used as parameters of the macro.

The C++ Program I wrote is very simple, it takes in i and outputs x and y as such:

#include <iostream>
#include <math.h>

using namespace std;

int main()
{
  double i;
  double theta = 11 * (3.1415926535897932384626/180);

  cin >> i;

  double b = 24.370;

  double y = (b/i)*sin(theta);
  double x = (b/i)*cos(theta);

  cout << x << " " <<  y << endl;

  return 0;
}

The script I'm writing outputs a bunch of stuff that has to do with the macros i'm trying to create, but the line I'm stuck on (labled as (1) ) needs to do something like this...

for i in {1..100}
do
  echo "./a.out" #calling the C program
  echo "$i" #entering i as input

  x = first output of a.out, y = second output a.out #(1) Confused on how to do this part!

  echo -n "/gps/position $x $y 0 27.7 cm" > mymacro.mac

done

I know there has to be a really easy way to do this but I'm not exactly sure what to do. I basically just need to use the output of a c program as variables in the script.

1
  • So, did you get your script working? Were any of the answers below helpful? Commented Oct 5, 2012 at 16:04

3 Answers 3

3

You should probably consider passing $i to your c++ program as a variable and using argv to read it in (this might be helpful). That's most likely the "proper" way to do it. Then you can use this for bash:

#!/bin/bash
IFS=' ';
for i in {1..100}
do
    read -ra values <<< `./a.out $i`
    x=${values[0]}
    y=${values[1]}
    echo -n "/gps/position $x $y 0 27.7 cm" > mymacro.mac
done

And are you sure you want > mymacro.mac instead of >> mymacro.mac (if the former is inside of a loop, only the last value will be written to the file mymacro.mac.

3
  • The man page says of -a: "The words are assigned to sequential indices of the array variable name, starting at 0." This way, we can be assured ${values[0]} is the first number and ${values[1]} is the second number. More importantly, I was using -ra for something else, and copy-paste makes my life easier ;)
    – cegfault
    Commented Jul 20, 2012 at 1:39
  • Oops - I meant -a and edited my comment. If you update your answer, I'll delete this comment!
    – Adam Liss
    Commented Jul 20, 2012 at 1:41
  • hmm, I'm getting an error saying "Comments may only be edited for 5 minutes"... sorry :( -r is used to make sure backslash will not be an escape character. In this application, it's probably moot (since it should never appear), but I've just been using -ra in my own stuff so it was easy to copy-paste as it was without thinking about it ;)
    – cegfault
    Commented Jul 20, 2012 at 1:46
1

You can use cegfault's answer, or more simply:

read val1 val2 <<< $(./a.out $i)

Which executes a.out and stores the two numbers in $val1 and $val2.

You may find it even easier to use awk, which does handle floating-point numbers and most math functions. Here's an arbitrary example:

bash> read x y <<< $(echo 5 | awk '{ printf "%f %f\n", cos($1), sin($1) }')
bash> echo $x
0.283662
bash> echo $y
-0.957824
1
  • I like this; seems a little more elegant than my solution (one-liners make the world go 'round)
    – cegfault
    Commented Jul 20, 2012 at 1:47
0

If your script will be long-lived or has a lot of data to process, and especially since you're writing part of the functionality in a C++ program anyway, you'll probably do a lot better to just write the whole thing in C++, and the end result will be a whopping lot faster... and more centralized & easier to see what's going on.

#include <iostream>
#include <math.h>
#include <sstream>
#include <fstream>

int main()
{
  const double theta = 11 * (3.1415926535897932384626/180);
  const double b = 24.370;

  for (int n=1; n<=100; ++n)
  {
    double i = n;
    double y = (b/i)*sin(theta);
    double x = (b/i)*cos(theta);

    // Two ways of sending the output to mymacro.mac......

    // 1. Via the system() call.....
    std::stringstream ss;
    ss << "echo -n \"/gps/position " << x << ' ' << y << " 0 27.7 cm\" > mymacro.mac";
    system(ss.str().c_str());

    // 2. Via C++ file I/O.....
    std::ofstream ofile("mymacro.mac");
    ofile << "/gps/position " << x << ' ' << y << " 0 27.7 cm";
    ofile.close(); //...not technically necessary; ofile will close when it goes out of scope.
  }
}

Note that this solution replicates your example with exquisite fidelity, including the part about overwriting the file 'mymacro.mac' on every loop iteration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.