#c
#c
Вопрос:
Я пишу программу, но она неполная, которая показывает разницу в процентах для доходов мобильной компании. Я должен использовать среднее значение массива для хранения выручки от продаж за последние 3 года. Пример вывода приведен ниже Процент дохода мобильной компании
Enter Revenue for 2017: 100000
Enter Revenue for 2018: 250000
Enter Revenue for 2018: 150000
Enter Revenue for 2018: 150000
Year % Remark
Increase 150 2018
Decrease 40- 2019
Unchange" 0,0 2020
#include <stdio.h>
int main() {
printf("--------------------------------------------------n ");
printf("Mobile Company Revenue Percentagen ");
printf("--------------------------------------------------n ");
int i;
float Revenue[4], sum = 0.0, avg;
float rev1,rev2,rev3,rev4;
printf("Enter Revenue for 2017: ");
scanf("%f", amp;rev1);
printf("Enter Revenue for 2018: ");
scanf("%f", amp;rev2);
printf("Enter Revenue for 2018: ");
scanf("%f", amp;rev3);
printf("Enter Revenue for 2018: ");
scanf("%f", amp;rev4);
for (i = 0; i < 5; i) {
sum = Revenue[i];
}
avg = sum / sizeof(Revenue);
printf("Average = %.2f", avg);
return 0;
}
Комментарии:
1.
for (i = 0; i < 4; i)
ошибка по одному. Допустимые индексы дляRevenue
0
сквозные3
, нет4
. Кроме того, все элементыRevenue
неинициализированы и попытка доступа к нимsum = Revenue[i];
вызывает неопределенное поведение . Всегда инициализируйте свои массивы, напримерfloat Revenue[4] = {0};
. Вы не можете правильно использовать какую-либо функцию ввода без проверки возврата . В противном случае у вас нет возможности узнать, был ли ввод успешным или неудачным.avg
Требуетсяsum / (sizeof Revenue / sizeof *Revenue
). Почемуsizeof Revenue == 20
2. Пришло время узнать о массивах и
for
циклах. Вы почти используете их здесь, но, похоже, вы пропустили и вместо этого объявили кучу несвязанных переменных.3. Вам нужно задать конкретный вопрос. Какая конкретная проблема у вас есть, которая мешает вам продвигать код?
4. Прежде всего,
float
это небезопасно, поскольку это приводит к снижению производительности и является менее точным, чемdouble
.
Ответ №1:
Очевидно, у вас возникли небольшие проблемы. Как отмечалось выше, в моем комментарии у вас есть ряд проблем, и вы вызываете неопределенное поведение, пытаясь использовать значения массива с автоматической продолжительностью хранения, если значения не определены (неинициализированы). Проблема возникает из-за использования вами магических чисел в вашем коде. Это приводит к тому, что ваш лимит цикла увеличивается на единицу (слишком много).
Чтобы избежать использования магических чисел, вычислите, что вам нужно, и присвоите значение переменной. Например, вам нужно количество элементов Revenue
в. Это можно определить, взяв размер массива, деленный на размер первого элемента.
int nelem = sizeof Revenue/sizeof *Revenue;
(примечание: правильный тип будет size_t
, но C int
также допускает возврат)
Установив количество элементов, вы можете выполнить цикл соответствующее количество раз и вычислить среднее значение с соответствующим делителем, например
for (i = 0; i < nelem; i )
sum = Revenue[i];
avg = sum / nelem;
printf ("nAverage = %.2fn", avg);
Теперь давайте посмотрим на входные данные. Вы не сможете правильно использовать любую функцию пользовательского ввода, если не проверите возврат. В противном случае у вас нет способа определить, был ли ввод успешным или неудачным. Кроме того, для пользователя вполне допустимо отменить ввод, создав руководство EOF
(с Ctrl dили Ctrl zв Windows). Поэтому вы должны справиться с этим случаем. Вам также необходимо удалить 'n'
left в stdin
by scanf()
на случай, если следующий ввод в вашей программе будет с функцией ввода, которая не отбрасывает начальные пробелы.
Поскольку вы будете принимать более одного float
, было бы разумно написать короткую функцию для обработки проверки для вас. Поэтому каждый раз, когда вам нужно float
, вы просто вызываете функцию. Вы можете выполнить это, используя приглашение для отображения в качестве параметра функции. Вы могли бы сделать что-то вроде:
/* display prompt and return float (exit on manual EOF) */
float getfloat (const char *prompt)
{
float f = 0;
while (1) { /* loop continually until valid float provided by user */
if (prompt) /* prompt if not NULL */
fputs (prompt, stdout);
int rtn = scanf ("%f", amp;f); /* read float, save return */
if (rtn == EOF) { /* check for manual EOF */
puts ("(user canceled input)");
exit (EXIT_SUCCESS);
}
empty_stdin(); /* empty to end of line */
if (rtn == 1) /* if good input, break loop */
break;
fputs (" error: invalid float input.n", stderr); /* handle error */
}
return f; /* return float value */
}
Обратите внимание, функция постоянно повторяется, пока пользователь не предоставит действительный float
или не отменит ввод. Именно так вы должны подходить к каждому пользовательскому вводу. Не разрешайте пользователю вводить входные данные, не обработав эту ошибку и не убедившись, что вы получаете входные данные, требуемые вашей программой.
empty_stdin()
Вспомогательная функция, вызванная getfloat()
выше, просто отбрасывает любые посторонние символы stdin
до следующего 'n'
или EOF
в зависимости от того, что произойдет раньше. Таким образом, если пользователь вводит что-то вроде "Lots of money"
вместо действительной суммы, это удаляется stdin
до вашей следующей попытки ввода. Ничего больше не требуется, чем:
/* simple helper to clear stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != 'n' amp;amp; c != EOF)
c = getchar();
}
Теперь ваша main()
функция сводится к фрагменту читаемого кода, который позволяет получить четыре float
значения и вычислить среднее значение, например
int main (void) {
float Revenue[4] = {0}, sum = 0.0, avg = 0;
int i, nelem = sizeof Revenue/sizeof *Revenue;
puts ("--------------------------------------------------n"
"Mobile Company Revenue Percentagen"
"--------------------------------------------------n ");
Revenue[0] = getfloat ("Enter Revenue for 2017: ");
Revenue[1] = getfloat ("Enter Revenue for 2018: ");
Revenue[2] = getfloat ("Enter Revenue for 2019: ");
Revenue[3] = getfloat ("Enter Revenue for 2020: ");
for (i = 0; i < nelem; i )
sum = Revenue[i];
avg = sum / nelem;
printf ("nAverage = %.2fn", avg);
}
(Я составил годы с тех пор, как вы 2018
указали 3 из 4 лет)
Вам нужен только один вызов функции вывода, чтобы вывести столько строк, сколько вам нужно. Если не требуется преобразование (например "%f"
, и т. Д.), То Нет необходимости использовать функцию variadic printf()
. Просто используйте puts()
(или fputs()
, если вам нужен конечный контроль.
Пример использования / вывода
$ ./bin/mobileco
--------------------------------------------------
Mobile Company Revenue Percentage
--------------------------------------------------
Enter Revenue for 2017: 100
Enter Revenue for 2018: 200
Enter Revenue for 2019: 300
Enter Revenue for 2020: 400
Average = 250.00
Если пользователь вводит неверный ввод, программа не примет его, например:
$ ./bin/mobileco
--------------------------------------------------
Mobile Company Revenue Percentage
--------------------------------------------------
Enter Revenue for 2017: A whole lot of $Money$ :)
error: invalid float input.
Enter Revenue for 2017: 100
Enter Revenue for 2018: 200
Enter Revenue for 2019: three-hundred
error: invalid float input.
Enter Revenue for 2019: 300
Enter Revenue for 2020: 400
Average = 250.00
Вычисление процента — изменение дохода между годами
В ответ на ваш комментарий ниже, вы можете вычислить процентное увеличение или процентное уменьшение от среднего дохода, используя формулу процентного изменения. Для вычисления значения у вас есть original
new
значение и. При вычислении изменения от среднего значения ваше original
значение является средним, а new
значение — доходом за год. Вам нужно применить либо формулу увеличения в процентах, если доход превышает средний, либо формулу уменьшения в процентах, если доход ниже среднего.
Формулы для увеличения и уменьшения процентов следующие:
pct_increase = (new - original) / original * 100;
и
pct_decrease = (original - new) / original * 100;
Вы можете просто создать функцию изменения процента и проверить original
значения new
и, применить правильную формулу и вернуть это значение. Например:
/* percent change between new_value and orig_value */
float percentchg (const float new_value, const float orig_value)
{
if (new_value < orig_value)
return (orig_value - new_value) / orig_value * 100.;
return (new_value - orig_value) / orig_value * 100.;
}
(примечание: поскольку new
это ключевое слово C , лучше избегать его использования в вашем коде, на случай, если ваш код будет включен позже как часть программы на C , хотя есть способы заставить его работать)
Затем, main()
чтобы вычислить процентное изменение за каждый год, вы должны сделать:
...
printf ("nAverage = %.2fnn", avg);
for (i = 0; i < nelem; i )
printf ("year %d revenue: %.2f%% (%s) from averagen", i 1,
percentchg (Revenue[i], avg),
Revenue[i] < avg ? "decrease" : "increase");
(примечание: троичный используется для определения того, выводить "decrease"
или "increase"
как часть вывода. Троичный — это всего лишь короткая рука if (condition) { if_true } else { if_false }
, для которой синтаксис:
condition ? if_true : if_false
который вы можете видеть включенным в качестве параметра printf()
функции, предоставляющей входные данные для спецификатора "%s"
формата)
Новый пример вывода
$ ./bin/mobileco
--------------------------------------------------
Mobile Company Revenue Percentage
--------------------------------------------------
Enter Revenue for 2017: 100
Enter Revenue for 2018: 200
Enter Revenue for 2019: 300
Enter Revenue for 2020: 400
Average = 250.00
year 1 revenue: 60.00% (decrease) from average
year 2 revenue: 20.00% (decrease) from average
year 3 revenue: 20.00% (increase) from average
year 4 revenue: 60.00% (increase) from average
Полный код
Если бы вы помогли увидеть код compete после обновления, то есть:
#include <stdio.h>
#include <stdlib.h>
/* simple helper to clear stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != 'n' amp;amp; c != EOF)
c = getchar();
}
/* display prompt and return float (exit on manual EOF) */
float getfloat (const char *prompt)
{
float f = 0;
while (1) { /* loop continually until valid float provided by user */
if (prompt) /* prompt if not NULL */
fputs (prompt, stdout);
int rtn = scanf ("%f", amp;f); /* read float, save return */
if (rtn == EOF) { /* check for manual EOF */
puts ("(user canceled input)");
exit (EXIT_SUCCESS);
}
empty_stdin(); /* empty to end of line */
if (rtn == 1) /* if good input, break loop */
break;
fputs (" error: invalid float input.n", stderr); /* handle error */
}
return f; /* return float value */
}
/* percent change between new_value and orig_value */
float percentchg (const float new_value, const float orig_value)
{
if (new_value < orig_value)
return (orig_value - new_value) / orig_value * 100.;
return (new_value - orig_value) / orig_value * 100.;
}
int main (void) {
float Revenue[4] = {0}, sum = 0.0, avg = 0;
int i, nelem = sizeof Revenue/sizeof *Revenue;
puts ("--------------------------------------------------n"
"Mobile Company Revenue Percentagen"
"--------------------------------------------------n ");
Revenue[0] = getfloat ("Enter Revenue for 2017: ");
Revenue[1] = getfloat ("Enter Revenue for 2018: ");
Revenue[2] = getfloat ("Enter Revenue for 2019: ");
Revenue[3] = getfloat ("Enter Revenue for 2020: ");
for (i = 0; i < nelem; i )
sum = Revenue[i];
avg = sum / nelem;
printf ("nAverage = %.2fnn", avg);
for (i = 0; i < nelem; i )
printf ("year %d revenue: %.2f%% (%s) from averagen", i 1,
percentchg (Revenue[i], avg),
Revenue[i] < avg ? "decrease" : "increase");
}
Просмотрите все и дайте мне знать, если у вас возникнут дополнительные вопросы.
Комментарии:
1. спасибо, как показать разницу в процентах для доходов мобильной компании??
2. Из-за того, что вы имеете в виду за каждый год, например, между 2017-2018, а затем 2018-2019 и т. Д.? То есть, как только у вас будет среднее значение, вы захотите узнать разницу в процентах за каждый год?
3. @Fedaa — Я обновил ответ, чтобы включить вычисления изменения процента.