Org Mode Babel - Evaluación de bloque de código interactivo

12

Me gustaría evaluar en modo org los bloques de código fuente en C ++ que contienen instrucciones "cin", pero no puedo encontrar una manera de tener una evaluación interactiva (con la entrada del usuario) durante la evaluación. Ejemplo de código:

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

¿Es posible tener una evaluación tan interactiva o simular (dando al código fuente una entrada falsa)?

Lgen
fuente
¿Realmente necesita que sea interactivo, o simplemente necesita darle alguna información que ya conozca de antemano, pero no en este bloque de código? El segundo caso es más fácil: podría usarlo :var varname=valueen el encabezado. En el segundo caso, aún podría usar :var, pero en lugar de valor, use otro bloque de código con una función ELisp que solicite entrada.
wvxvw
Gracias @wvxvw por tu respuesta; Lo que quiero hacer es hacer un documento con algunos ejemplos de programas para estudiantes y, por lo tanto, me gustaría mantener el bloque de código fuente "tal cual"; entonces mi preferencia sería el segundo caso que mencionas; Trataré de seguir su sugerencia (para usar: var y un código elisp para solicitar información), ¿tiene un enlace o un ejemplo de dicha llamada?
Lgen
Oh, lo siento, ha habido un pequeño malentendido. El segundo ejemplo usaría Emacs para leer la entrada, pero Babel no llamará al programa C ++ de la manera que permita la interacción. Lo único en lo que puedo pensar es que si agrega alguna función "polimórfica" a su código, que tiene dos implementaciones: una, donde lee la entrada interactivamente, y otra, donde la lee del archivo o la proporciona durante la evaluación del bloque de código .
wvxvw

Respuestas:

8

Me gusta esto:

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

Cree un archivo in.txten el mismo directorio que el archivo Org, con contenido 10.

abo-abo
fuente
7

Puede pedirle a Emacs que obtenga la entrada interactiva utilizando un elispbloque con nombre . Luego pase el valor recolectado al bloque de fuente C ++ usando la :var c-variable=block-namesintaxis:

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

Tenga en cuenta que las salidas de los bloques de origen se pasan como cadenas, por lo que tenemos que convertirlo en un entero, de ahí el atoiy el extra #include.

erikstokes
fuente
1
Haz como quieras. Sin embargo, su código está vinculado al modo Org, mientras que el mío se puede copiar y pegar literalmente y compilar fácilmente.
abo-abo
1
Gracias @erikstrokes por esta contribución; Tuve una idea similar (usar un bloque externo) e hice una mezcla con la solución abo-abo. Publiqué el resultado como respuesta.
Lgen
4

Gracias @ abo-abo por tu ayuda. He seguido su sugerencia correcta e incluso la he mejorado un poco para editar solo mi archivo de organización (y para crear automáticamente el archivo de entrada externo). La idea es crear un bloque de código externo (aquí un script bash llamado build_input_file) que crea el archivo de datos y llamarlo automáticamente antes de evaluar el otro bloque gracias a :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
fuente