Песочница →
Пишем двуязычную программу
Недавно передо мной встала нелёгкая задачка, которую мне подкинул один знакомый. Суть состоит в том, чтобы, написав один исходник, можно было его скомпилировать в gcc и исполнить, также и исполнить через интерпретатор perl. Казалось бы, не так уж и сложно, но не всем программистам придёт в голову, как правильно написать данный исходник. Приступим к рассмотрению изначальных программ на C и Perl.
Голый Си:
Проверяем:
Теперь аналог на Perl:
Снова проверяем:
Теперь приступим решению поставленной задачи.
Приведу сразу готовый исходник для рассмотрения:
Тестируем результат:
Давайте рассмотрим хитрости обоих языков, использованные при написании.
На этом, в принципе, и все. Возможно у вас есть другие методы написания подобных «двуязычных» программ. С нетерпение жду ваших решений!
Голый Си:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sum=0;
int i;
for (i=1; i<argc; i++)
sum+=atoi(argv[i]);
printf("%d\n", sum);
return 0;
}
Проверяем:
cyber@punk:/opt# gcc test.c -o test1
cyber@punk:/opt# ./test1 -2 15 -13
0
cyber@punk:/opt# ./test1 2 4 6
12
Теперь аналог на Perl:
#!/usr/bin/perl
$sum=0;
foreach (@ARGV) {
$sum+=$_;
}
print "$sum\n";
Снова проверяем:
cyber@punk:/opt# perl test.pl 3 15 10 20
48
Теперь приступим решению поставленной задачи.
Приведу сразу готовый исходник для рассмотрения:
#include <stdio.h>
#include <stdlib.h>
#define $ /* */
#define ARGV argv
#define if($x) int main(int argc, char *argv[])
#define $start 1
#if PERL
sub atoi { $_[0] }
$ argc=@ARGV;
$ start=0;
$ x=1;
#endif
if($x)
{
int $ sum;
int $ i;
$ sum=0;
for ( $ i = $start; $ i < $ argc ; $ i++) {
$ sum += atoi ($ ARGV [$ i]);}
printf("%d\n", $ sum);
exit(0);
}
Тестируем результат:
cyber@punk:/opt# perl test4.c 3 15 10 20
48
cyber@punk:/opt# gcc test4.c -o test4
cyber@punk:/opt# ./test4 3 15 10 20
48
Давайте рассмотрим хитрости обоих языков, использованные при написании.
- Perl интерпретирует знак #, как начало комментария до конца строки, это дает возможность использовать директивы препроцессора Си, которые Perl будет игнорировать.
- Синтаксис языка Perl допускает пробел между знаком $ и именем переменной. Поэтому определение #define $ /* */ позволит в Си интерпретировать переменную вида $ var, как var, а в perl — как $var.
- В Си параметры командной строки передаются как char *argv[], а в perl — ARGV. Проблему решает директива: #define ARGV argv.
- В Си нулевой аргумент — это имя программы, а в Perl ARGV — переданный параметр. Обходится это введением переменной start, которая в Си устанавливается в единицу, а в Perl — в ноль. Кусок кода Perl экранируется в Си директивой #if PERL.
- Синтаксис операторов for и printf в Perl и Си одинаков, поэтому никаких дополнительных мер тут не требуется.
На этом, в принципе, и все. Возможно у вас есть другие методы написания подобных «двуязычных» программ. С нетерпение жду ваших решений!
06.11.2011 22:48+0400