Org Mode Babel - Interaktywna ocena bloku kodu


12

Chciałbym oceniać bloki kodu źródłowego w trybie org w C ++ zawierające instrukcje „cin”, ale nie mogę znaleźć sposobu na interaktywną ocenę (z wkładem użytkownika) podczas oceny. Przykład kodu:

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

Czy możliwe jest przeprowadzenie takiej interaktywnej oceny lub symulacji (poprzez podanie kodu źródłowego fałszywych danych wejściowych)?


Czy rzeczywiście potrzebujesz interaktywności, czy po prostu musisz podać jakieś informacje, które możesz znać z góry, ale nie w tym bloku kodu? Drugi przypadek jest łatwiejszy: możesz użyć :var varname=valuew nagłówku. W drugim przypadku możesz nadal używać :var, ale zamiast wartości użyj innego bloku kodu z funkcją ELisp, która prosi o podanie danych.
wvxvw

Dzięki @wvxvw za odpowiedź; Chcę zrobić dokument z niektórymi przykładami programów dla studentów, dlatego chciałbym zachować blok kodu źródłowego „taki, jaki jest”; więc preferuję drugi przypadek, o którym wspominasz; Spróbuję postępować zgodnie z twoją sugestią (użyć: var i kod elisp, aby poprosić o dane wejściowe), czy masz link lub przykład takiego połączenia?
Lgen

Przepraszam, było trochę nieporozumień. Drugi przykład użyłby Emacsa do odczytania danych wejściowych, ale Babel nie wywoła programu C ++ w sposób umożliwiający interakcję. Jedyne, o czym mogę pomyśleć, to to, że jeśli dodasz do kodu jakąś funkcję „polimorficzną”, która ma dwie implementacje: jedną, w której interaktywnie odczytujesz dane wejściowe, i drugą, w której odczytujesz dane z pliku lub udostępniasz podczas oceny bloku kodu .
wvxvw

Odpowiedzi:


8

Lubię to:

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

Utwórz plik in.txtw tym samym katalogu co plik organizacji z zawartością 10.


7

Zamiast tego możesz poprosić Emacsa o interaktywne wprowadzanie danych za pomocą nazwanego elispbloku. Następnie przekaż zebraną wartość do bloku souce C ++, używając :var c-variable=block-nameskładni:

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

Zauważ, że wyjścia bloków źródłowych są przekazywane jako ciągi, więc musimy przekonwertować je na liczbę całkowitą, stąd atoii dodatkowe #include.


1
Rób co chcesz. Jednak twój kod jest powiązany z trybem Org, podczas gdy mój można kopiować i wklejać dosłownie i łatwo kompilować.
abo-abo

1
Dzięki @erikstrokes za ten wkład; Miałem podobny pomysł (użyj zewnętrznego bloku) i zrobiłem miks z rozwiązaniem abo-abo. Wynik opublikowałem jako odpowiedź.
Lgen

4

Dzięki @ abo-abo za pomoc. Postępowałem zgodnie z twoją sugestią, która jest właściwa, a nawet trochę ją ulepszyłem, aby edytować tylko mój plik org (i automatycznie tworzyć zewnętrzny plik wejściowy). Pomysł polega na utworzeniu zewnętrznego bloku kodu (tutaj skrypt bash o nazwie build_input_file), który tworzy plik danych i wywołuje go automatycznie przed oceną drugiego bloku dzięki :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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.