Модераторы: xvr

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> демон под BSD для вычислений 
V
    Опции темы
Larrikin
Дата 15.8.2007, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Здравстуйте, обитатели форума.

прошу помощи в реализации такой практически возникшей передо мной задачи:

Дано:
 - сервер FreeBSD
 - внешний скрипт через веб-интерфейс формирует данные  - длинный список из неизвестного заранее количества float порядка сотен и одно какое особое заданное число

Нужно:
 - вернуть номера позиций из них, которые ближе всего приближаются к заданному числу путем складывания, вычитания, умножения или деления любых из списка
 - делать это по возможности быстро

Предполагаю написать демон под FreeBSD, который будет отслеживать появление файлов с данными, загружать этот список чисел, запускать цикл тройной вложенности, запоминать комбинацию с минимальной погрешностью и сохранять эту комбинацию в файл

Вопросы такие, которые сам не могу придумать из-за того, что это моя первая задача на C:
- как лучше организовать эту очередь задач на расчет? предполагается, что веб-интерфейс будет формировать какую-то очередь fifo на расчет, а потом забирать результаты
- как сделать демон? пока собираюсь дописать функцию в код /usr/src/usr.sbin/daemon/daemon.c 
Код

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/usr.sbin/daemon/daemon.c,v 1.3.8.1 2006/01/15 17:50:36 delphij Exp $");

#include <sys/param.h>

#include <err.h>
#include <errno.h>
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void usage(void);
int
main(int argc, char *argv[])
{
        struct pidfh *pfh;
        int ch, nochdir, noclose, errcode;
        const char *pidfile;
        pid_t otherpid;

        nochdir = noclose = 1;
        pidfile = NULL;
        while ((ch = getopt(argc, argv, "-cfp:")) != -1) {
                switch (ch) {
                case 'c':
                        nochdir = 0;
                        break;
                case 'f':
                        noclose = 0;
                        break;
                case 'p':
                        pidfile = optarg;
                        break;
                default:
                        usage();
                }
        }
        argc -= optind;
        argv += optind;

        if (argc == 0)
                usage();
        /*
         * Try to open the pidfile before calling daemon(3),
         * to be able to report the error intelligently
         */
        if (pidfile) {
                pfh = pidfile_open(pidfile, 0600, &otherpid);
                if (pfh == NULL) {
                        if (errno == EEXIST) {
                                errx(3, "process already running, pid: %d",
                                    otherpid);
                        }
                        err(2, "pidfile ``%s''", pidfile);
                }
        }

        if (daemon(nochdir, noclose) == -1)
                err(1, NULL);

        /* Now that we are the child, write out the pid */
        if (pidfile)
                pidfile_write(pfh);

        execvp(argv[0], argv);

        /*
         * execvp() failed -- unlink pidfile if any, and
         * report the error
         */
        errcode = errno; /* Preserve errcode -- unlink may reset it */
        if (pidfile)
                pidfile_remove(pfh);

        /* The child is now running, so the exit status doesn't matter. */
        errc(1, errcode, "%s", argv[0]);
}

static void
usage(void)
{
        (void)fprintf(stderr,
            "usage: daemon [-cf] [-p pidfile] command arguments ...\n");
        exit(1);
}



стоит ли делать какие-нибудь разные потоки для вычисления каждого нового задания или считать одним по очереди? если сильно стоит, то я не поленюсь, научусь :)
сервер не жалко, лишь бы не падала система под нагрузкой

вот не пойму, как вообще организовать этот поток получения данных и отдачу?
нужно как-то идентифицировать один от другого - в отдельном файле? именем файла?
как там будет с блокировками? а то начнет читать, пока веб-морда в него пишет...
надо какой-то файл-флаг готовности или писать из веба данные во временный файл, а потом уже готовый переименовывать? каким путем идти?
думаю, надо будет юзать malloc для выделения нужного объема памяти после чтения очередной порции данных?
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 15.8.2007, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  15.8.2007,  17:59 Найти цитируемый пост)
- как сделать демон? пока собираюсь дописать функцию в код /usr/src/usr.sbin/daemon/daemon.c 

Код

int make_self_daemon() {
    pid_t pid = fork();
    if (pid > 0) 
        _exit(0);
    else if (pid < 0)
        return -1;
    setsid();
    close(STDOUT_FILENO);
    close(STDIN_FILENO);
    close(STDERR_FILENO);
    run(); /* основная функциональность демона */
}

Цитата(Larrikin @  15.8.2007,  17:59 Найти цитируемый пост)
- как лучше организовать эту очередь задач на расчет? предполагается, что веб-интерфейс будет формировать какую-то очередь fifo на расчет, а потом забирать результаты

как вариант, использовать какой-нибудь IPC
думаю, тут лучше всего подойдут именованные каналы
т. е создаем два именованных канала, в один из них веб-интерфейс пишет запрос, который обрабатывает демон, через второй он (веб-интерфейс) получает результат
запрос можно оформить в виде пакета: заголовок (количество чисел) и тело (сами числа)
аналогично с ответом
Цитата(Larrikin @  15.8.2007,  17:59 Найти цитируемый пост)
стоит ли делать какие-нибудь разные потоки для вычисления каждого нового задания или считать одним по очереди?

если критична скорость получения результата, возможно стоит обрабатывать каждый запрос в отдельном потоке
но тут тоже не все однозначно, надо больше информации, чтобы ответить на этот вопрос


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 15.8.2007, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



я тут надумал, что может логичнее брать данные напрямую из базы mysql, откуда их берет и готовит веб-морда
фактически, достаточно передавать только одну цифру ID набора данных для расчета, остальное можно получить прямо в коде С

то есть общий алгоритм, если не делать несколько потоков, примерно такая может быть:

при старте демона говорим ему параметры мускуля - сокет, базу, логин/пароль, таблицу
1. демоном читаем, если есть, файл dataset.id
2. берем из dataset.id целое id набора данных из таблицы
3. считаем и пишем в базу
4. повторить с цифры 1

так, наверное, будет проще и надежнее, чем с файлами париться?
на один файл проще права дать один раз, а паузой будет id равное 0, например

правда, я с мускулом пока не знаю насколько просто/сложно работать с мускулем из C smile

Цитата(MAKCim @  15.8.2007,  18:16 Найти цитируемый пост)
код C++
int make_self_daemon() {

что-то не пойму, это полностью самодостаточный код демона или функция отдельная?


Это сообщение отредактировал(а) Larrikin - 15.8.2007, 19:30
PM MAIL WWW ICQ   Вверх
bsa
Дата 15.8.2007, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Цитата(Larrikin @ 15.8.2007,  19:11)
Цитата(MAKCim @  15.8.2007,  18:16 Найти цитируемый пост)
код C++
int make_self_daemon() {

что-то не пойму, это полностью самодостаточный код демона или функция отдельная?

Считай, что это код функции main().
PM   Вверх
MAKCim
Дата 15.8.2007, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  15.8.2007,  19:11 Найти цитируемый пост)
1. демоном читаем, если есть, файл dataset.id
2. берем из dataset.id целое id набора данных из таблицы

зачем файл?
нужна будет синхронизация
тут лучше именованный канал, как я уже говорил


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 15.8.2007, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Цитата(MAKCim @  15.8.2007,  19:59 Найти цитируемый пост)
 лучше именованный канал

а где про это почитать? говорю же, я первый раз на С задачу решаю, есть только две бумажные книжки:
 - Программирование на языке С.Стефан Кочан
 - С++ Справочник.O'REILLY
PM MAIL WWW ICQ   Вверх
bsa
Дата 15.8.2007, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Цитата(Larrikin @ 15.8.2007,  20:06)
Цитата(MAKCim @  15.8.2007,  19:59 Найти цитируемый пост)
 лучше именованный канал

а где про это почитать?

man 3 mkfifo, man 2 pipe и man 2 socket

Это сообщение отредактировал(а) bsa - 15.8.2007, 20:24
PM   Вверх
MAKCim
Дата 15.8.2007, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Larrikin, 
ты С вообще знаешь хорошо?
если собрался писать под какую-то ОС (в твоем случае BSD), то одним С не обойдешься
нужно знание API
конкретно по вопросу
вот, имхо, лучшая книга
+ маны, маны и еще раз маны
man 3 mkfifo


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 15.8.2007, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Цитата(MAKCim @  15.8.2007,  20:16 Найти цитируемый пост)
ты С вообще знаешь хорошо?

когда-то пару прог на лабораторных написал в институте smile лет десять назад...

вот заказал в Озоне, вроде такая же http://www.ozon.ru/context/detail/id/2355792/

пару дней с вопросами не буду приставать -  пофтыкаю маны, подожду книжку...
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 20.8.2007, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



фтыкаю книжку Марка Дж. Рочкинда - похоже, лучше через сокеты делать?
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 20.8.2007, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  20.8.2007,  20:29 Найти цитируемый пост)
фтыкаю книжку Марка Дж. Рочкинда - похоже, лучше через сокеты делать? 

Unix domain sockets?
или обычные?

Это сообщение отредактировал(а) MAKCim - 20.8.2007, 21:07


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 20.8.2007, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



для начала попробую на unix, потом вроде несложно переделывать на сетевые

только у меня что-то не компилируется пример из книжки http://www.basepath.com/aup/ex/sktex_8c.html:

> gcc -DFREEBSD sktex.c
/var/tmp//ccyQH9U8.o(.text+0x59): In function `main':
: undefined reference to `ec_in_cleanup'


вроде все аккуратно добавил, что он хотел:

> ll
total 24
-rw-r--r--  1 larrikin  wheel  3278 Aug 20 20:14 defs.h
-rw-r--r--  1 larrikin  wheel  2228 Aug 20 20:14 ec.h
-rw-r--r--  1 larrikin  wheel   964 Aug 20 20:14 extio.h
-rw-r--r--  1 larrikin  wheel   210 Aug 20 20:14 logf.h
-rw-r--r--  1 larrikin  wheel   130 Aug 20 20:13 macrostr.h
-rw-r--r--  1 larrikin  wheel   255 Aug 20 20:13 options.h
-rw-r--r--  1 larrikin  wheel  2220 Aug 20 20:13 sktex.c
-rw-r--r--  1 larrikin  wheel  2077 Aug 20 20:13 suvreq.h
>

в книжке по С написано, что ищет в /usr/include - скопировал туда тоже, что вообще странно для BSD, скорее должно где-нить быть в /usr/local/include - тоже самое дает

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

Это сообщение отредактировал(а) Larrikin - 20.8.2007, 21:34
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 20.8.2007, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  20.8.2007,  21:30 Найти цитируемый пост)
щас пытаюсь надеюсь найти возможность при компиляции задавать путь для поиска заголовочных файлов...

Код

# gcc -I <где ищем>



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 20.8.2007, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



хм... дело, видимо, не в бобине...

gcc -DFREEBSD -I /usr/home/larrikin/files/examples.c/ sktex.c | less
/var/tmp//ccUZoeWV.o(.text+0x59): In function `main':
: undefined reference to `ec_in_cleanup'
/var/tmp//ccUZoeWV.o(.text+0xb7): In function `main':
: undefined reference to `ec_push'
/var/tmp//ccUZoeWV.o(.text+0xf7): In function `main':
: undefined reference to `ec_in_cleanup'
/var/tmp//ccUZoeWV.o(.text+0x13b): In function `main':
: undefined reference to `ec_push'
/var/tmp//ccUZoeWV.o(.text+0x149): In function `main':
: undefined reference to `ec_in_cleanup'
/var/tmp//ccUZoeWV.o(.text+0x1a7): In function `main':
: undefined reference to `ec_push'


придется еще пару дней вкуривать в азы компиляции, блин столько времени убивается на эти все отвлекающие от сути задачи нюансы языка и реализаций...
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 20.8.2007, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Larrikin, 
смотри
если есть исходник
Код

#include <include/lib.h>
#include <headers/groups.h>
#include <assembler.h>
...

он расположен, допустим, в sources
в директории, где находится директория sources, находится директория, допустим, inc, которая содержит
include/lib.h, headers/groups.h и assembler.h
тогда, находясь в ./sources, компилировать исходник нужно так
Код

# gcc -I ../inc -c <исходник>



--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 2.9.2007, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Соображение такое - сделать программу по модели grep, то есть брать текстовые данные со стандартного входа или файла и отдавать на стандартный выход или файл...

данные - несколько (вряд ли тысячи, скорее десятки, может сотни) строк. Каждая несет один набор, состоящий из чисел, разделенных двоеточием:
целое число со знаком (id)
дробное число со знаком (value)

на выходе в том же формате строки:
целое число со знаком(id1)
целое число со знаком(id2)
символьная строка(action)


Какой пример реализации по такой модели самый удачный и несложный?
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 2.9.2007, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  2.9.2007,  13:56 Найти цитируемый пост)
Какой пример реализации по такой модели самый удачный и несложный? 

так тут вообще нет ничего сложного
Код

int main() {
    ssize_t count;
    int size, position = 0;
    char buffer[SIZE];
    while ((count = read(STDIN_FILENO, buffer + position, SIZE - position))) {
        if (count < 0) return errno;
        /* работаем с данными */
        do {
            if (write(STDOUT_FILENO, buffer + position, size) < 0) { /* size может быть != count */
                if (errno == EINTR) continue;
                else return errno;
            }
            break;
        } while (1);
    }
    return 0;
}


Это сообщение отредактировал(а) MAKCim - 2.9.2007, 15:00


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
JackYF
Дата 2.9.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 3
Всего: 162



Цитата(Larrikin @  2.9.2007,  13:56 Найти цитируемый пост)
данные - несколько (вряд ли тысячи, скорее десятки, может сотни) строк. Каждая несет один набор, состоящий из чисел, разделенных двоеточием:
целое число со знаком (id)
дробное число со знаком (value)

на выходе в том же формате строки:
целое число со знаком(id1)
целое число со знаком(id2)
символьная строка(action)

имхо, можно обойтись и без демона... awk, perl неплохо подойдут для такой задачи. Правда, не понял логику преобразования...


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Larrikin
Дата 2.9.2007, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



про демона речи уже и нету, по крайнем мере пока не доказана недостаточность функциональности простого "фильтра"
реализация на интерпретируемом языке скриптов уже есть - падает после полтора-двух десятков входных строк из-за переполнения свопа.

пример какой-то куцый - на простое чтение и запись, а перед работой с данными нужно проделать дофига всякой работы ведь


взять кусок строки от начала до первого двоеточия, выбрать из него ноль или один знаков минус с последующими не менее одной цифры и только цифры
запомнить это число как id
убедиться, что такого id до сих пор не было в этом наборе данных
если что не так - ругнуться в stderr и попробовать выдрать данные из следующей строки

взять кусок строки от первого двоеточия до второго
попробовать преобразовать его в число в обычной нотации или в научной или шестнадцатиричной и т.д.
запомнить это число как value
если никак не получилось  - ругнуться в stderr и попробовать выдрать данные из следующей строки

добавить набор из id, value в массив данных для дальнейшей работы

обработать следующую строку


PM MAIL WWW ICQ   Вверх
MAKCim
Дата 2.9.2007, 17:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Larrikin @  2.9.2007,  16:55 Найти цитируемый пост)
пример какой-то куцый - на простое чтение и запись, а перед работой с данными нужно проделать дофига всякой работы ведь

ну так проделай эту работу
ты ж сам алгоритм написал
 smile 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 2.9.2007, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



изобрести колесо?
боюсь, квадратное получится...
наверняка уже полно отлаженных есть реализаций - работают же утилиты с файлов /etc/master.password как раз похожий набор строк...

какие реализации считаются самыми удачными/проверенными?
PM MAIL WWW ICQ   Вверх
bsa
Дата 3.9.2007, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Larrikin, смотри в сторону strtok(). Она позволяет разбивать строку разделенную чем-то на подстроки.
PM   Вверх
Larrikin
Дата 10.9.2007, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Парни, помогите... не могу найти время на то, чтобы разобраться самому, как реализовать этот простой алгоритм на C.

Если кто может написать эти несколько строк кода интерфейса, чтобы можно было вставить обработку свою по аналогии примера MAKCim - заплачу 70 WMZ с протекцией

примерное ТЗ в этой теме, если надо подробнее - расскажу в ICQ 129916863
PM MAIL WWW ICQ   Вверх
bsa
Дата 10.9.2007, 17:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Попробуй такой код:
Код
while( !feof(stdin) ) {
      int id;
      double value;
      int x = scanf("%i:%f", &id, &value);
      if (x == 2) {
            int id1, id2;
             //here need some processing code
            printf("%i:%i:%f\n", id1, id2, value);
      } else {
             fprintf(stderr, "invalid format\n");
      }
}

PM   Вверх
Larrikin
Дата 10.9.2007, 19:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Цитата(bsa @  10.9.2007,  17:56 Найти цитируемый пост)

      int id;
      double value;
      int x = scanf("%i:%f", &id, &value);

выглядит красиво, а насколько он устойчив к входным данным и всегда ли сможет принять, например, такие?

-1: (подразумевается пара -1 и 0)
- 1: 0 (подразумевается пара -1 и 0)
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111:1 (корректно игнорить строку)
12: - 0.12123123 (пробелы после двоеточия, знака и перед переводом строки, подразумевается 12 и -0.12123123 )

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

Это сообщение отредактировал(а) Larrikin - 10.9.2007, 19:20
PM MAIL WWW ICQ   Вверх
bsa
Дата 10.9.2007, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Ты возьми и попробуй. Если тебе нужен исполнитель - в другой раздел.
PM   Вверх
Larrikin
Дата 11.9.2007, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



вот что получилось и даже компилируется gcc ncalc.c -o ncalc:
Код

#include <stdio.h>

// Сколько строк данных мы готовы переварить
// TODO: сделать опцией командной строки
#define MAX_DATALINE 100

int main (void){

// counter
        int i;

// теоретически приходящие данные должны содержать целое и дробное число
        struct dataline{
                long int id;
                long double value;
        };

// в этот массив будем сохранять приходящие данные для обработки
        struct dataline n[MAX_DATALINE + 1];

// в позиции 0 массива будет храниться номер последнего заюзанного элемента
// он же количество строк данных в массиве
        n[0].id = 0;

// часть дальнейшего кода дал bsa, я не очень уверен, что понимаю его смысл

// по логике тут из входящего потока должны извлекаться данные в массив
// TODO: данные в каждой строке потока разделяются пока только двоеточием

        while(!feof(stdin) || n[0].id < MAX_DATALINE){
                long int id;
                long double value;
                int x = scanf("%li:%lf", &id, &value);
                if (x == 2){
                        ++n[0].id;
                        n[n[0].id].id = id;
                        n[n[0].id].value = value;

//bsa                   int id1, id2;
//bsa here need some processing code
//bsa                   printf("%i:%i:%f\n", id1, id2, value);
                }else{
                        fprintf(stderr, "invalid format\n");
                }
        }

//processing here wirh arraj n

// output
        for ( i = 1; i <= n[0].id; ++i){
                printf("%li:%lf\n", n[i].id, n[i].value);
        }

        return 0;
}



сделал такой файлик data
> cat data
-1:20
0:0
1:21

выполняю
./ncalc < data

получаю в консоле бесконечный цикл:

invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
invalid format
^C
>

непонятно...
похоже, не отрабатывает !feof(stdin), но что это и как должно отрабатываться я в своих книжках не нашел, в инете только готовые примеры использования, на вид такие же...
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 11.9.2007, 02:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



еще одна странность - если поставить #define MAX_DATALINE 2, то на тех же данных вывод получается такой:

> ./ncalc < data
invalid format
-1:20.000000
0:0.000000
1:21.000000
>

очень непонятно, почему три строки обработал, а не две...
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 11.9.2007, 02:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



ну конечно, условие неверное, вот так работает ожидаемо:

Код

   while(!feof(stdin) && n[0].id < MAX_DATALINE){

PM MAIL WWW ICQ   Вверх
Larrikin
Дата 12.9.2007, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



не могу найти инфу, может ли функция возвращать массив?
или, например, указатель на масссив?

просто код разрастается, получается мусора много, хочу сделать чтение потока в массив данных отдельной функцией, но не знаю как...

PM MAIL WWW ICQ   Вверх
bsa
Дата 12.9.2007, 15:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Цитата(Larrikin @ 12.9.2007,  14:00)
не могу найти инфу, может ли функция возвращать массив?
или, например, указатель на масссив?

Код
int* process(const char *txt)
{
....
      int * array = (int*)malloc(sizeof(int)*size);
....
      return array;
}

Если писать на с++, то там никаких проблем нет, если возвращать std::vector
PM   Вверх
Larrikin
Дата 21.9.2007, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



разбил этот код на файлы getdata.c main.c потом, видимо,  будет ncalc.c и output.c

думаю, еще нужен будет заголовок типа ncalc.h для того, чтобы определния типа #define MAX_DATALINE 100 не надо было править во всех файлах...

подскажите в Сети толковое руководство по созданию Makefile для BSD, а то везде только перевод "Мини-руководство по созданию Makefile-ов" который обещает научить в начале, но не делает этого...

че-то не работает сборка по примерам из этого мини-руководства, а других нету на русском или не там ищу...

да хоть бы и не на русском, только чтобы внятнее мана было

о BSD много доки про makefile для портирования, а как мне простую сборку сделать-то?

Это сообщение отредактировал(а) Larrikin - 21.9.2007, 13:24
PM MAIL WWW ICQ   Вверх
bsa
Дата 21.9.2007, 18:53 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Larrikin, попробуй воспользоваться Automake...

На самом деле формат Makefile достаточно прост (если не делать всяких условных сборок):
Код
<Цель>: <зависимость1> <зависимость2>...
    command1
    command2
    ....
    commandN
Обрати внимание, что перед commandX должна стоять табуляция (не пробелы) - это важно.
Например, у тебя есть 3 файла file1.c, file2.c и file3.c, их надо скомпилировать в myprog:
Код
all: myprog
myprog: file1.o file2.o file3.o
    gcc -o $@ $^
file1.o: file1.c
    gcc -c -o $@ $<
file2.o: file2.c
    gcc -c -o $@ $<
file3.o: file3.c
    gcc -c -o $@ $<
$@ - это название цели, $^ - все зависимости, $< - первая зависимость
PM   Вверх
Larrikin
Дата 21.9.2007, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



вот вроде нашел интересную статью http://palm.opennet.ru/base/dev/auto_makefile.txt.html
но не получается заставить собирать мои жалкие несколько файлов...

что не так в таком скрипте?
Код


#!/usr/bin/make -f
SOURCES := $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
PROJNAME = $(notdir $(PWD))
BINARY= $(PROJNAME)

all: $(PROJNAME)

$(BINARY): $(OBJECTS)
    $(CC) $(LDFLAGS) -o $@ $(OBJECTS)

# а здеся мы генерим зависимости от заголовков
#include $(SOURCES:.c=.d)
#%.d: %.c
#    gcc -MM -MG $< \
#    | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
#    [ -s $@ ] || rm -f $@

clean:
    rm -f *.d *.o

.PHONY: clean

PM MAIL WWW ICQ   Вверх
JackYF
Дата 22.9.2007, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 3
Всего: 162



Цитата(Larrikin @  21.9.2007,  22:57 Найти цитируемый пост)
но не получается заставить собирать мои жалкие несколько файлов...

телепатов нееетт.... логи с ошибками приводи

Приведи имена всех файлов проекта. Возможно, тебе поможет замена

Цитата(Larrikin @  21.9.2007,  22:57 Найти цитируемый пост)
SOURCES := $(wildcard *.c)

на
Цитата

SOURCES := $(wildcard *.cpp)

если у тебя .cpp - файлы.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Larrikin
Дата 22.9.2007, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



Код

> pwd
/usr/home/larrikin/files/ncalc
> ll
total 14
-rw-r--r--  1 larrikin  wheel   118 Sep 21 23:31 Makefile
-rwxr-xr-x  1 larrikin  wheel   515 Sep 22 10:58 compile.sh
-rw-r--r--  1 larrikin  wheel    20 Sep 11 22:09 data
-rw-r--r--  1 larrikin  wheel  1721 Sep 21 22:39 getdata.c
-rw-r--r--  1 larrikin  wheel  2271 Sep 21 22:39 main.c
-rw-r--r--  1 larrikin  wheel   111 Sep 21 22:37 ncalc.h
> cat compile.sh
#!/usr/bin/make -f
SOURCES := $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
PROJNAME = $(notdir $(PWD))
BINARY= $(PROJNAME)
$(BINARY): $(OBJECTS)
        $(CC) $(LDFLAGS) -o $@ $(OBJECTS)

# а здеся мы генерим зависимости от заголовков
include $(SOURCES:.c=.d)

%.d: %.c
        gcc -MM -MG $< \
        | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
        [ -s $@ ] || rm -f $@
clean:
        rm -f *.d *.o

.PHONY: clean> ./compile.sh
"./compile.sh", line 10: Missing dependency operator
make: fatal errors encountered -- cannot continue
>



Это сообщение отредактировал(а) Larrikin - 22.9.2007, 10:51
PM MAIL WWW ICQ   Вверх
JackYF
Дата 22.9.2007, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 3
Всего: 162



Попробуй вручную создать пустые файлы getdata.d, main.d или вместо


Цитата(Larrikin @  22.9.2007,  10:51 Найти цитируемый пост)
include $(SOURCES:.c=.d)

сделать
Цитата

-include $(SOURCES:.c=.d)



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Larrikin
Дата 22.9.2007, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



оба способа не меняют ошибку в любой комбинации...

напоминаю

> uname -rs
FreeBSD 6.2-STABLE

PM MAIL WWW ICQ   Вверх
JackYF
Дата 22.9.2007, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 3
Всего: 162



Гм. Попробуй переименовать файл Makefile в что-нибудь другое.
Честно говоря, не понимаю ошибки.

Попробуй, если и это не пойдет, создать файл с названием Makefile и туда скопировать всё содержимое без первой строчки файла compile.sh, после чего вызвать
Цитата

make



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Larrikin
Дата 22.9.2007, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



нашел в магазине книжку "В.П.Солдатов. Make. Build. Autotools. Управление программными проектами"
пофтыкаю, авось разберусь, раз это такой гимор...
PM MAIL WWW ICQ   Вверх
JackYF
Дата 22.9.2007, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 3
Всего: 162



Цитата(Larrikin @  22.9.2007,  19:56 Найти цитируемый пост)
пофтыкаю, авось разберусь, раз это такой гимор... 

не знаю. Простые make-файлы у меня заработали с пол-пинка... хотя читать там, действительно, есть о чём smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Larrikin
Дата 27.9.2007, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



вот так вроде работает:

Код

#!/usr/local/bin/gmake -f
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)
PROJNAME = $(notdir $(PWD))
BINARY = $(PROJNAME)
CC = gcc

$(BINARY): $(OBJECTS)
        $(CC) $(LDFLAGS) -o $@ $(OBJECTS)

$(OBJECTS): $(SOURCES) $(HEADERS)
        $(CC) -c $(SOURCES) -I $(PWD)

clean:
        rm -f *.d *.o

.PHONY: clean


PM MAIL WWW ICQ   Вверх
Larrikin
Дата 27.9.2007, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



как такое может быть? я просто в шоке...

Код

        for ( i = 1; i <= n[0].id; ++i){
            printf("%i %li:%lf\n", i, n[i].id, n[i].value);
        }
// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            fprintf(stderr, "first best: id %li value %ld\n", n[1].id, n[1].value);
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '+';
            best.result = n[1].value + n[1].value;
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }


выдает:
1 -1:5.000000
2 1:10.000000
3 2:25.000000
first best: id -1 value 0


ПОЧЕМУ НОЛЬ????
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 28.9.2007, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



а блин, просто формат вывода напутал %lf %ld
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 28.9.2007, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



а вот этого я реально не постигаю... сейчас такой ncalc.h

Код

#include <stdio.h>
#include <stdbool.h>
#include <tgmath.h>

// Сколько строк данных мы готовы переварить
// TODO: сделать опцией командной строки
#define MAX_DATALINE 100

// приходящие данные должны содержать целое и дробное число
struct dataline{
    long int id;
    long double value;
};

// общий массив для данных
struct dataline n[MAX_DATALINE + 1];

// в такой форме будем искать результат
struct new{
    long int id1;
    long int id2;
    char act;
    long double result;
    long double err;
    bool is_null;
};

// общая для лучшего предложения
struct new best;


в отдельном файле best_plus.c

Код

// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '+';
            printf("id(1) value(%lf)\n",n[1].value);
            best.result = (n[1].value + n[1].value);
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }
        printf("best: id1(%li) id2(%li) act(%c) result(%lf) err(%lf)\n",
            best.id1, best.id2, best.act, best.result, best.err);


Код

> cat data/nice
-1:5
-1:21
0:100
0:51
1:10
2:25
2 :15


выполняю ./lmake && ./ncalc < data/nice
 получаю фигню

id(1) value(5.000000)
best: id1(-1) id2(-1) act(+) result(-2.000000) err(0.000000)

каким образом пять плюс пять получается минус два и как с этим бороться? мыслей вообще никаких...
 smile 

Это сообщение отредактировал(а) Larrikin - 28.9.2007, 10:02
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 28.9.2007, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



с этим разобрались smile http://forum.vingrad.ru/forum/topic-174485.html
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 28.9.2007, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



а, в общем-то, всё готово похоже smile
Код

> pwd
/usr/home/larrikin/files/ncalc
> ll
total 20
-rw-r--r--  1 larrikin  wheel  1121 Sep 28 16:13 best_divide.c
-rw-r--r--  1 larrikin  wheel  1095 Sep 28 16:07 best_minus.c
-rw-r--r--  1 larrikin  wheel  1001 Sep 28 15:23 best_multiply.c
-rw-r--r--  1 larrikin  wheel   993 Sep 28 15:03 best_plus.c
drwxr-xr-x  2 larrikin  wheel   512 Sep 27 21:56 data
-rw-r--r--  1 larrikin  wheel  2140 Sep 28 16:17 getdata.c
-rwxr-xr-x  1 larrikin  wheel   356 Sep 28 13:34 lmake
-rw-r--r--  1 larrikin  wheel  1155 Sep 28 16:23 main.c
-rw-r--r--  1 larrikin  wheel   563 Sep 28 16:31 ncalc.h

best_divide.c
Код

#include <ncalc.h>

////////////////////////////////////////////////////////////////////////
// checking /
////////////////////////////////////////////////////////////////////////

void divide(void){

// counters
    int i,j;
// Проверим факт наличия хоть каких-нибудь данных
    if ( n[0].id > 0){

// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '-';
            best.result = (n[1].value - n[1].value);
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }
        for ( i = 1; i <= n[0].id; ++i){
            for (j = 1; j <= n[0].id; ++j){
                if(
                    !n[j].value == 0 &&
                    fabs( n[0].value - ( n[i].value / n[j].value) )
                    < best.err
                ){
                    best.id1 = n[i].id;
                    best.id2 = n[j].id;
                    best.act = '/';
                    best.result = n[i].value / n[j].value;
                    best.err = fabs( n[0].value - best.result );
                    best.is_null = false;
//                    fprintf(stderr, "%Lf - %Lf = %Lf err %Lf\n", n[i].value, n[j].value, best.result, best.err);
                }
            }
        }

    }else{
        fprintf(stderr, "error: minus: i need data to calculating!");
    }

}

best_minus.c
Код

#include <ncalc.h>

////////////////////////////////////////////////////////////////////////
// checking -
////////////////////////////////////////////////////////////////////////

void minus(void){

// counters
    int i,j;
// Проверим факт наличия хоть каких-нибудь данных
    if ( n[0].id > 0){

// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '-';
            best.result = (n[1].value - n[1].value);
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }
        for ( i = 1; i <= n[0].id; ++i){
            for (j = 1; j <= n[0].id; ++j){
                if(
                    fabs( n[0].value - ( n[i].value - n[j].value) )
                    < best.err
                ){
                    best.id1 = n[i].id;
                    best.id2 = n[j].id;
                    best.act = '-';
                    best.result = n[i].value - n[j].value;
                    best.err = fabs( n[0].value - best.result );
                    best.is_null = false;
//                    fprintf(stderr, "%Lf - %Lf = %Lf err %Lf\n", n[i].value, n[j].value, best.result, best.err);
                }
            }
        }

    }else{
        fprintf(stderr, "error: minus: i need data to calculating!");
    }

}

best_multiply.c
Код

#include <ncalc.h>

////////////////////////////////////////////////////////////////////////
// checking *
////////////////////////////////////////////////////////////////////////

void multiply(void){

// counters
    int i,j;
// Проверим факт наличия хоть каких-нибудь данных
    if ( n[0].id > 0){

// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '*';
            best.result = (n[1].value * n[1].value);
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }
        for ( i = 1; i <= n[0].id; ++i){
            for (j = i; j <= n[0].id; ++j){
                if(
                    fabs( n[0].value - ( n[i].value * n[j].value) )
                    < best.err
                ){
                    best.id1 = n[i].id;
                    best.id2 = n[j].id;
                    best.act = '*';
                    best.result = n[i].value * n[j].value;
                    best.err = fabs( n[0].value - best.result );
                    best.is_null = false;
                }
            }
        }

    }else{
        fprintf(stderr, "error: multiply: i need data to calculating!");
    }

}

best_plus.c
Код

#include <ncalc.h>

////////////////////////////////////////////////////////////////////////
// checking +
////////////////////////////////////////////////////////////////////////

void plus(void){

// counters
    int i,j;
// Проверим факт наличия хоть каких-нибудь данных
    if ( n[0].id > 0){

// Гарантируем возврат хоть какого-нибудь результата
        if ( best.is_null ){
            best.id1 = n[1].id;
            best.id2 = n[1].id;
            best.act = '+';
            best.result = (n[1].value + n[1].value);
            best.err = fabs( n[0].value - best.result );
            best.is_null = false;
        }
        for ( i = 1; i <= n[0].id; ++i){
            for (j = i; j <= n[0].id; ++j){
                if(
                    fabs( n[0].value - ( n[i].value + n[j].value) )
                    < best.err
                ){
                    best.id1 = n[i].id;
                    best.id2 = n[j].id;
                    best.act = '+';
                    best.result = n[i].value + n[j].value;
                    best.err = fabs( n[0].value - best.result );
                    best.is_null = false;
                }
            }
        }

    }else{
        fprintf(stderr, "error: plus: i need data to calculating!");
    }

}

getdata.c
Код

#include <ncalc.h>

int getdata(void){


// в позиции 0 массива данных будет храниться
// id - номер последнего заюзанного элемента, он же количество строк данных в массиве
// value - цель

    n[0].id = 0;

// Для проверки дубликатов id нужны две переменные:
// чтобы можно было сделать continue
    bool have_duplicate = false;

// счетчик количества поступающих данных, надеюсь простого int хватит
    int i;

// здесь будем отслеживать факт прихода конечной цели всего набора данных
    bool have_target = false;

// сами данные
    long int id;
    long double value;

// номер строки входящих данных
    
    int line = 0;

// результат работы метода - число полученных строк или -1 при ошибке

    int result = -1;


////////////////////////////////////////////////////////////////////////
// конец определений, начало вычислений
////////////////////////////////////////////////////////////////////////

    
// по логике тут из входящего потока должны извлекаться данные в массив

    while(!feof(stdin) && n[0].id < MAX_DATALINE && line < MAX_DATALINE){

// TODO: данные в каждой строке потока разделяются пока только двоеточием
        int x = scanf("%Li:%Lf", &id, &value);
//        fflush(stdin);
        ++line;        
        if (x == 2){
            for ( i = 1; i<= n[0].id; ++i){
                if ( n[i].id == id){have_duplicate = true;}
            }
            if (have_duplicate){
//                fprintf(stderr, "data string %i ignored: duplicate id %Li\n", line, id);
                have_duplicate = false;
                continue;
            }
// в строке с id 0 value должно быть таргетом всех вычислений
            if ( id == 0){
                if ( !have_target){
                    n[0].value = value;
                    have_target = true;
                }else{
//                    fprintf(stderr, "data %Lf  with id 0 ignored: target value already %Lf\n", value, n[0].value );
                }
            }else{
                n[0].id                = n[0].id + 1;
                n[n[0].id].id        = id;
                n[n[0].id].value    = value;
            }
        }else{
//            fprintf(stderr, "data string %i ignored: invalid format\n", line);
            continue;
        }
    }

    if ( n[0].id == 0){
//        fprintf(stderr, "data ignored: no valid strings\n");
        return(0);
    }else{
        if (!have_target){
//            fprintf(stderr, "data ignored: no valid strings\n");
            return(-1);
        }else{
            return(n[0].id);
        }
    }
}

main.c
Код

#include <ncalc.h>

int main (void){

// counter
    int i;


////////////////////////////////////////////////////////////////////////
// конец определений, начало вычислений
////////////////////////////////////////////////////////////////////////

    if( getdata() > 0){
//        printf("We have %Li dataline, Yo!\n", n[0].id);
//        for ( i = 1; i <= n[0].id; ++i){
//            printf("%Li:%Lf\n", n[i].id, n[i].value);
//        }
//        printf("target %Lf\n", n[0].value);


////////////////////////////////////////////////////////////////////////
//processing here with arraj n
////////////////////////////////////////////////////////////////////////

        best.is_null = true;
        plus();
        minus();
        multiply();
        divide();

////////////////////////////////////////////////////////////////////////
// output
////////////////////////////////////////////////////////////////////////
        printf("get:%Li:target:%Lf:best:%Li:%c:%Li:%Lf:err:%Lf\n",
            n[0].id, n[0].value, best.id1, best.act, best.id2, best.result, best.err);
        return 0;
    }else{
//TODO: придумать вывод help message
        printf("need data like this:\n");
        printf("0:0.4\n");
        printf("1:2.901\n");
        printf("-1:4.1\n");
    }
}

ncalc.h
Код

#include <stdio.h>
#include <stdbool.h>
#include <tgmath.h>

// Сколько строк данных мы готовы переварить
// TODO: сделать опцией командной строки
#define MAX_DATALINE 1000

// приходящие данные должны содержать целое и дробное число
struct dataline{
    long int id;
    long double value;
};

// общий массив для данных
struct dataline n[MAX_DATALINE + 1];

// в такой форме будем искать результат
struct willnew{
    long int id1;
    long int id2;
    char act;
    long double result;
    long double err;
    bool is_null;
};

// общая для лучшего предложения
struct willnew best;

data/bad
Код

-1:5
-1:21
0:2.45
1:10
2:25
2 :15
0:q51w1


./ncalc < data/bad

get:3:target:2.450000:best:2:/:1:2.500000:err:0.050000


можно передохнуть и начинать рефакторинг smile

Это сообщение отредактировал(а) Larrikin - 28.9.2007, 16:30
PM MAIL WWW ICQ   Вверх
Larrikin
Дата 7.10.2007, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



поработал фильтр и стало нужно всё-таки делать демон, чтобы работало независимо...

оцените, в ту ли сторону я пошел?

> ll
total 8
-rw-r--r--  1 larrikin  wheel   62 Oct  7 15:12 common.h
-rw-r--r--  1 larrikin  wheel   84 Oct  7 16:02 daemon.c
-rwxr-xr-x  1 larrikin  wheel  345 Oct  7 15:22 lmake
-rw-r--r--  1 larrikin  wheel  571 Oct  7 16:02 main.c
>


common.h
Код

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


main.c
Код

#include <common.h>

int main(void){
        pid_t pid;
        switch (pid = fork())
        {
                case -1:
                        /* Here pid is -1, the fork failed */
                        /* Some possible reasons are that you're */
                        /* out of process slots or virtual memory */
                        perror("The fork failed!");
                        break;

                case 0:
                        /* pid of zero is the child */
                        /* Here we're the child...what should we do? */
                        ncalcd();
                        /* but after doing it, we should do something like: */
                        return(0);

                default:
                        /* pid greater than zero is parent getting the child's pid */
                        printf("Child's pid is %d\n",pid);
                }
        }



daemon.c
Код

#include <common.h>
int ncalcd(void){
        printf("Hello, world!\n");
        return(0);
        1;
}



собственно, функциональность собираюсь писать в daemon.c

пока выдает:

> ./ncalcd
Child's pid is 93393
Hello, world!
>

PM MAIL WWW ICQ   Вверх
MAKCim
Дата 7.10.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Larrikin, 
я же писал в этой теме как сделать демона
тут


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Larrikin
Дата 7.10.2007, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 15.8.2007

Репутация: нет
Всего: нет



так я так и делаю, только че-то меня пугает огромное количество информации про сигналы без готового примера "как делать правильно" для моего случая, а ведь сигналы мне слушать все равно надо, хотя бы для корректного выхода...

main.c
Код

#include <common.h>

int main(void){
        pid_t pid  = fork();
        switch (pid)
        {
                case -1:
                        /* Here pid is -1, the fork failed */
                        /* Some possible reasons are that you're */
                        /* out of process slots or virtual memory */
                        perror("The fork failed!");
                        break;

                case 0:
                        /* pid of zero is the child */
                        /* Here we're the child...what should we do? */
                        close(STDOUT_FILENO);
                        close(STDIN_FILENO);
                        close(STDERR_FILENO);
                        ncalcd();
                        /* but after doing it, we should do something like: */
                        _exit(0);

                default:
                        /* pid greater than zero is parent getting the child's pid */
                        printf("ncalcd have pid %d\n",pid);
        }
}


PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.1459 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.