1

Тема: Таймер для Ubuntu на С

Доброго дня!
Я розпочав писати таймер для ОС Ubuntu (використовую її).
Функції такого таймера в майбутньому будуть такими:
1) запуск з ОС
2) робота у фоні
3) через N проміжок часу виводиться потрібне повідомлення.
Про графічний інтерфейс ще не кажу, тому що ще мову С погано знаю.
Поки що написав лише сам таймер з інтерфейсом користувача у терміналі. Пишу в різних файлах.
Проблема з'явилась ось в чому:
після запуску таймера процесор навантажується на 50 %, хоча перед цим навантаження на процесорі (при відкритому VIM, Google Chrome та плеєром) було близько 5 - 10 %

main.c - керує програмою

#include "prototypes.h"

/* prototypes.h - містить прототипи функцій та константи
 * variant_of_timer - варіанти роботи таймера
 *      вибір кількості повторювань таймера
 *      вибір часу роботи таймера
 * якщо була вибрана (введена власноруч або вибраний варінт) 
 * кількість повторювань таймера відмінна від ALWAYS то виконується 
 * цикл while (numbres_of_timer--)
 * в іншому випадку таймер повторюється постійно
 * timer - виклик таймера
 */
int main (void){
    int numbers_of_timer = 0;
    float time_target_seconds = 0;
    variant_of_timer (&numbers_of_timer, &time_target_seconds);
    
    if (numbers_of_timer > 0)
        while (numbers_of_timer--)
            timer (time_target_seconds);
    else while (1)
        timer (time_target_seconds);

    return 0;
}

prototypes.h - знаходяться константи та прототипи функцій

#define FIVE 5
#define TEN 10
#define TWENTY 20
#define ALWAYS 0
#define ONE_HOUR 3600
#define TWO_HOUR 7200
#define STARS "\n*********************"

void variant_of_timer (int * number_of_timer, float * time_target);
int number_times_of_timer (void);
float enter_time_seconds (void);
void timer (float time_target_seconds);

/* FIVE, TEN, TWENTY, ALWAYS - кількість повторювань таймера
 * ONE_HOUR, TWO_HOUR - одна і дві години (у секундах) відповідно 
 * STARS - зірочки, для інтерфейсу
 * variant_of_timer - вибір кількості повторювань та часу роботи таймеру
 * number_times_of_timer - введення кількості повторювань таймеру
 * enter_time_seconds - введення часу роботи таймера у секундах
 * timer - таймер
 */ 

variant_of_timer.c - вибір режиму роботи таймера

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "prototypes.h"

/* вибір режиму роботи таймеру */
void variant_of_timer (int * p_number_timer, float * p_time_target){
    char var;
    bool todo = true;
    puts (STARS);
    printf (" Timer has variants!");
    puts (STARS);
    printf ("You can choose how many times the timer runs:\n");
    while (todo){
        printf ("1 - 5 times.\n");
        printf ("2 - 10 times.\n");
        printf ("3 - 20 times.\n");
        printf ("4 - timer runs always.\n");
        printf ("5 - enter times.\n");
        printf ("Enter q to exit.\n");
        scanf ("%c", &var);
        switch (var){
            case '1':
                *p_number_timer = FIVE;
                todo = false;
                break;
            case '2':
                *p_number_timer = TEN;
                todo = false;
                break;
            case '3':
                *p_number_timer = TWENTY;
                todo = false;
                break;
            case '4':
                *p_number_timer = ALWAYS;
                todo = false;
                break;
            case '5':
                *p_number_timer = number_times_of_timer ();
                todo = false;
                break;
            case 'q':
                exit(1);
                break;
            default:
                printf ("Please, choose variant or enter q to exit!\n");
                break;
        }
    }
    while (getchar() != '\n')
        ;
    todo = true;
    system ("clear");
    if (*p_number_timer != ALWAYS)
        printf ("\n\nTimer will be runs %d times!\n\n", *p_number_timer);
    else printf ("\n\nTimer will be runs always!\n\n");
    printf ("You can choose how much time timer work:\n");
    while (todo){
        printf ("1 - 1 hour.\n");
        printf ("2 - 2 hour.\n");
        printf ("3 - enter time timer work.\n");
        printf ("Enter q to exit.\n");
        scanf ("%c", &var);
        switch (var){
            case '1':
                *p_time_target = ONE_HOUR;
                todo = false;
                break;
            case '2':
                *p_time_target = TWO_HOUR;
                todo = false;
                break;
            case '3':
                *p_time_target = enter_time_seconds ();
                todo = false;
                break;
            case 'q':
                exit (1);
            default:
                printf ("Please, choose variant or enter q to exit!\n");
                break;
        }
    }
}

enter_numbers.c - введення кількості повторювань та часу роботи таймера

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

/* введення кількості повторювань таймера */
int number_times_of_timer (void){
    char ch;
    int times_of_timer = 0;  
    printf ("How much times do you want to run timer?\n");
    printf ("Enter times (or enter q to exit): ");
    while ((scanf ("%d", &times_of_timer)) != true || times_of_timer < 0){
        if (times_of_timer < 0){
            printf ("Please, enter times (only positive numbers): "); 
            times_of_timer = 0;
        }else if ((ch = getchar ()) != 'q'){
            if (ch != 'a'){
                while ((ch = getchar ()) != '\n')
                    ;
                printf ("Please, enter times (only numbers) or enter q to exit: "); 
            }else{
                times_of_timer = -1;
                break;
            }
        }else exit (1);
    }

    return times_of_timer;
}

/* введення часу роботи таймеру у секундах */ 
float enter_time_seconds (void){
    char ch;
    float time_sec;
    printf ("Enter time (seconds) for end of timer (enter q to exit): ");
    while ((scanf ("%f", &time_sec)) != true){
        if ((ch = getchar ()) == 'q')
            exit (2);
        else while ((ch = getchar ()) != '\n')
            ;
        printf ("This symbols are not numbers! Please enter number or enter q to exit: ");
    }
    return time_sec;
}

timer.c -  таймер

/* timer.c - описується робота самого таймеру */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "prototypes.h"

/* timer - сам таймер  */ 
void timer (float time_target_seconds){
    int time_start_processor, time_end_processor; 
    float time_result_seconds = 0;
    time_start_processor = clock ();
    do{
        time_end_processor = clock ();
        time_result_seconds = (float)(time_end_processor - time_start_processor) / CLOCKS_PER_SEC;
    }while (time_result_seconds < time_target_seconds);    
    printf ("End of timer!\n");
}

Makefile

project:
    gcc main.c variant_of_timer.c enter_numbers.c timer.c

2 Востаннє редагувалося -=ЮрА=- (31.01.2016 17:27:09)

Re: Таймер для Ubuntu на С

do{
        time_end_processor = clock ();
        time_result_seconds = (float)(time_end_processor - time_start_processor) / CLOCKS_PER_SEC;
    }while (time_result_seconds < time_target_seconds);

- це цикл без sleep - він буде завантажувати систему по повній, проц буде на 100% завантаженні, з яких 99% буде припадати на цю частину - це поганий концепт.

Подякували: GVIG1

3

Re: Таймер для Ubuntu на С

man sleep
man usleep
man nanosleep

або ж просто

man cron

Подякували: GVIG1

Re: Таймер для Ubuntu на С

Цікаво!  Я погано уник у код.   Може воно можливо переривати роботу циклу яким нєбудь сліп.

Ледь крутонувсь - став. Крутонувсь-став. І може і запрацює

5

Re: Таймер для Ubuntu на С

Дмитро-Чебурашка написав:

Цікаво!  Я погано уник у код.   Може воно можливо переривати роботу циклу яким нєбудь сліп.

Ледь крутонувсь - став. Крутонувсь-став. І може і запрацює

Ні після запуску циклу зупинити роботу програму можливо лише за допомогою sudo kill процес (у мому випадку).
Я ще не придумав, як зробити можливість для переривання роботи циклу.

6 Востаннє редагувалося GVIG (31.01.2016 18:40:07)

Re: Таймер для Ubuntu на С

-=ЮрА=- написав:

це цикл без sleep - він буде завантажувати систему по повній, проц буде на 100% завантаженні, з яких 99% буде припадати на цю частину - це поганий концепт.

Дякую виявилось набагато простіше ніж я спершу очікував!
Навіть не знав, що існує sleep. Не можу придумати, як створити можливість для виходу з програми під час циклу.

    while (seconds--){
        printf ("Time to exit: %d second\n", seconds + 1);
        sleep (1);
    }

Якщо написати getchar() після sleep() то потрібно буде постійно натискати на клавіатурі щось + Enter.
Не маю ідей як зробити це.
Уявляю як це повинно бути, але як реалізувати не знаю.
       йде цикл
                     після sleep() потрібно щоб було натиснута 'q'
                     натиснута: вихід з програми
                     нічого не натиснуто або не 'q': продовжується виконання
Звичайно вийти можна за допомогою Ctrl+C, але хочеться зробити гарніше.

7

Re: Таймер для Ubuntu на С

GVIG, у однопоточній реалізації без опитування юзера через консоль прервати цикл не можна.

Подякували: GVIG1

8 Востаннє редагувалося -=ЮрА=- (31.01.2016 19:29:04)

Re: Таймер для Ubuntu на С

Хоча, хоча... можна створити "велосипед" з файловим i/o тобто у каталозі з ехе потрібен бути так званий керуючий файл (для простоти хай буде звичайний txt-ник), наприклад наступного зміста

runApp : true

у циклі програма повинна постійно зчитувати цей файл та перевіряти значення runApp. Захочеш вимкнути арр, відкриваєш файл та пишеш runApp : false звісно функціонал по файловому зчитуванню та парсінгу тобі доведеться написати.
Друкую схему

int iWork = 1;
while( iWork ){
     update_timer();//це твій функціонал з таймером
     sleep(1);//це твій сліп, проте рекомендую виставити там 10 мсек
     fopen(...);
     fread(...);
     iWork = parse_file();
}

9

Re: Таймер для Ubuntu на С

Можливо стирати екран в терміналі Ubuntu так само швидко, як це було можливо у Windows за допомогою system ("cls")?
Тому що clear не очищує термінал, а просто опускає курсор вниз.
reset - очищує, але робить це довго.
Шукав в Інтернеті, але крім clear та reset нічого не знайшов. Можливо якось швидко очистити термінал?

10 Востаннє редагувалося -=ЮрА=- (31.01.2016 19:32:36)

Re: Таймер для Ubuntu на С

Можливо стирати екран в терміналі Ubuntu так само швидко, як це було можливо у Windows за допомогою system ("cls")?
Тому що clear не очищує термінал, а просто опускає курсор вниз.
reset - очищує, але робить це довго.
Шукав в Інтернеті, але крім clear та reset нічого не знайшов. Можливо якось швидко очистити термінал?

друкуй інформацію таймеру з деліметру \r (він повертає курсор на початок рядка)

#include <stdio.h>

int main(){
    size_t i;
    for( i = 0; i < 100; i++ )
        printf("\r iteration : %d\t", i);
    return 0;
}
Подякували: GVIG, leofun012

11

Re: Таймер для Ubuntu на С

Про клавіші - гляньте тут.
Про очищення екрану - тут.

Подякували: GVIG, leofun012

12

Re: Таймер для Ubuntu на С

-=ЮрА=- написав:

Можливо стирати екран в терміналі Ubuntu так само швидко, як це було можливо у Windows за допомогою system ("cls")?
Тому що clear не очищує термінал, а просто опускає курсор вниз.
reset - очищує, але робить це довго.
Шукав в Інтернеті, але крім clear та reset нічого не знайшов. Можливо якось швидко очистити термінал?

друкуй інформацію таймеру з деліметру \r (він повертає курсор на початок рядка)

#include <stdio.h>

int main(){
    size_t i;
    for( i = 0; i < 100; i++ )
        printf("\r iteration : %d\t", i);
    return 0;
}

друкується лише останній рядок! Всі інші рядки не друкуються!

13 Востаннє редагувалося -=ЮрА=- (31.01.2016 19:52:43)

Re: Таймер для Ubuntu на С

друкується лише останній рядок! Всі інші рядки не друкуються!

- ох і не люблю коли початківці не розібравшись починають кричати ось цим (!) та говорити не працює і таке інше. Друкується там все, ти побачити не встигаєш, я ж сказав вистав у сліпа більший інтервал щоб встигав бачити зміни.

#include <stdio.h>
 
int main(){
    size_t i;
    for( i = 0; i < 100; i++ ){
        printf("\r iteration : %d\t", i);
        sleep(1000);//Так вже все друкується та витирається?А щось змінилось по коду, окрім того що пауза стала більшою?
    }
    return 0;
}

І взагалі перед тим перш ніж щось написати раджу перевіряти роботу в онлайн компіллерах, які показують як воно є http://codepad.org/9TQZcWK4

14 Востаннє редагувалося GVIG (31.01.2016 20:15:06)

Re: Таймер для Ubuntu на С

-=ЮрА=-, ось що в мене виходить:
виводить лише: Time to exit: 1 secondd (не розумію чому не second а secondd)

Post's attachments

Знімок екрана з 2016-01-31 20:10:54.png 62.51 kb, 300 downloads since 2016-01-31 

15

Re: Таймер для Ubuntu на С

GVIG, постав sleep(1000); тобто чекати 1 секунду я ж тобі кажу ти не встигаєш побачити зміни