Org Mode Babel - Evaluasi blok kode interaktif

12

Saya ingin mengevaluasi dalam blok kode sumber mode org dalam C ++ yang berisi instruksi "cin" tetapi saya tidak dapat menemukan cara untuk melakukan evaluasi interaktif (dengan input pengguna) selama evaluasi. Contoh kode:

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

Apakah mungkin untuk melakukan evaluasi interaktif atau mensimulasikan (dengan memberikan kode sumber input palsu)?

Lgen
sumber
Apakah Anda benar-benar membutuhkannya untuk menjadi interaktif, atau Anda hanya perlu memberikan beberapa masukan yang mungkin sudah Anda ketahui sebelumnya, hanya saja tidak dalam blok kode ini? Kasus kedua lebih mudah: Anda bisa menggunakan :var varname=valuedi header. Dalam kasus kedua Anda masih bisa menggunakan :var, tetapi sebagai pengganti nilai gunakan blok kode lain dengan fungsi ELisp yang meminta input.
wvxvw
Terima kasih @ wvxvw atas jawaban Anda; Yang ingin saya lakukan adalah membuat dokumen dengan beberapa contoh program untuk siswa dan oleh karena itu saya ingin menjaga blok kode sumber "apa adanya"; jadi preferensi saya akan menjadi kasus kedua yang Anda sebutkan; Saya akan mencoba mengikuti saran Anda (untuk menggunakan: var dan kode elisp untuk meminta masukan), apakah Anda memiliki tautan atau contoh panggilan seperti itu?
Lgen
Oh, maaf, ada sedikit kesalahpahaman. Contoh kedua akan menggunakan Emacs untuk membaca input, tetapi Babel tidak akan memanggil program C ++ dengan cara seperti mengizinkan interaksi. Satu-satunya hal yang dapat saya pikirkan adalah bahwa jika Anda menambahkan beberapa fungsi "polimorfik" ke kode Anda, yang memiliki dua implementasi: satu, di mana Anda membaca input secara interaktif, dan yang lain, di mana Anda membacanya dari file atau menyediakan selama evaluasi blok kode .
wvxvw

Jawaban:

8

Seperti ini:

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

Buat file in.txtdi direktori yang sama dengan file Org, dengan konten 10.

abo-abo
sumber
7

Anda dapat meminta Emacs untuk mendapatkan input interaktif alih-alih menggunakan elispblok bernama . Kemudian meneruskan nilai yang dikumpulkan ke blok sumber C ++ menggunakan :var c-variable=block-namesintaksis:

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

Perhatikan bahwa output dari blok sumber dilewatkan sebagai string, jadi kita harus mengubahnya menjadi bilangan bulat, karenanya atoidan ekstra #include.

erikstokes
sumber
1
Lakukan sesukamu. Namun, kode Anda terikat ke mode-Org, sedangkan kode saya dapat disalin-tempel kata demi kata dan siap dikompilasi.
abo-abo
1
Terima kasih @erikstrokes untuk kontribusi ini; Saya punya ide serupa (menggunakan blok eksternal) dan membuat campuran dengan solusi abo-abo. Saya memposting hasilnya sebagai jawaban.
Lgen
4

Terima kasih @ abo-abo atas bantuan Anda. Saya telah mengikuti saran Anda yang benar dan bahkan sedikit ditingkatkan untuk mengedit hanya file org saya (dan untuk membuat secara otomatis file input eksternal). Idenya adalah untuk membuat blok kode eksternal (di sini skrip bash bernama build_input_file) yang membuat file data dan untuk memanggilnya secara otomatis sebelum mengevaluasi blok lain terima kasih kepada :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
sumber