Org Mode Babel - Đánh giá khối mã tương tác


12

Tôi muốn đánh giá các khối mã nguồn ở chế độ org trong C ++ có chứa các hướng dẫn "cin" nhưng tôi không thể tìm cách đánh giá tương tác (với đầu vào của người dùng) trong quá trình đánh giá. Ví dụ về mã:

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

Có thể có một đánh giá tương tác như vậy hoặc mô phỏng (bằng cách cung cấp cho mã nguồn một đầu vào giả)?


Bạn có thực sự cần nó để tương tác, hoặc bạn chỉ cần cung cấp cho nó một số đầu vào mà bạn có thể đã biết trước, chỉ là không có trong khối mã này? Trường hợp thứ hai dễ dàng hơn: bạn có thể sử dụng :var varname=valuetrong tiêu đề. Trong trường hợp thứ hai, bạn vẫn có thể sử dụng :var, nhưng thay vì giá trị, hãy sử dụng một khối mã khác có chức năng ELisp yêu cầu nhập liệu.
wvxvw

Cảm ơn @wvxvw cho câu trả lời của bạn; Những gì tôi muốn làm là tạo một tài liệu với một số ví dụ chương trình cho sinh viên và do đó tôi muốn giữ khối mã nguồn "như hiện tại"; vì vậy sở thích của tôi sẽ là trường hợp thứ hai bạn đề cập; Tôi sẽ cố gắng làm theo đề xuất của bạn (để sử dụng: var và một mã elisp để yêu cầu đầu vào), bạn có một liên kết hoặc một ví dụ về một cuộc gọi như vậy không?
Lgen

Ồ, xin lỗi, đã có một chút hiểu lầm. Ví dụ thứ hai sẽ sử dụng Emacs để đọc đầu vào, nhưng Babel sẽ không gọi chương trình C ++ theo cách như để cho phép tương tác. Điều duy nhất tôi có thể nghĩ là nếu bạn thêm một số chức năng "đa hình" vào mã của mình, có hai triển khai: một, trong đó bạn đọc đầu vào tương tác và một chức năng khác, nơi bạn đọc nó từ tệp hoặc cung cấp trong quá trình đánh giá khối mã .
wvxvw

Câu trả lời:


8

Như thế này:

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

Tạo một tệp in.txttrong cùng thư mục với tệp Org, có nội dung 10.


7

Bạn có thể yêu cầu Emacs lấy đầu vào tương tác thay vì sử dụng một elispkhối được đặt tên . Sau đó chuyển giá trị được thu thập vào khối souce C ++ bằng :var c-variable=block-namecú pháp:

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

Lưu ý rằng đầu ra của các khối nguồn được truyền xung quanh dưới dạng chuỗi, vì vậy chúng tôi phải chuyển đổi nó thành một số nguyên, do đó atoivà thêm #include.


1
Làm như bạn muốn. Tuy nhiên, mã của bạn được liên kết với chế độ Org, trong khi mã của tôi có thể được sao chép nguyên văn và sẵn sàng biên dịch.
abo-abo

1
Cảm ơn @erikstrokes vì ​​sự đóng góp này; Tôi đã có một ý tưởng tương tự (sử dụng một khối bên ngoài) và thực hiện kết hợp với giải pháp abo-abo. Tôi đăng kết quả như một câu trả lời.
Lgen

4

Cảm ơn @ abo-abo vì sự giúp đỡ của bạn. Tôi đã làm theo đề xuất của bạn là đúng và thậm chí tăng cường một chút để chỉ chỉnh sửa tệp org của tôi (và để tự động tạo tệp đầu vào bên ngoài). Ý tưởng là tạo một khối mã bên ngoài (ở đây là một tập lệnh bash có tên build_input_file) để tạo tệp dữ liệu và gọi nó tự động trước khi đánh giá khối khác nhờ vào :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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.