Как создать программу моделирования, которая перестает выполняться раньше или через 24 часа после имитации

Есть резервуар с водой на 500 галлонов, который использовался для хранения рыбы, чтобы она стала мальками в течение 24 часов. Резервуар как течь, который теряет воду из расчета 10% оставшейся воды каждый час. Как мне исправить мой код, чтобы он перестал выполняться через 24 часа или после того, как объем бака достигнет 100 галлонов. По какой-то причине я не могу понять цикл for.

int main()
{
    double add, gal = 500, vol, newVol, hour;

    printf("Please enter additional water added per hour: ");
    scanf("%f", &add);

    for (int hour = 0; hour <= 24; hour++)
    {
        vol = gal * 0.90 + add;
    }
    printf("The volume is %f gallons after %d hours. \n", &vol, &hour);

}

person intriguedandconfused    schedule 26.03.2019    source источник
comment
Просто: обратите внимание на отметку времени в начале и через определенный интервал продолжайте проверять отметку времени.   -  person Sourav Ghosh    schedule 26.03.2019
comment
Добавить условие в свой цикл, чтобы проверить громкость?   -  person Some programmer dude    schedule 26.03.2019
comment
Добавить if (vol >= 100.0) break; в цикл? Хотя я не понимаю 100, если бак имеет емкость 500 галлонов...   -  person Stefan Becker    schedule 26.03.2019
comment
Или инициализируйте vol = 0.0 при объявлении, а затем for (int hour = 0; hour <= 24 && vol >= 100; hour++) (это предполагает, что вы хотите продолжать жарить до тех пор, пока объем масла не упадет ниже 100 галлонов - при необходимости отрегулируйте тест) И &vol, &hour); должно быть vol, hour);. (без знака '&' для печати)   -  person David C. Rankin    schedule 26.03.2019
comment
Это означает, что у вас недостаточно предупреждений компилятора. Для gcc/clang добавьте -Wall -Wextra -pedantic в строку компиляции, для VS добавьте /W3 и не принимайте код, пока он не скомпилируется без предупреждения.   -  person David C. Rankin    schedule 26.03.2019
comment
Я отредактировал заголовок, чтобы рассказать о симуляции, поскольку ваш код, похоже, не использует реальное время и выглядит как симуляция. Если на самом деле предполагается использовать режим реального времени, откатитесь назад.   -  person hyde    schedule 26.03.2019
comment
@hyde - я думаю, ты в безопасности, ничего о рыбе, которую нужно сделать к 5:00.   -  person David C. Rankin    schedule 26.03.2019


Ответы (3)


В вашей программе несколько проблем:

  • вы должны включить <stdio.h>
  • Спецификация преобразования scanf() для типа double — это %lf, а не %f.
  • Вы должны протестировать возвращаемое значение scanf(), чтобы избежать неопределенного поведения при неверном вводе.
  • Цикл повторяется 25 раз вместо 24.
  • выражение vol = gal * 0.90 + add; для обновления тома неверно: следует обновить gal или использовать только vol. Кроме того, если вода добавляется в начале каждого часа, ее должно быть vol = (gal + add) * 0.90;, но бак не может вмещать более 500 галлонов. Если вода добавляется в конце каждого часа, вы должны проверить, достигает ли она 100 галлонов, прежде чем добавлять больше воды.
  • вы не проверяете предел 100 галлонов
  • формат printf некорректен, как и аргументы: должно быть printf("The volume is %f gallons after %f hours. \n", vol, hour); или лучше printf("The volume is %f gallons after %d hours. \n", vol, hour);, а hour должно определяться как int.
  • main должно вернуть 0.

Вот исправленная версия:

#include <stdio.h>

int main() {
    double add, gal = 500, vol;
    int hour;

    printf("Please enter additional water added per hour: ");
    if (scanf("%lf", &add) != 1) {
        printf("invalid input\n");
        return 1;
    }
    for (vol = gal, hour = 1; hour <= 24; hour++) {
        vol = vol * 0.90;
        if (vol <= 100)
            break;
        /* water is added at the end of each hour */
        vol += add;
        /* the tank cannot hold more than 500 gallons */
        if (vol > gal)
            vol = gal;
    }
    printf("The volume is %f gallons after %d hours.\n", vol, hour);
    return 0;
}

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

person chqrlie    schedule 26.03.2019
comment
В C (начиная с C99, я думаю) вам не нужен return в main, и если он отсутствует, то ожидается возвращаемое значение 0. - person hyde; 26.03.2019
comment
@hyde: это верно для C99 и более поздних версий, комитет взломал спецификацию C, чтобы гарантировать, что небрежный устаревший код будет неявно возвращать 0, если main уходит без оператора return. Сделать это неявное return 0; явным — хороший стиль. - person chqrlie; 26.03.2019
comment
Как vol может быть <= 100, если выше vol = gal * 0.90 и gal постоянны в цикле? Разве это не должно быть for (vol=gal, hour... и vol *= 0.9 ниже? - person Breaking not so bad; 26.03.2019
comment
@RingØ: действительно, ты прав! всегда есть еще одна ошибка :) - person chqrlie; 26.03.2019
comment
@chqrlie Я полагаю, это вопрос мнения. В C быть явным - это вещь (по сравнению, например, с C++, где конструкторы могут выполнять неизвестный объем обработки в копиях и т. д.). OTOH, каждая строка, которая ничего не привносит в код, — это плохая строка, просто беспорядок. Я думаю, что правильным решением было бы изменить тип возврата на void main(), поскольку это разрешено в C (IIRC). - person hyde; 26.03.2019
comment
@hyde: void main() не разрешен стандартом C. Явное значение return 0; означает возврат успешного выполнения в исполняющую среду. Сделать некоторые неявные вещи явными — вопрос стиля и ясности ИМХО. Например, char *p = NULL; предпочтительнее char *p = 0;, что точно эквивалентно, но менее явно. - person chqrlie; 30.03.2019
comment
@chqrlie После некоторого поиска в Google кажется, что стандарт C позволяет реализовать основные подписи, определенные реализацией (я полагаю, в отличие от C ++). Это, наверное, то, что я вспомнил. Однако это не имеет значения, поскольку вещи, нарушающие переносимость, очевидно, не должны использоваться без веской причины. - person hyde; 30.03.2019
comment
@hyde: C19 5.1.2.2.1 Запуск программы Функция, вызываемая при запуске программы, называется main. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвращаемого значения int и без параметров: int main(void) { /* ... */ } или с двумя параметрами (обозначаемыми здесь как argc и argv, хотя можно использовать любые имена, поскольку они являются локальными для функции, в которой они объявлены): int main(int argc, char *argv[]) { /* ... */ } или эквивалентным, или каким-либо другим способом, определяемым реализацией. - person chqrlie; 30.03.2019
comment
Другой способ, определяемый реализацией, обычно относится к добавлению третьего аргумента в unix-системах, таких как: int main(int argc, char **argv, char** envp) {...}. Я не могу придумать ни одной среды C, в которой void main() вызывал бы проблемы, но тем не менее это неверно. - person chqrlie; 30.03.2019

Насколько я понимаю, это всего лишь симуляция, которая не обязательно должна быть в реальном времени.

Просто добавить строку:

if (vol <= 100) break;

Таким образом, он выходит из цикла for.

Кстати, в вашем коде наверняка есть и другие ошибки. Например, vol всегда будет одним и тем же значением. Также ваша переменная hour, используемая для цикла for, отличается от той, которую вы используете снаружи (например, в printf). Вы должны сделать что-то подобное, чтобы заставить его работать:

vol = gal
for (hour = 0; hour <= 24; hour++)
{
    vol = vol * 0.90 + add;
    if (vol <= 100) break;
}
person Puck    schedule 26.03.2019

Вы можете использовать функцию gettimeofday(), чтобы получить начальное время (когда процесс начинается), а затем снова использовать gettimeofday() несколько раз, чтобы получить текущее время. Когда разница между текущим временем и начальным временем составляет 24 часа, прерывание цикла.

Для справки проверьте http://man7.org/linux/man-pages/man2/gettimeofday.2.html

person Shrishty Deorari    schedule 26.03.2019
comment
Ну да, но зацикливание hour = 0; hour <= 24; ... делает это благодаря счетчику циклов :) - person David C. Rankin; 26.03.2019
comment
Я не думаю, что вопрос в том, чтобы ждать фактические 24 часа, а вместо этого запускать симуляцию так быстро, как она работает, поэтому gettimeofday бесполезен. - person hyde; 26.03.2019