12

I would like to evaluate in org mode source code blocks in C++ containing "cin" instructions but I can't find a way to have an interactive evaluation (with user input) during evaluation. Example of code :

#+BEGIN_SRC C++  :results output :export code :tangle myfile.cpp 
#include <iostream>
using namespace std;

int main()
{
int a;
cin>>a;
cout<<a+1;
}
#+END_SRC

Is it possible to have such an interactive evaluation or to simulate (by giving to the source code a fake input) ?

Lgen
  • 1,380
  • 10
  • 19
  • Do you actually need it to be interactive, or do you just need to give it some input you may already know in advance, just not in this code block? The second case is easier: you could use `:var varname=value` in the header. In the second case you could still use `:var`, but in place of value use another code block with an ELisp function which asks for input. – wvxvw Aug 26 '15 at 18:43
  • Thanks @wvxvw for your answer; What I want to do is to make a document with some program examples for students and therefore I would like to keep the source code block "as is"; so my preference would be the second case you mention; I will try to follow your suggestion (to use :var and an elisp code to ask for input), do you have a link or an example of such a call ? – Lgen Aug 27 '15 at 06:46
  • Oh, sorry, there's been a bit of misunderstanding. The second example would use Emacs to read the input, but Babel won't call C++ program in the way such as to allow interaction. The only thing I can think about is that if you add some "polymorphic" function to your code, which has two implementations: one, where you read input interactively, and another one, where you read it from file or provide during code block evaluation. – wvxvw Aug 27 '15 at 07:02

3 Answers3

9

Like this:

#+begin_src C++ :results output :cmdline < in.txt
#include <iostream>
int main(int argc, char *argv[]) {
  int a;
  std::cin >> a;
  std::cout << a + 1;
  return 0;
}

#+end_src

#+RESULTS:
: 11

Create a file in.txt in the same directory as the Org file, with contents 10.

abo-abo
  • 13,943
  • 1
  • 29
  • 43
8

You can ask Emacs to get the interactive input instead using a named elisp block. Then pass the collected value to the C++ souce block using the :var c-variable=block-name syntax:

#+name: input_block
#+BEGIN_SRC elisp :export none :results none
(completing-read "a=" nil)

#+END_SRC

#+BEGIN_SRC C++  :results output :export code :tangle myfile.cpp :var input=input_block
  #include <stdlib.h>
  #include <iostream>
  using namespace std;

  int main()
  {
  int a = atoi(input);
  cout<<a+1;
  }
#+END_SRC 

Note that the outputs of source blocks are passed around as strings, so we have to convert it to an integer, hence the atoi and the extra #include.

erikstokes
  • 12,686
  • 2
  • 34
  • 56
  • 1
    Do as you like. However, your code is bound to Org-mode, while mine can be copy-pasted verbatim and readily compiled. – abo-abo Aug 27 '15 at 12:40
  • 1
    Thanks @erikstrokes for this contribution; I had a similar idea (use an external block) and made a mix with abo-abo solution. I posted the result as an answer. – Lgen Aug 27 '15 at 12:56
4

Thanks @abo-abo for your help. I have followed your suggestion which is right and even enhanced it a little to edit only my org file (and to create automatically the external input file). The idea is to create an external code block (here a bash script named build_input_file) which creates the data file and to call it automatically before evaluating the other block thanks to the:var tmp=build_input_file.

#+name: build_input_file
#+BEGIN_SRC bash  :results none :exports none 
echo "10 12" > in.txt
#+END_SRC

#+name: my_function_with_cin
#+BEGIN_SRC C++  :results output :exports both  :var tmp=build_input_file :cmdline < in.txt
#include <iostream>
using namespace std;

int main()
{
 int a,b;
 cin>>a>>b;
 cout<<a<<" "<<b;
}
#+END_SRC
Lgen
  • 1,380
  • 10
  • 19