Я думаю, что это может быть достигнуто проще всего при использовании Python плюс matplotlib . Чтобы достичь этого, на самом деле есть несколько способов: а) интегрировать Python Interpreter непосредственно в ваше приложение на C, б) распечатать данные в стандартный вывод и передать их в простой скрипт на Python, который выполняет фактическое построение. Далее я опишу оба подхода.
У нас есть следующее приложение C (например, plot.c
). Он использует интерпретатор Python для взаимодействия с функциями построения графиков в matplotlib. Приложение может отображать данные напрямую (при вызове как ./plot --plot-data
) и печатать данные в stdout
(при вызове с любым другим набором аргументов).
#include <Python.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CMD_BUF_SIZE 256
void initializePlotting() {
Py_Initialize();
// load matplotlib for plotting
PyRun_SimpleString("from matplotlib import pyplot as pp");
PyRun_SimpleString("pp.ion()"); // use pp.draw() instead of pp.show()
}
void uninitializePlotting() {
Py_Finalize();
}
void plotPoint2d(double x, double y) {
// this buffer will be used later to handle the commands to python
static char command[CMD_BUF_SIZE];
snprintf(command, CMD_BUF_SIZE, "pp.plot([%f],[%f],'r.')\npp.draw()", x, y);
PyRun_SimpleString(command);
}
double myRandom() {
double sum = .0;
int count = 1e4;
int i;
for (i = 0; i < count; i++)
sum = sum + rand()/(double)RAND_MAX;
sum = sum/count;
return sum;
}
int main (int argc, const char** argv) {
bool plot = false;
if (argc == 2 && strcmp(argv[1], "--plot-data") == 0)
plot = true;
if (plot) initializePlotting();
// generate and plot the data
int i = 0;
for (i = 0; i < 1000; i++) {
double x = myRandom(), y = myRandom();
if (plot) plotPoint2d(x,y);
else printf("%f %f\n", x, y);
}
if (plot) uninitializePlotting();
return 0;
}
Вы можете построить его так:
$ gcc plot.c -I /usr/include/python2.7 -l python2.7 -o plot
И запустите его как:
$ ./plot --plot-data
Затем он некоторое время будет рисовать красные точки на оси.
Когда вы решаете не выводить данные напрямую, а печатать их на stdout
, вы можете выполнять построение с помощью внешней программы (например, сценария Python с именем plot.py
), которая принимает данные из stdin
, т.е. труба, и наносит на график данные, которые он получает.
Для этого вызовите программу типа ./plot | python plot.py
, с plot.py
, аналогичной:
from matplotlib import pyplot as pp
pp.ion()
while True:
# read 2d data point from stdin
data = [float(x) for x in raw_input().split()]
assert len(data) == 2, "can only plot 2d data!"
x,y = data
# plot the data
pp.plot([x],[y],'r.')
pp.draw()
Я протестировал оба подхода на моей машине с Debian. Для этого требуются пакеты python2.7
и python-matplotlib
.
EDIT
Я только что видел, что вы хотели построить гистограмму или что-то подобное, это, конечно, также возможно с помощью matplotlib, например гистограмма:
from matplotlib import pyplot as pp
pp.ion()
values = list()
while True:
data = [float(x) for x in raw_input().split()]
values.append(data[0])
pp.clf()
pp.hist([values])
pp.draw()