Skip to content

Commit 81b97ad

Browse files
committed
Новая версия урока 3.4
1 parent 2d5cb22 commit 81b97ad

File tree

10 files changed

+470
-51
lines changed

10 files changed

+470
-51
lines changed

lang_c/3/3__vvod_dannyh_scanf/article.md

Lines changed: 380 additions & 48 deletions
Large diffs are not rendered by default.
13.7 KB
Loading
53.2 KB
Loading
18.9 KB
Loading
12.4 KB
Loading
13.3 KB
Loading
19.8 KB
Loading

lang_c/3/3__vvod_dannyh_scanf/practice.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,20 @@
22

33
- Решите [задачи с автоматической проверкой решения на Stepik](https://stepik.org/lesson/40318/step/1)
44

5+
<div class="lessonStepikBlock">
6+
<iframe src="https://stepik.org/lesson/40318/step/1"></iframe>
7+
</div>
8+
9+
- Попробуйте удалить в программе «sum2» (Листинг 2) символ `&` в каком-нибудь из вызовов функции `scanf`. Посмотрите как отреагирует на это ваш компилятор.
10+
11+
- Самостоятельно прогоните через вызов `scanf("%d%d", &a, &b);` следующие варианты входных потоков ` 10 5\n`, `10\n5\n`. Опишите пошагово, как функция `scanf` будет пошагово их обрабатывать. Ваши ответы можете скидывать на проверку в комментарии к этому уроку.
12+
513
### Исследовательские задачи для хакеров
614

7-
- Попробуйте удалить в программе Листинг 2 символ `&` в какой-нибудь функции `scanf`. Посмотрите какую ошибку выдаст компилятор.
8-
- Попробуйте использовать `%f` для типа `double`, а `%lf` для типа `float`. Каковы результаты? Напишите об этом в комментариях к этому уроку. Не забудьте указать название вашей IDE или компилятора.
15+
- Замените в программе Листинг 4 формат-строку на `"%d %d "`. Используя знания о том, как обрабатывается формат-строка, разберитесь, как прервать выполнение функции `scanf`. Когда разберётесь, напишите об этом в комментариях к этому уроку.
16+
17+
- Запустите программу Листниг 7. Совпадает ли ваш результат с тем, что получилось у меня? Напишите об этом в комментариях к уроку, указав используемую вами IDE и/или компилятор.
18+
19+
- Попробуйте использовать спецификатор `%f` для типа `double`, а спецификатор `%lf` для типа `float`. Каковы результаты? Напишите об этом в комментариях к этому уроку. Не забудьте указать название вашей IDE или компилятора.
20+
21+
- У спецификаторов формата в функции `scanf` тоже есть модификаторы формата, например `*` и ширина поля ввода (например, `%2d`). Разберитесь самостоятельно как они работают.
Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,77 @@
11
## Дополнительные материалы
22

3-
1. пока нет
3+
1\. Представьте: вы написали программу «sum2». Вы знаете, как она работает, потому что сами её создали. Но когда программу запустит другой человек, он увидит просто пустой экран и мигающий курсор. Что делать дальше? Что вводить?
4+
5+
Одним из вариантов решения этой проблемы -- подсказать пользователю, что от него требуется. Давайте посмотрим на пример:
6+
7+
Следующая программа считает количество каллорий, расходуемое на базовый обмен веществ по формуле Миффлина-Сан Жеора. Для расчета нужны: возраст, рост и вес.
8+
9+
Листинг 10. Программа рассчёта базового обмена веществ (BMR, basal metabolic rate)
10+
```c
11+
#include <stdio.h>
12+
13+
int main(void)
14+
{
15+
int age, height, weight;
16+
double bmr_male, bov_female;
17+
18+
printf("Enter your age (in years, integer number):\n");
19+
scanf("%d", &age); // считываем целое значение в переменную age
20+
21+
printf("Enter your height (in centimeters, integer number):\n");
22+
scanf("%d", &height); // считываем значение в переменную height
23+
24+
printf("Enter your weight (in kilograms, integer number):\n");
25+
scanf("%d", &weight); // считываем значение в переменную weight
26+
27+
bmr_male = 10*weight + 6.25*height - 5*age + 5;
28+
bmr_female = 10*weight + 6.25*height - 5*age - 161;
29+
30+
printf("| BMR |\n");
31+
printf("| male | female |\n");
32+
printf("|%8.2f|%8.2f|\n", bmr_male, bmr_female);
33+
34+
return 0;
35+
}
36+
```
37+
38+
39+
2\. В уроке сказано, что при передаче переменных в функцию `scanf` необходимо перед именем переменной добавлять значок `&`. Но почему? Зачем это нужно? Всё дело в том, как в языке Си устроена передача аргументов в функцию.
40+
41+
Когда вы передаете переменную в функцию, происходит следующее:
42+
1. В памяти компьютера для этой переменной выделяется новое место;
43+
2. Значение переменной копируется в это место;
44+
3. Функция работает только с этой копией.
45+
46+
Это называется =передача по значению (pass by value)=.
47+
48+
Вернёмся к нашей любимой аналогии с коробками. Представьте, что у вас есть коробка с важным числом (переменная). Когда вы вызываете функцию, вы не отдаете ей свою коробку, а делаете временную копию и отдаете её. Что бы функция ни делала с этой копией, ваша оригинальная коробка в безопасности.
49+
50+
Но функция `scanf` -- это особый случай. Эта функция должна **записать** новое значение в вашу переменную. Копия тут не прокатит -- нужен доступ к оригиналу. Поэтому мы используем `&`. В этом случае функция получает не какую-то там жалкую копию, а информацию о том, где в памяти находится наша переменная, а потому может записать в неё введенное пользователем значение.
51+
52+
Логика в этом примерно следующая. Мы относимся к любым функциям как к потенциально опасным объектам, которые могут повредить данные. Поэтому по умолчанию функции получают только копии данных -- это защищает от случайных изменений. А чтобы позволить функции работать с оригинальными данными, мы должно совершить сознательное действие -- передать адрес переменной.
53+
54+
Мы ещё подробнее обсудим этот механизм, когда будем изучать, как можно создавать собственные функции.
55+
56+
57+
58+
3\. У функции `printf` есть специальный спецификатор `%p`, который используется, чтобы вывести адрес на экран.
59+
60+
```c
61+
#include <stdio.h>
62+
63+
int main(void)
64+
{
65+
int x = 10;
66+
67+
printf("value x:\t %d\n", x); // выводим значение переменной
68+
printf("address:\t %p\n", &x); // выводим адрес переменной в памяти
69+
70+
return 0;
71+
}
72+
```
73+
74+
Более того, для хранения адреса можно использовать специальный тип переменных, который называется =указателями=. Ближе к концу курса мы познакомимся поближе с этим понятием.
75+
76+
77+
4\. В некоторых случаях функция `scanf` может вернуть отрицательное число (обычно `-1`). Это происходит в случаях, когда произошла ошибка чтения потока (например, в потоке не оказалось данных) или был достигнут конец файла (например, если поток был связан с каким-то текстовым файлом).
15.2 KB
Loading

0 commit comments

Comments
 (0)