Org Mode Babel - Интерактивная оценка кода блока

12

Я хотел бы оценить блоки исходного кода в режиме org в C ++, содержащие инструкции "cin", но я не могу найти способ провести интерактивную оценку (с пользовательским вводом) во время оценки. Пример кода:

#+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

Можно ли проводить такую ​​интерактивную оценку или моделировать (предоставляя исходному коду поддельный ввод)?

Lgen
источник
Вам действительно нужно, чтобы он был интерактивным, или вам просто нужно дать ему информацию, которую вы, возможно, уже знаете заранее, но не в этом блоке кода? Второй случай проще: вы можете использовать :var varname=valueв шапке. Во втором случае вы все еще можете использовать :var, но вместо значения используйте другой блок кода с функцией ELisp, который запрашивает ввод.
wvxvw
Спасибо @wvxvw за ваш ответ; Я хочу сделать документ с некоторыми примерами программ для студентов, и поэтому я хотел бы оставить блок исходного кода «как есть»; таким образом, мое предпочтение будет вторым случаем, который вы упомянули; Я постараюсь следовать вашему предложению (чтобы использовать: var и elisp-код для запроса ввода), есть ли у вас ссылка или пример такого вызова?
Lgen
Ой, прости, было немного недоразумений. Второй пример будет использовать Emacs для чтения ввода, но Бабель не будет вызывать программу на C ++ таким образом, чтобы разрешить взаимодействие. Единственное, о чем я могу думать, это то, что если вы добавите в ваш код какую-то «полиморфную» функцию, которая имеет две реализации: одну, где вы читаете ввод в интерактивном режиме, и другую, где вы читаете его из файла или предоставляете во время оценки блока кода. ,
wvxvw

Ответы:

8

Нравится:

#+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

Создайте файл in.txtв том же каталоге, что и файл Org, с содержимым 10.

Або-або
источник
7

Вы можете попросить Emacs получить интерактивный ввод, используя именованный elispблок. Затем передайте собранное значение в блок souce C ++, используя :var c-variable=block-nameсинтаксис:

#+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 

Обратите внимание, что выходные данные исходных блоков передаются в виде строк, поэтому мы должны преобразовать их в целое число, следовательно, atoiи дополнительные #include.

erikstokes
источник
1
Делай как хочешь. Тем не менее, ваш код привязан к режиму Org, в то время как мой код можно дословно вставить и легко скомпилировать.
abo-abo
1
Спасибо @erikstrokes за этот вклад; У меня была похожая идея (использовать внешний блок) и я сделал микс с помощью решения abo-abo. Я опубликовал результат как ответ.
Lgen
4

Спасибо @ abo-abo за вашу помощь. Я последовал вашему предложению, которое является правильным, и даже немного улучшил его, чтобы редактировать только мой файл org (и автоматически создавать внешний входной файл). Идея состоит в том, чтобы создать блок внешнего кода (здесь сценарий bash с именем build_input_file), который создает файл данных, и автоматически вызывать его перед оценкой другого блока благодаря :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
источник