How to use boost program_options to read an integer array? - c++

I am using Ubuntu and boost v1.50.
Previously I used boost program_options to feed a set of options into a program like so:
#!/bin/bash
./prog --arg1 1 --arg2 "2" --arg3 {1,2,3} --arg4 {1,2} --arg5 5
So I am dealing with a mix of single integers, strings and integer arrays.
This worked fine.
However, after "improving" the code by introducing local variables in bash, I have:
#!/bin/bash
a1=1
a2="2"
a3={1,2,3}
a4={1,2}
a5=5
./prog --arg1 $a1 --arg2 $a2 --arg3 $a3 --arg4 $a4 --arg5 $a5
Executing this results in an error:
error: the argument ('{1,2,3}') for option '--arg3' is invalid
I have set up the boost program_options like this:
namespace po = boost::program_options;
using namespace std;
try{
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("arg1", po::value<int>(&arg1)->required(), "doc1")
("arg2", po::value<string>(&arg2)->default_value("test"), "doc2")
("arg3", po::value<vector<int> >(&arg3)->multitoken(), "doc3")
("arg4", po::value<vector<int> >(&arg4)->multitoken(), "doc4")
("arg5", po::value<int>(&arg5)->default_value(1), "doc5")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
if(vm.count("help")) cout << desc << "\n";
}
catch(exception& e){
cerr << "error: " << e.what() << "\n";
errorflag=1;
}
catch(...){
cerr << "Exception of unknown type!\n";
errorflag=1;
}
Where did I go wrong? Is multitoken not appropriate in this context? What can I use instead? Is it not possible to read integer arrays?
I tried omitting multitoken but then it fails also.
Using quotation marks around the local variable in the bash script does not help either.
If I change the array input from {a,b,c} to "a b c", it is ok. However, I already have a large number of entries in the other format and I am would like to continue using it as other programs depend on it too.
I think it should be doable, since it worked without the local variables. Does someone know how?
EDIT: I have been mistaken. "a b c" does NOT work as input :(
EDIT 2: I came up with a little workaround:
I convert {a,b,c} -> a b c using
argnew=`echo ${arg:1:-1} | tr ',' ' '`
and the feeding it to the program works fine. Is that the best solution?

Changing your original script to add the -x bash debugging option, like this:
#!/bin/bash -x
./prog --arg1 1 --arg2 "2" --arg3 {1,2,3} --arg4 {1,2} --arg5 5
and then running it shows this output:
+ ./prog --arg1 1 --arg2 2 --arg3 1 2 3 --arg4 1 2 --arg5 5
So your curly brace groupings aren't working they way you think they're working, because bash command line processing is expanding them before invoking ./prog.
You can get it working if in your second script, if you change the assignments for a3 and a4 to be like this:
a3='1 2 3'
a4='1 2'
and then double-quote all your variables when you call ./prog:
./prog --arg1 "$a1" --arg2 "$a2" --arg3 "$a3" --arg4 "$a4" --arg5 "$a5"

Related

How to sort the output of C++ program (stdout) via "| sort"

I have a working program in c++ that creates a List and makes possible to fill that list with items (add), remove items, print items.
I want to test that add function works, so I create and run test.cc:
#include "List.h"
#include <string>
using namespace std;
int main()
{
List s;
s.add("OMG Milk Factory", "Milk", 140, 2);
s.add("Just Milk", "Milk", 80, 4);
s.print(cout);
return 0;
}
Because the print function shuffle items before printing, the output might be:
140 2 Milk OMG Milk Factory
80 4 Milk Just Milk
or
80 4 Milk Just Milk
140 2 Milk OMG Milk Factory
I create bash script and I want to sort the output of test.cc by using piping output to sort, but I do not know how. I have this one and it doesn't work:
compile_and_run() {
rm -f ./a.out
LANG=C run -C Build "g++ -std=c++17 -Wall -I. ~/Documents/testcase/$1 libhw2.a && ./a.out"
}
compile_and_run test.cc | sort
test "Add 2 Element Function Test" exact '140 2 Milk "OMG Milk Factory"\n80 4 Milk Just Milk\n' stdout
How to correctly use | sort ?
In your case you might just have to do
compile_and_run test.cc | sort -k1,1n
so that it sorts numerically in ascending order on the first column.

Pipe the output of a process to a file via UNIX shell command '>'

I need to pipe the output of printf statements in some c code so that instead of printing the output to the terminal, it will print the output to a file.
currently, I'm trying to do that with the following code:
int main() {
printf("Line 1 .. \n > output.txt");
write(1, "Line 2 ", 7);
}
This produces the output:
Line 1 ..
Line 2 > output.txtJims-MacBook-Pro-2:Homework1 JimmyNesbitt$
The output looks like its doing something along the lines of what I want it to do because the Line 2 comes before the > output.txt. But this is being printed to the terminal and not an external file. How can I get my print statements to be written to a file instead of printed to the terminal in this way?

Systemtap simple userspace example (function tracing, Ubuntu)?

(I've spent quite some time getting this to work, so I thought I'd document it - first, to put it formally as a question):
Is there a simple example of systemtap probing/tracing functions in a user-space application, preferably in C++? My system is Ubuntu 14.04:
$ uname -a
Linux mypc 4.2.0-42-generic #49~14.04.1-Ubuntu SMP Wed Jun 29 20:22:11 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ g++ --version
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 ...
$ stap --version
Systemtap translator/driver (version 2.3/0.158, Debian version 2.3-1ubuntu1.4 (trusty))
OK, so this didn't turn out to be trivial - first of all, I somehow ended up with a (newer) kernel 4.2.0 on Ubuntu 14.04; and apparently the systemtap that comes with Ubuntu 14.04 is too old for that kernel (see below). That means that I had to build systemtap from source - this was my procedure:
cd /path/to/src
git clone git://sourceware.org/git/elfutils.git elfutils_git
git clone git://sourceware.org/git/systemtap.git systemtap_git
cd systemtap_git
./configure --with-elfutils=/path/to/src/elfutils_git --prefix=/path/to/src/systemtap_git/local --enable-docs=no
make
make install
# after this, there are `stap` executables in:
# /path/to/src/systemtap_git/stap
# /path/to/src/systemtap_git/local/bin/stap
This is the thing:
you shouldn't build elfutils separately, and then systemtap - you should instead pass the elfutils source directory to --with-elfutils of systemtap's configure, which will then configure and build elfutils as well.
you MUST do make install of systemtap, even if it is in a non-system/private (local) directory! - otherwise, some errors occur (unfortunately, didn't log them)
After building, stap reports version:
$ ./stap --version
Systemtap translator/driver (version 3.2/0.170, commit release-3.1-331-g0efba6fc74c8 + changes) ...
Ok, so I found a basic Fibonacci C++ example for analysis, which I slightly modified, and called /tmp/fibo.cpp:
// based on: http://www.cplusplus.com/articles/LT75fSEw/
#include <iostream>
using namespace std;
class Fibonacci{
public:
int a, b, c;
void generate(int);
void doFibonacciStep(int);
};
void Fibonacci::doFibonacciStep(int istep){
c = a + b;
cout << " istep: " << istep << " c: " << c << endl;
a = b;
b = c;
}
void Fibonacci::generate(int n){
a = 0; b = 1;
cout << " Start: a "<< a << " b " << b << endl;
for(int i=1; i<= n-2; i++){
doFibonacciStep(i);
}
}
int main()
{
cout << "Hello world! Fibonacci series" << endl;
cout << "Enter number of items you need in the series: ";
int n;
cin >> n;
Fibonacci fibonacci;
fibonacci.generate(n);
return 0;
}
First I tried compiling it like this:
cd /tmp
g++ -g fibo.cpp -o fibo.exe
Now, the first thing that we want to do, is to figure out which functions are available for probing in our executable; for that, we can use stap -L (note, here I'm still using the old, Ubuntu 14.04 system stap):
$ stap -L 'process("/tmp/fibo.exe").function("*").call'
process("/tmp/fibo.exe").function("_GLOBAL__sub_I__ZN9Fibonacci15doFibonacciStepEi").call
process("/tmp/fibo.exe").function("__static_initialization_and_destruction_0").call $__initialize_p:int $__priority:int
process("/tmp/fibo.exe").function("doFibonacciStep#/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int
process("/tmp/fibo.exe").function("generate#/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int
process("/tmp/fibo.exe").function("main#/tmp/fibo.cpp:28").call
Nice - so I'd like to probe/trace the doFibonacciStep and its input argument, istep. So I try from the command line:
$ sudo stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe
WARNING: "__tracepoint_sched_process_fork" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined!
WARNING: "__tracepoint_sys_exit" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined!
WARNING: "__tracepoint_sys_enter" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined!
WARNING: "__tracepoint_sched_process_exec" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined!
WARNING: "__tracepoint_sched_process_exit" [/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko] undefined!
ERROR: Couldn't insert module '/tmp/stap51A5tV/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko': Unknown symbol in module
WARNING: /usr/bin/staprun exited with status: 1
Pass 5: run failed. [man error::pass5]
Tip: /usr/share/doc/systemtap/README.Debian should help you get started.
$ sudo stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe
ERROR: Couldn't insert module '/tmp/stapmo60OW/stap_ab5b824c79b38b5207910696c49c4e22_1760.ko': Unknown symbol in module
WARNING: /usr/bin/staprun exited with status: 1
Pass 5: run failed. [man error::pass5]
Ouch, errors like these - not good. The post "__tracepoint_sched_process_fork undefined" when run systemstap script explains that basically the stap version is too old for the kernel that I have - which required the building from source (above). So let's see now how the new stap -L works:
$ /path/to/src/systemtap_git/stap -L 'process("/tmp/fibo.exe").function("*").call'
process("/tmp/fibo.exe").function("_GLOBAL__sub_I__ZN9Fibonacci15doFibonacciStepEi#/tmp/fibo.cpp:37").call
process("/tmp/fibo.exe").function("__do_global_dtors_aux").call
process("/tmp/fibo.exe").function("__libc_csu_fini").call
process("/tmp/fibo.exe").function("__libc_csu_init").call
process("/tmp/fibo.exe").function("__static_initialization_and_destruction_0#/tmp/fibo.cpp:37").call $__initialize_p:int $__priority:int
process("/tmp/fibo.exe").function("_fini").call
process("/tmp/fibo.exe").function("_init").call
process("/tmp/fibo.exe").function("_start").call
process("/tmp/fibo.exe").function("deregister_tm_clones").call
process("/tmp/fibo.exe").function("doFibonacciStep#/tmp/fibo.cpp:13").call $this:class Fibonacci* const $istep:int
process("/tmp/fibo.exe").function("frame_dummy").call
process("/tmp/fibo.exe").function("generate#/tmp/fibo.cpp:20").call $this:class Fibonacci* const $n:int
process("/tmp/fibo.exe").function("main#/tmp/fibo.cpp:28").call
process("/tmp/fibo.exe").function("register_tm_clones").call
Nice, this is already a bit more verbose than the old version. Anyways, I'd like to probe the doFibonacciStep function, and its input argument, here $istep. So I write this on the command line:
$ sudo /path/to/src/systemtap_git/stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe
semantic error: while processing probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep#/tmp/fibo.cpp:13").call from: process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call
semantic error: No cfa_ops supplied, but needed by DW_OP_call_frame_cfa: identifier '$istep' at <input>:1:107
source: probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }
Pass 2: analysis failed. [man error::pass2]
Ouch - a nasty error, and doesn't really tell me anything - there are very few bug reports on this error (and mostly from 2010). So I was about to get stuck here, when for some reason, I remembered that the other day, I compiled some programs with -gdwarf-2 (for reasons I've forgotten by now); so I thought I'd try it - and whaddayaknow, it actually started working now:
$ g++ -gdwarf-2 fibo.cpp -o fibo.exe
$ sudo /path/to/src/systemtap_git/stap -e 'probe process("/tmp/fibo.exe").function("Fibonacci::doFibonacciStep").call { printf("stap do step: %d\n", $istep) }' -c /tmp/fibo.exe
Hello world! Fibonacci series
Enter number of items you need in the series: 5
Start: a 0 b 1
istep: 1 c: 1
istep: 2 c: 2
istep: 3 c: 3
stap do step: 1
stap do step: 2
stap do step: 3
Nice! Note that the stap prints are actually printed after the program has finished (that is, they are not interleaved with the actual program output where they occured).
Instead of specifying the probe points and behavior directly on the command line, we could write a script instead - so here is check-do-step.stp - here with some extra stuff:
#!/usr/bin/env stap
global stringone = "Testing String One"
global stringtwo = "Testing String Two"
probe begin {
printf("begin: %s\n", stringone)
#exit() # must have; else probe end runs only upon Ctrl-C if we only have `begin` and `end` probes!
}
probe process(
"/tmp/fibo.exe"
).function(
"Fibonacci::doFibonacciStep"
).call {
printf("stap do step: %d\n", $istep)
}
probe end {
newstr = "We Are " . stringtwo . " And We're Done" # string concat
printf("%s\n", newstr)
}
... and with this script, our call and results look like this:
$ sudo /path/to/src/systemtap_git/stap check-do-step.stp -c /tmp/fibo.exe
Hello world! Fibonacci series
Enter number of items you need in the series: begin: Testing String One
6
Start: a 0 b 1
istep: 1 c: 1
istep: 2 c: 2
istep: 3 c: 3
istep: 4 c: 5
stap do step: 1
stap do step: 2
stap do step: 3
stap do step: 4
We Are Testing String Two And We're Done
Notice again - the begin: Testing ... string does not hit at the very start as we'd otherwise expect, but only after the program already started generating output.
Well, I guess this is it - certainly good enough for me, for a simple example...

How to print something without this format : $[num]=[value] in GDB environment?

What I want is this :
(gdb) define mynext
Redefine command "mynext"? (y or n) y
Type commands for definition of "mynext".
End with a line saying just "end".
>print "------"
>print Location:
>where
>print "-------------"
>print Code:
>list
>print "---------------------"
>print Next:
>next
>end
This is what outputs is:
$1 = "-----"
....
I expect:
-----
....
I used call printf("opopo") also, but It print the return value of "opopo" which is 5. Just like this:$4 = 5
My question is: how can I print something without this format which is :$[num]=[value].
As you found, print puts the printed value into the value history. gdb provides two different ways to avoid this.
One is printf. This works somewhat like the C function, but is a gdb command. Use it like:
(gdb) printf "whatever you like\n"
whatever you like
(gdb)
Another is output. This is a bit like the print command, but does not enter the value into the value history.
(gdb) output 5
5(gdb)
You can see from this that output also doesn't emit a trailing newline. You would have to add that yourself.

Regex mirc situation

Hello i'm having a script but when i try to catch info that i need i cant this is the part of html code that i would like to get:
<div class="pretty-container " >
2100.0
</div>
So on my socket y try to do this to get the 2100.0(2100.0 it is a variable number):
on *:sockread:foo: {
var %read
sockread %read
if ($regex(%read,<div class="pretty-container " >(.*)<\/div>)) {
echo -s price founded: $regml(1)
; - here i try to catch the 2100.0 number
sockclose $sockname
}
}
but this doesn't work i believe it is because the number and are in another line. con some one helpme to solve this please?
thanks in advace,
Carlos
The sockread command you use only reads one line at a time. Seeing as the data you're looking for is spread over multiple lines, your regular expression will never find a match.
A solution to this would be simply checking whether the current line contains <div class="pretty-container " >, and if so, store the data of the next line in another variable:
var %read, %number
sockread %read
if (<div class="pretty-container " > isin %read) {
sockread %number
echo -s Number: %number
sockclose $sockname
}