Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > PHP to C++


Автор: A12345 21.1.2007, 14:25
Всем привет. У меня такая проблема. 

Имеется скрипт на PHP, который обрабатывает текстовый файл, используя алгоритм, определённый в другом файле (см. ниже 'cat', 'dog', 'bird').

Нужно то же самое реализовать в виде консольного приложения на С++.

Опыта работы с C++ у меня нет. (но есть опыт с Perl, PHP, JavaScript и т.п., из чего следует что с некоторыми структурами и синтаксисом C++ разобраться сложно)

Просмотрев несколько учебников по С++, в принципе разобрался как это реализовать, но возникла проблема с постройкой главной структуры и доступа к ней (см. ниже “$this->results”).

Подскажите аналог этого PHP кода, на C++:


Код

<?php
// PHP to C++

class start
{
    function start()
    {
    $data["date"] = date("d.m.y");
    $data["time"] = date("H:i:s");
    
    $this->results = array(
        'objects' => array(),
        'errors' => array(),
        'clock' => &$data,
        'profile' => array(),
    );
    }

    function run()
    {
    $ids = array('cat', 'dog', 'bird');
    $results = &$this->results;
        foreach($ids as $k)
        {
        $results['objects'][$k] = new $k;
        $results['profile'][$k] = $results['objects'][$k]->profile;
        }

    $k = 'cat';
    $obj = &$results['objects'][$k];
        if($obj->profile['info'] == "")
        {
        $results['errors'][$k] = 'empty info ('.$k.')';
        }
    $obj->print_hello();
    print $results['clock']['date'];
    }
}// End class start

class cat
{
    function cat()
    {
    $this->profile = array(
        'name' => 'cat',
        'info' => 'about cat',
    );
    }
    function print_hello()
    {
    print "hello (cat)";
    }
}

class dog
{
    function dog()
    {
    $this->profile = array(
        'name' => 'dog',
        'info' => 'about dog',
    );
    }
    function print_hello()
    {
    print "hello (dog)";
    }
}

class bird
{
    function bird()
    {
    $this->profile = array(
        'name' => 'bird',
        'info' => 'about bird',
    );
    }
    function print_hello()
    {
    print "hello (bird)";
    }
}


function main()
{
$a = new start();
$a->run();
}

main();

?>

Автор: KpoHyc 21.1.2007, 14:53
A12345, а можно постановку задачи?

Автор: Axxent 22.1.2007, 10:54
Задачка в общем-то интересная получается. Однако решить ее в С++ можно только с некоторой потерей гибкости - например создание объектов по имени класса придется забивать в switch, либо юзать какие-то неизвестные мне технологии RTTI по созданию объектов из строкового представления имени класса (если они вообще такие есть). Как минимум полиморфизм и наследование будет необходимо. 
Теперь надо постановку задачи и ограничения на гибкость - обязательно ли создавать объекты по имени или это финт писавшего это чудо программиста. И в чем кроме этого загвоздка - тоже описать.

Автор: KpoHyc 22.1.2007, 11:22
Axxent, постановкито и не хватает)

Автор: A12345 22.1.2007, 13:20
Код PHP я модифицировал -- удалил "$this->results" (см. ниже).

Цитата(Axxent @  22.1.2007,  10:54 Найти цитируемый пост)
обязательно ли создавать объекты по имени
+
Цитата(Axxent @  22.1.2007,  10:54 Найти цитируемый пост)
И в чем кроме этого загвоздка - тоже описать.

Алгоритм работы ядра программы:
1.    Программа получает данные 'cat', 'dog', ‘bird’ (и/или) ($ids).
2.    Проверяет, существуют ли эти классы, если да то обрабатывает текстовой файл, используя алгоритмы, описанные в этих классах (вызывая функцию "print_hello()" каждого класса).
3.    Далее идёт работа с объектами $this->objects[$k], где $k имена инициализированных объектов, хранящиеся в массиве $ids.

Цитата(KpoHyc @  21.1.2007,  14:53 Найти цитируемый пост)
A12345, а можно постановку задачи? 

Главная задача создать код на C++, по функциональности соответствующей этому коду на PHP (он описывает ядро программы).

Самая большая проблема, как сделать на C++: $this->objects[$k] = new $k;

Подскажите аналог этого PHP кода, на C++ (версия 2):
Код

<?php
// PHP to C++ (2)

class start
{
    function start()
    {
    $data["date"] = date("d.m.y");
    $data["time"] = date("H:i:s");
    
    $this->objects = array();
    $this->errors = array();
    $this->clock = &$data;
    $this->profile = array();
    }

    function run()
    {
    $ids = array('cat', 'dog', 'bird');
        foreach($ids as $k)
        {
        $this->objects[$k] = new $k;
        $this->profile[$k] = $this->objects[$k]->profile;
        }

    $k = 'cat';
    $obj = &$this->objects[$k];
        if($obj->profile['info'] == "")
        {
        $this->errors[$k] = 'empty info ('.$k.')';
        }
    $obj->print_hello();
    print $this->clock['date'];
    }
}// End class start

class cat
{
    function cat()
    {
    $this->profile = array(
        'name' => 'cat',
        'info' => 'about cat',
    );
    }
    function print_hello()
    {
    print "hello (cat)";
    }
}

class dog
{
    function dog()
    {
    $this->profile = array(
        'name' => 'dog',
        'info' => 'about dog',
    );
    }
    function print_hello()
    {
    print "hello (dog)";
    }
}

class bird
{
    function bird()
    {
    $this->profile = array(
        'name' => 'bird',
        'info' => 'about bird',
    );
    }
    function print_hello()
    {
    print "hello (bird)";
    }
}

function main()
{
$a = new start();
$a->run();
}

main();

?>

Автор: Axxent 22.1.2007, 14:17
Цитата

Самая большая проблема, как сделать на C++: $this->objects[$k] = new $k;

Вот. Значит все-таки надо делать фабрику объектов. Хотя на половину своих вопросов я так и не получил ответа. Например,постановка задачи - то что надо перевести код понятно. Но его будет проще перевести если знать сразу что нужно сделать в этом коде. Подходы к проектированию в пхп и с++ сильно различаются.

Код

class obj {
    virtual string getHello()=0;
};

class cat public obj {
    string name;
    string info;
public:
    cat() {
         name = "cat";
         info = "about cat";
    }
    string getHello() {
        return string("hello (cat)");
    }
};
// доги и птахи аналогично, наследуются оттуда же

Теперь start
Код

class start {
    obj** rep;
    obj* makeObject(string what) {
         switch(what) {
             case "cat": return new cat(); // прямо какой-то английский текст получаецо, ей-богу
             case "dog": return new dog();
             case "bird": return new bird();
             default: return NULL;
        }
    }
public:
    start() {
         // что-то там еще делается...
         rep = new obj*[10]; // допустим 10 объектов
    }
    void run() {
        string arr[3];
        arr[0]="cat";
        arr[1]="dog";
        arr[2]="bird";
        for(int i=0; i<2; i++) {
            rep[i]=makeObject(arr[i]);
        }
        //....делаем что-то дальше
        int k=1;
        obj* myobj = rep[k];
        cout << obj->getHello();
        //... итд
    }
};


В общем-то тут было бы лучше использовать ассоциативное множество типа map или что-нибудь в этом духе для представления аналогичных пхп ассоциативных массивов, если не разберешься то посмотрим, глядишь кто поможет.

Автор: A12345 22.1.2007, 21:13
Цитата(Axxent @  22.1.2007,  14:17 Найти цитируемый пост)
    obj* makeObject(string what) {
         switch(what) {
             case "cat": return new cat();
             case "dog": return new dog();

Не подходит.
Программа будет компилироваться 1 раз.
А к "cat", "dog", "bird" будут добавляться/удаляться новые "классы".
В программе определить все их возможные названия невозможно.

Структура программы:
proga.exe
+
Конфигурационные файлы:
cat.ini, dog.ini (может быть любое название).
Например, cat.ini:
[profile]
name=cat
info=about cat
[hello]
print=hello (cat)

- Программа разбирает те конфиг. файлы какие у неё требуют.
- Все классы делают одно и тоже, только с разными переменными.

Задача будет более очевидна если классы "cat", "dog", "bird" разместить отдельно в соответствующих их названию файлах и подключать их по мере необходимости динамически, а $ids получать из серверной предопределённой переменной:
Код
    $ids = split (":", $_GET['text']);
        foreach($ids as $k)
        {
        include $k.php;
        $this->objects[$k] = new $k;
        $this->profile[$k] = $this->objects[$k]->profile;
        }

Структура:
php_to_cpp_3.php
cat.php
dog.php
bird.php





Автор: A12345 22.1.2007, 21:27
Aналоги для $this->errors и $this->clock на C++ готовы

Теперь надо как-то изменить "class OBJpair" чтобы в "second" ставить объекты (если это возможно конечно).
Код

// php to cpp
#include <string>
#include <vector>
#include <iostream>
using namespace std;

class OBJpair : public pair<string, string>// надо изменить
{
public:
    OBJpair(){};
    OBJpair(string name, string value)
    {
    first = name;
    second = value;// Здесь как-то вместо "value" надо сделать "new ClassA(name)"
    }
};


class OBJmap: public vector<OBJpair>
{
    string name;
    void operator=(OBJmap&);
    OBJmap(OBJmap&);
public:
    OBJmap(string what): name(what)
    {
        if(name == "cat")
        {
        push_back(OBJpair("cat", "value in class OBJpair must be Object (cat)"));
        }
        else
        {
        cout << "error_exit\n";
        exit(1);
        }
    }

    string operator[](const string& key)
    {
    iterator i = begin();
        while(i != end())
        {
        if(i->first == key)
        return i->second;
        i++;
        }
    return string();
    }
};// End class OBJmap




int main()
{
string name = "cat";

OBJmap objects(name);
cout << objects["cat"] << endl;

// Теперь !теоретически!, objects["cat"] -- будет объект, если класс "OBJpair", изменить

/*
string name2 = "dog";
OBJmap objects(name);
cout << objects["dog"] << endl;
// и т.д..
*/
}


/*
class ClassA //??????????????????
{
string name;
string info;
string print;
public:
    ClassA(string name)
    {
    // name -- это 'cat', 'dog', 'bird' или что-то ещё
    // Здесь разбирается файл name.ini и устанавливаются переменные
    // Например "cat.ini":
    // [profile]
    // name=cat
    // info=about cat
    // [hello]
    // print=hello (cat)

    name = "cat";
    info = "about cat";
    print = "hello (cat)";
    }
    
    string getHello()
    {
    return hello;
    }
};
*/

Автор: nickless 22.1.2007, 21:35
Цитата(A12345 @ 22.1.2007,  20:13)
Программа будет компилироваться 1 раз.
А к "cat", "dog", "bird" будут добавляться/удаляться новые "классы".
В программе определить все их возможные названия невозможно.

C++ это не скриптовый язык как php, javascript итд, тут нельзя без перекомпиляции добавить новый класс, так что прийдётся это сделать как-то по-другому.

Если точно известно набор возможностей, доступных такому скажем так "модулю", то можно придумать язык для описания алгоритма и написать класс, читающий его и интерпретирующий, это примерно то, что ты начал делать, но тут надо для начала знать, что именно должен делать класс, если получается настоящий язык то легче оставить всё как есть.

Можно сделать по принципу плагинов, т.е. главная программа загружает "модули" = динамические библиотеки с определённым набором функций (типа process(char* filename)), тогда действительно можно динамически добавлять совершенно новые модули.

Оба метода потребуют написать довольно много кода, на это уйдёт время, поэтому сначала надо бы задаться вопросом, а стоит ли оно того?
Чем не устраивает решение на php? Какова задача, может можно обойтись без динамических "модулей" (_забудь_ на момент про способы, возможные в php)?

ЗЫ
Прочитал вот это:
Цитата(A12345 @  22.1.2007,  20:13 Найти цитируемый пост)
- Все классы делают одно и тоже, только с разными переменными.

Т.е. я так понимаю алгоритм у всех классов один и тот же, только скажем "коты" всегда заменяют слова "кто я" на "кот" ан "собаки" на "собака"?
Тогда тебе вообще только _один_ класс нужен, без наследствия, просто при инициализации нужно прочитать из файла эти переменные.

Автор: Axxent 22.1.2007, 22:13
Цитата

А к "cat", "dog", "bird" будут добавляться/удаляться новые "классы".
В программе определить все их возможные названия невозможно.

В php ты также едва ли сможешь добавить новый класс без написания нового кода через одни только ini-файлы. Разница только в том что в пхп ты подключаешь файл и доволен, а в сях еще перекомпилировать приходится. Хотя последнее время с появлением инкрементальных компоновщиков, позволяющих догружать только что скомпилированный код в уже работающую программу и эта проблема может решаться на лету. Однако это таки из пушки по воробьям.
Совет такой - пересмотреть приложение с позиции проектирования. Поставить задачу - в данном случае видимо больше максимизация гибкости чем минимизация времени выполнения. Рассмотреть подходящие методы и идиомы. В данном случае я бы присмотрелся к идиоме прототипов, возможно это как раз то что нужно (как уже было сказано, раз не можем на уровне языка сделать новый класс - эмулируем). Правда ограничения и тут есть - сложность кода, невысокое быстродействие... Либо же писать свой интерпретатор, но при наличии пхп под рукой это имхо неразумно.

Автор: nickless 22.1.2007, 22:28
A12345,
Код
// Animal.h
class Animal
{
    public:
        Animal(string name, string value);
        Animal(string filename);

        void hello();

    private:
        string my_name;
        string my_value;
}

// Animal.cpp
Animal::Animal(string name, string value)
{
    my_name = name;
    my_value = value;
}

Animal::Animal(string filename)
{
    // тут парсим файл
    my_name = ...
    my_value = ...
}

Animal::hello()
{
    cout << "Hi, I'm " << my_name << "!!!" << endl;
    cout << "Adn here is my value: " << my_value << endl;
}


// main.cpp
int main()
{
    string names[3] = {"cat.ini", "dog.ini", "bird.ini"};

    Animal* animals[3];
    for (int i=0; i<3; i++)
    {
        animals[i] = new Animal(names[i]);
    }

    // тут делаем что-нибудь

    for (int i=0; i<3; i++)
    {
        animals[i]->hello();
    }
}

не это ли тебе нужно?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)