• ,

Гарвард CS50: задания первой недели (лекции 3 и 4)

CS50 задания

Друзья, основные теоретические сведения вы можете почерпнуть из конспекта семинаров. Там, помимо основ С рассказано, как подключиться к специальной облачной IDE CS50 (это нужно сделать для выполнения и проверки заданий), описаны основные нужные команды Linux и структуры языка. Если вам будет недостаточно материала о C, изложенного в лекции и конспекте, обратитесь к другим источникам. Например, к тем, что указаны в конце данной статьи.

В топике "Дополнительные материалы"
  • Цели первой недели
  • IDE CS50
  • Командная строка и обновление рабочей среды
  • Работа в IDE
  • Hello, C!
  • Баги?
  • Проверка на правильность: тест check50
  • Основы С: сравнение со Scratch
  • Основные типы данных в C
  • Библиотеки С
  • И снова Hello C: разбор синтаксиса простейших программ
  • Еще немного о вводе/выводе в C
Материалы в этом топике:

Ввод данных с проверкой: специальные функции библиотеки cs50.h
Для более удобного прохождения этого курса, мы разработали специальную библиотеку CS50, в которой, в частности, есть очень полезные функции обработки введенных пользователем данных.

GetString() считывает введенную пользователем строку
GetInt() считывает введенную пользователем строку и проверяет, не записано ли в ней целое число
GetFloat()считывает введенную пользователем строку и проверяет, не записано ли в ней число с плавающей точкой
GetLongLong() считывает введенную пользователем строку и проверяет, не записано ли в ней длинное вещественное число.

Задание 1. Умный подсчет расхода воды



Логично: чем дольше вы принимаете душ, тем больше воды уходит на этот процесс. Давайте прикинем, сколько? Даже если ваш душ едва открыт, в минуту из него вытекает примерно 6 литров воды. А это 12 бутылочек воды, которые вы носите с собой для питья. Обычно человек принимает душ минут 10. Итого, чтобы помыться, нужно 120 полулитровых бутылок. Немало!

Создайте файл water.c в вашей директории ~/workspace/pset1. Программа должна подсчитывать сколько бутылочек воды уходит на душ зависимости от времени. То есть:

  1. Программа запрашивает у пользователя количество минут, проведенных в душе
  2. Пользователь вводит положительное целое число
  3. Программа выводит на экран количество бутылочек, израсходованных пользователем.

username:~/workspace/pset1 $ ./water
minutes: 10
bottles: 120

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

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

check50 2015.fall.pset1.water water.c

А если вы хотите посмотреть, как работает программа water, написанная сотрудниками курса выполните следующую команду:

~cs50/pset1/water


Задание 2. С нами Марио!


Знаете ли вы самого знаменитого водопроводчика в мире? С легкой руки компании Nintendo вымышленный усатый и немного полноватый дядечка в красной кепке стал героем для нескольких поколений геймеров. Если вы не знаете, о ком речь, вот вам ссылка на классическую игру 1985 года: поверьте, она всё ещё хороша и заслуживает внимания! Также можно найти вариант классического Super Mario для смартфонов или оффлайновых эмуляторов. Всё это нам нужно для общего развития, это еще, к сожалению, не задание;). А задание состоит вот в чем. В конце первого уровня Mario каждый игрок видел вот такую полупирамидку:

Создайте файл mario.c в вашей директории ~/workspace/pset1. Наша рограммка будет рисовать полупирамиду, подобную той, что вы видите, но прямо в консоли, без графики: каждый из блоков будет состоять из значка хэша (#). Даже если вы еще не сообразили, как это сделать, поверьте: это просто. Чтобы сделать задачу более интересной, добавим в неё возможность задавать высоту полупирамидки с помощью неотрицательного целого числа от 0 до 23. Высота пирамидки на картинке считается в самом высоком месте, то есть равна 8. Если пользователь неправильно вводит число, нужно попросить его сделать это ещё раз. Затем сгенерировать (с помощью printf пирамидку.

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

username:~/workspace/pset1 $ ./mario

height: <u>8</u>
       ##
      ###
     ####
    #####
   ######
  #######
 ########
#########

Обратите внимание, что два крайних правых столбца имеют одинаковую высоту. Генерировать трубы, облака и самого Марио пока не стоит=). По крайней мере для этого задания.

Если пользователь ввел неправильные данные (ввел не число, или число, которое меньше единицы или больше, чем 23), программа должна снова попросить его ввести данные, как в примере внизу, где подчеркнутый текст — то, что вводил пользователь с клавиатуры.

Для считывания введенной строки используйте GetInt. Она может помочь проверить неправильный ввод, но не для всех случаев.

username:~/workspace/pset1 $ ./mario
Height: -2
Height: -1
Height: foo
Retry: bar
Retry: 1
##

Чтобы скомпилировать программу, введите строку в терминале:

make mario

или более прозрачный, но длинный вариант:

clang -o mario mario.c -lcs50

после этого запустите программу на исполнение:

./mario

Если вы хотите проверить правильность выполнения программы, запускайте check50:

check50 2015.fall.pset1.mario mario.c

А если вы хотите поиграться с версией mario, созданной ассистентами курса, mario набирайте следующую строку:

~cs50/pset1/mario


Задание 3. Время получать сдачу

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

Однако что будет, если кто-то рассчитается с кассиром крупной купюрой? Представьте, сколько мороки будет с тем, чтобы посчитать монетки на сдачу. Для минимизации количества выдаваемых монет можно использовать так называемые «жадные» алгоритмы. Они, согласно определению Национального Института Стандартов и Технологии (NIST) всегда находят оптимальное решение на каждом шаге решения задачи, допуская, что конечное решение (полученное из совокупности таких шагов) также будет оптимальным.

Что это значит? Представим, что кассир должен покупателю сдачу в 41 цент, а у него на поясе есть цилиндры с монетками для сдачи номиналом в 25, 10, 5 и 1 цент. Руководствующийся «жадным» алгоритмом кассир сразу же захочет выдать максимум, на первом же шаге. На этом шаге оптимальным или наилучшим решением будет выдать 25 пенсов. 41-25 = 16. Осталось выдать 16 пенсов. Очевидно, 25 пенсов слишком много, значит, остается 10. 16-10 = 6. Теперь выдаем по тому же принципу 5 пенсов, и затем — 1. Таким образом, покупатель получит всего четыре монеты номиналом 25, 10, 5 и 1 пенс.

Оказывается, «жадная» пошаговая инструкция выдачи денег оптимальна не только для этого случая, но также для номиналов валюты США (и Евросоюза тоже). То есть, если у кассира достаточно монет любого номинала, алгоритм будет работать лучшим образом, то есть, выдаст минимальное количество монет из всех возможных случаев.
Итак, какое минимальное количество монеток нам нужно, чтобы дать сдачу? Это и есть наша третья задачка.

Создайте файл greedy.c в своей директории ~/workspace/pset1.

Дано: монетки номиналом 25, 10, 5, 1 цент

Программа должна:

  1. Спросить пользователя, сколько сдачи нужно выдать
  2. Посчитать минимальное количество монет, с помощью которых можно это сделать

Примечание: для ввода будем пользоваться функцией GetFloat из библиотеки CS50 и printf из стандартной библиотеки ввода/вывода для вывода. Кроме того, программа должна проверять корректность ввода.

Мы попросили вас использовать GetFloat, чтобы пользователь мог вводить значение в долларах и центах через точку. Например, если мы должны $9.75, пользователь должен ввести 9.75, но не $9.75 или 975.

Вы должны проследить, чтобы пользователь ввел число, которое имеет смысл. Скажем, неотрицательное, в этом функция GetFloat сама по себе не поможет. Если пользователь сделал неправильный ввод, нужно просить его повторить его и выполнять программу только с корректными данными.

Остерегайтесь неточностей, свойственных числам с плавающей точкой. Например, 0.01 не может быть представлено непосредственно как float. Попробуйте использовать форматированный вывод, например, с 50 знаками после запятой, используя указанный ниже код:

float f = 0.01;
printf("%.50f\n", f);

Кстати, перед тем, как что-либо считать, будет логично перевести всю сумму в центы, (и заодно преобразовать её из float в int), что поможет избежать массы ошибок и сложностей.
Чтобы наш автоматический анализатор кода мог правильно проверить вашу задачу, убедитесь, что последняя строка вывода вашей программы не содержит никакой другой информации, кроме минимального количества монеток: целое число с символом \n после него (те, кто учится на JavaRush, прекрасно знают, о чём мы здесь говорим =)).

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

username:~/workspace/pset1 $ ./greedy
O hai! How much change is owed?
0.41
4

Учитывая особенность чисел с плавающей точкой, можно игнорировать нуль и вводить такое число в форме .41.
Конечно, пользователи, которые захотят проверить программу на возможность ввода некорректных данных по полной, должны увидеть что-то вроде:

username:~/workspace/pset1 $ ./greedy
O hai! How much change is owed?
-0.41
How much change is owed?
-0.41
How much change is owed?
foo
Retry: 0.41
4

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

Если во время тестирования приложения вы поймете, что цикл не останавливается, вы можете прервать выполнение программы комбинацией ctrl-c (иногда — многократной).

Как компилировать и выполнять программу вы уже знаете.

Если вы хотите проверить правильность работы вашей программы, с помощью утилиты check50, в терминале введите следующую строку:

check50 2015.fall.pset1.greedy greedy.c

А если вам захочется поиграть с этой программой, выполненной ассистентами курса, пропишите следующую команду:

~cs50/pset1/greedy

Как подтвердить правильность кода и получить оценки

Вариант 1

Если вам важно проверить именно правильность кода, а не получить итоговую оценку, вы можете его проверять и исправлять с помощью команды

check50 2015.fall.pset1.name name.c


введенной в терминальной строке CS50 IDE.
Где name — название файла вашей задачи.

Вариант 2
Если же вы хотите получить оценки (по сути, тот же запуск check50, но с запоминанием результата и заполнением некоторых форм на английском, тогда проделайте следующие шаги:
Шаг 1 из 2

  1. Когда приложения готовы, залогиньтесь в CS50 IDE.
  2. В левом верхнем углу CS50 IDE в пределах его файлового браузера, а не терминального окна, кликните левой клавишей мыши с удержанием ctrl или правой клавишей мыши по вашему файлу hello.c (тому, который лежит в директории pset1 ) и нажмите Download. Вы должны обнаружить, что браузер загрузил hello.c.
  3. Повторите для water.c.
  4. Повторите для mario.c.
  5. Повторите для greedy.c.
  6. В отдельной вкладке или окне залогиньтесь в CS50 Submit.
  7. Нажмите Submit в левом нижнем углу окна.
  8. Под Problem Set 1 на появившемся окне нажмите на Upload New Submission.
  9. На появившемся окне жмите Add files…. Должно появиться окно с именем Open Files.
  10. Пройдите путь к месту, куда загружен hello.c. Обычно он находится в папке Downloads или в той папке, которая назначена у вас по умолчанию для загрузки. Найдя hello.c, нажмите на него один раз чтобы отметить, затем нажмите Open.
  11. Кликните Add files… снова, и окно Open Files снова появится.
  12. Теперь найдите таким же образом файл water.c. Кликните по нему, затем кликните Open (или «Открыть»).
  13. Теперь находите mario.c. И тоже кликайте и открывайте таким же образом.
  14. Все то же самое с файлом greedy.c.
  15. Нажмите Start upload чтобы начать загрузку ваших файлов на серверы CS50.
  16. На появившемся экране вы увидите окно с надписью No File Selected. Если вы переместите курсор мыши в левую часть окра, вы увидите список файлов, которые вы загрузили. Нажмите на каждый, чтобы подтвердить содержание каждого из них. (Нет необходимости нажимать на другие кнопки или иконки). Если уверены, что готовы отослать файл на проверку, считайте, вы все сделали! Если хотите проверить свой код самостоятельно ещё раз или исправить что-либо, возвращайтесь в CS50 Submit и повторите эти шаги. Вы можете повторно отправить столько раз, сколько вы хотите; оцениваться будет только самое последнее представление.

Шаг 2 из 2
(он не обязателен для оценки, если что=))
Теперь перейдите по ссылке http://cs50.edx.org/2016/psets/1/ где вы обнаружите специальные формы. В них нужно ответить на несколько теоретических вопросов, и затем нажать Submit под ними.

Вопросы со звездочками – обязательны:

  • Alright, should've seen this one coming! In just a few sentences, what's a library? * (Кратко опишите, что такое библиотека)
  • In just a few sentences, what role does
    #include <cs50.h>

    play when you write it atop some program? *(какова роль строки #include <cs50.h>, которая фигурирует в верхней части кода некоторых программ?)
  • About how many hours would you say you spent on Problem Set 0: Scratch?(сколько времени у вас заняли задачки нулевой недели (Scratch)
  • About how many hours would you say you spent on Problem Set 1: C?(как долго вы решали задачки первой недели по C?)
  • What's your opinion of CS50x thus far? *(Ваше мнение о CS50 в настоящий момент, выбрать вариант нравится-не нравится)
  • Have you asked for help from classmates or staff via CS50s Facebook Group at www.facebook.com/groups/cs50? *(обращались ли вы за помощью к другим студентам или ассистентам в группе facebook)
  • Have you asked for help from classmates or staff via CS50s Subreddit at www.reddit.com/r/cs50 *(обращались ли вы за помощью к другим студентам или ассистентам через Subreddit)
  • Have you asked for help from classmates or staff via Twitter using @cs50 or #cs50? *(просили ли вы помощи у других студентов или ассистентов в Twitter используя @cs50 или #cs50).


Друзья, если возникают какие-то вопросы, пишите их в комментариях под этим руководством. Если вы не достигли пятого уровня JavaRush, чтобы получить приглашение на info, рекомендуем это сделать. Это бесплатно, интересно и не очень сложно.

Ресурс кода:

Лекция три
cdn.cs50.net/2015/fall/lectures/1/w/src1w.zip
Лекция четыре
cdn.cs50.net/2015/fall/lectures/1/f/src1f.zip
cdn.cs50.net/2015/fall/lectures/1/f/src1f/

Дополнительная литература

cpp.com.ru/kr_cbook/ — русская версия классической книги по C от авторов языка — Брайана Кернигана и Дэнниса Ритчи. Широко известна в узких кругах как K&R. Перевод, правда, не самого нового издания.
Почитайте первые три главы. Там будет несколько больше материала, чем вам нужно, но достаточно для решения задач.
computer.howstuffworks.com/c.htm — ресурс, рекомендуемый авторами CS50. На английском языке. Стр. 1-7, 9 и 10.

49 комментариев

ggking
я один только первую задачу решил? а во второй получил пирамиду, которая выравнивается по другому краю, да и то с помощью функции из 5 лекции взятой? мне кажится я что-то не так делаю в этой жизни
зы: опыта на с не было вообще
Jonah_Hex
Для mario.c, как вариант, попробуйте использовать один внешний цикл (для построение пирамиды в высоту), и дополнительно два отдельных вложенных в него цикла (для построения пирамиды в ширину). :)
Masha
  • Masha
  • 0
  • Комментарий отредактирован 2016-07-27 17:46:13 пользователем Masha
Если опыта нет вообще, это норм=).Не бойтесь поиграться с разными циклами, как и говорил Jonah_Hex. Уточню только, что в одном из вложенных циклов можно печатать не только "#", но символ пробела =).
В правильных местах он поможет поменять направление пирамидки.
Pex1k
  • Pex1k
  • 0
  • Комментарий отредактирован 2016-07-27 16:18:55 пользователем Pex1k
Здравствуйте. На счет третьего задания.
Сделал цикл, проверяю с помощью команды «check50 2015.fall.pset1.greedy greedy.c». Все верно, но для числа 4.2 выводится неточный ответ (должен быть 18, а у меня 22). Стал разбираться из-за чего. После того, как я из долларов (4.2) перевожу в центы, должно быть 420 центов, но почему-то именно данное число (я проверял) меняется на 419. Вот кусочек, где я меняю из долларов в центы. x — центы.
Masha
  • Masha
  • +1
  • Комментарий отредактирован 2016-07-27 23:24:46 пользователем Masha
Это из-за особенностей float-чисел в Cи. Умножив на 100 вы надеетесь получить целое число, большее в 100 раз, а так не получается. Воспользуйтесь функцией округления round, чтобы получить нужно целое. Вот её описание: cs50.harvard.edu/resources/cppreference.com/stdmath/round.html.

по идее должно помочь. Если что-то неясно, пишите, я уточню.
Pex1k
  • Pex1k
  • +1
  • Комментарий отредактирован 2016-07-27 18:48:06 пользователем Pex1k
Извините, не могу точно понять. Как до меня дошло, функция round округляет x до до ближайшего целого числа. В каком случае, вы имеете в виду, его использовать? Вы говорите, что умножив на 100 я не получаю целого, но я получаю, только в случае 4.2 оно почему становится 419. Если я использую round в момент того, как запрашиваю число от пользователя, то оно будет округляться (допустим, 4.2 округлится до 4; 0.41 до 0), а это ведь неверно.

P.S. Но благодаря вашему комментарию, заметил, что если вместо float использовать double, то программа работает точно. Но все равно тот момент мне непонятен.
Masha
  • Masha
  • 0
  • Комментарий отредактирован 2016-07-27 23:14:56 пользователем Masha
Тот момент связан именно с реализацией float. Да, дабл здесь применять логичнее, но в курсе намерено ввели условие вводить доллары через float, чтобы дать понять его неточную структуру =). 32 бита мало таким числам, поэтому ошибки такого плана вкрадываются очень часто:
Мы вводим 1.24, а компилятор видит что-то вроде 1.249999946, и не округлив, мы теряем цент.
я делала так: int toCents (float amount)
{
return round(100*amount);
}
clinch
коллеги, ни к чему такие сложности, просто при переводе в центы умножайте значение не на 100 а на 1000, т.е. 4.2 * 1000 = 4200, учитывая, как бы еще тысячные доли, а потом разделите на 10, 4200 / 10 = 420. Так всегда получится перевести из доллоров в центы с учетом округления типа данных float. А далее уже переводите из float в int.
Masha
Вы правы, просто в лекции рекомендуют воспользоваться round =).
mrserfr
  • mrserfr
  • 0
  • Комментарий отредактирован 2016-07-27 19:26:18 пользователем mrserfr
нельзя для подсчете денег использовать числа с плавающей точкой, никогда

я не знаю, что там по заданию, но старайтесь считать все в центах и пользоваться сдвигом
Masha
В условии просили вводить в долларах, а затем переводить в целые числа. Специально, чтобы возникло это непонятное место с float.
Tigran
  • Tigran
  • 0
  • Комментарий отредактирован 2016-07-29 00:52:16 пользователем Tigran
Фуф, доделал Марио) Правда, прежде чем начать делать пирамидку, убил минут 30 на ту самую игру :)
Сначала тоже делал с помощью 2 циклов, расставления пробелов и т.д., потом:
1. нашел интересную функцию, «не имеюющую аналогов в мире»™ — strncat(s1, s2, i) — это позволило избавиться от 1 цикла.
2. нашел классную фишку в printf — знак *
3. минут 20 промурыжился с ошибкой Segmentation fault. Оказалось, что в C нелья просто так взять и конкатенировать строки, как в джаве, злобный компилятор не даст ни грамма лишней памяти :) Решилось через объявление максимального размера при инициализации переменной — char string[40] = "##";

В общем, что-то мне все это напоминает… задачка на 5 строк, а времени 2 часа :) Где-то я все это уже видел…
nyamkas
Как получить оценки?, при попытке перейти на CS50 Submit пишет:
403 You don't have permission to do that!
Tigran
Скорее всего, оценки можно получить, только буду студентом Гарварда, или закупив раз два и три
Есть кто-то на опыте, можете немного прояснить?
skalapendro
У этого курса на edx есть дедлайны? А то я с английским пока не очень…
Masha
Вы можете смотреть переведенные лекции и делать задачи по переведенным задачникам. И проверь задания командой check50. Проверка на edx, по сути, делает то же самое (проводит тесты по основным параметрам, и пишет, все ли пройдены или какой-то провален), просто фиксирует все результаты. Так что если вам важно именно научиться, а не оценки получать, то у вас всё для этого есть, и английский нужен минимально=).

На edx дедлайн до декабря примерно. Потом будет тот же курс, но в редакции следующего года.
khayrulintd
То есть после декабря возможно будут изменены задания и пропадет автопроверка на edx?
zeffir4ik
Ку всем!) А кто-нить делал задачи из «хакерского» задачника? Конкретно интересует задача про номера кредиток. Задайте направление. Как для начала в ней реализовать вычленение каждой второй цифры? Ведь я так понимаю пользователь должен ввести все цифры разом и мы должны записать это в единую переменную long? Или я куда-то не туда смотрю?
EvIv
Попробуй представить сперва в виде массива символов
zeffir4ik
Я, признаться думал об этом. Но вот проблемма в том что по заданию советую использовать GetLongLong
But do not assume that the user’s input will fit in an int! Best to use GetLongLong from CS50’s library to get users' input.
То есть ввод осуществить в одну переменную типа лонг. И второй подводный камень для меня тут это возможность ввести последовательность чисел в массив, так, чтобы каждое из них стало отдельным его элементом, не используя при этом Enter. То есть что бы ввод выглядел как: 1948718473, а не как:
1
2
3
4

н
EvIv
Можно еще разобрать длинное число по цифрам, деля число на десять. То есть в цикле делишь нацело на десять, берешь остаток, запоминаешь. Результат деления снова делишь на десять, остаток снова запоминаешь и так далее, пока цифры не кончатся. Так у тебя соберутся все цифры числа в обратном порядке.
zeffir4ik
Отличная подсказка. Думаю Так и буду реализовыать. Кстати очень логичное решение в рамках курса, потому что подобный метод нужен и для вычисления количества монет в задачке про сдачу))
sibkedr
Я сделал. Без использования массивов (а я пока и не умею), программа вышла на 100 строк.
zeffir4ik
Поверь, использование массивов не облегчает сильно жизнь((( У меня программа будет больше 150 строк ;) А как ты не используя массивы делал?
sibkedr
Ну как, все 16 переменных руками прописывал от n1 до n16.
Как решишь, оставь почту, могу поделиться решением
sibkedr
А, тут можно тоже в личку писать без почты
zeffir4ik
И снова всем привет!
Возвращаюсь к своим баранам. Моя проверка кредиток работает не правильно и я не могу понять где ошибка. Вернее я, по всей видимости, не правильно понимаю как должен работать алгоритм. Например 4111111111111111 должно определятся как VISA. Ок. Как это вижу я (и собственно как реализован мой алгоритм)
1) Берем все вторые числа и умножаем каждое на 2 ( 1*2=2, 1*2=2, 1*2=2, 1*2=2, 1*2=2, 1*2=2, 1*2=2, 1*2=2)
2) Складываем все полученные числа (если число бошьше 10 то его разбираем по разрядно и сначала складываем то чтополучилось (напр. 15 = 1 + 5 + 6)). Для нашего условия (2+2+2+2+2+2+2+2 = 16)
3) Складываем все нечетные элементы первоначального числа (4+1+1+1+1+1+1+1 = 11)
4) Складываем результаты двух сложений (16 + 11 = 27)
5) Если результат делится на 10 без остатка — значит это валидная VISA (в нашем примере)

НО 27 никак не делится на 10 без остатка. То есть одно из двух: либо это не валидная ВИЗА, либо я не правильно понимаю алгоритм.

Подскажите кто поумнее, а?
sibkedr
Это из-за трудностей перевода. Сам напоролся на эти грабли. Часа 2 не мог понять что не так. Потом нашел описание алгоритма Луна на русском. Каждая вторая цифра с конца берется, т.е. отсчет справа на лево. В вашем примере 4 надо умножать на 2 (заменит одну 1 на 4 среди тех чисел которые умножаются, т.е. среди четных, и заменить 4 на 1 среди тех что не умножаются.
Ohr
  • Ohr
  • 0
  • Комментарий отредактирован 2016-09-01 05:51:05 пользователем Ohr
Всем привет!
Подскажите что за бред почему компилятор матюкая меня, говорит что это выражение
while (1 < h < 24);

может вернуть только
true
?
zeffir4ik
Как я понимаю, тебе стоит реализовывать вот так

while ((h>1)&&(h<24))


Опять же на уровне моего понимания, компилятор не может одновременно учитывать два условия, поэтому надо разбивать на шаги и объединять их логическими операциями типа И(&&) ИЛИ (||) НЕ(!). Пошукай в сети на эту тему
Ohr
Пробовал, не работает. При таких условиях он компилирует нормально, но принимает любые числа
zeffir4ik
Тебе надо чтобы h было в диапазоне от 1 до 24, так? Просто вопрос для чего эта проверка. При таком условии цикл будет отрабатываться пока твое h в этом диапозоне. Покажи сам цикл тут и для чего он тебе. Может смогу подсказать))
Ohr
  • Ohr
  • 0
  • Комментарий отредактирован 2016-09-01 08:47:58 пользователем Ohr
Да именно так, от 1 до 24. Цикл выглядит так:
do {printf("Height: ");
       h = GetInt();
      }
    while ((24 > h) && (h > 0));

По условию задачи после введения числа его нужно проверить- оно должно быть от 0 до 23
З.Ы.(я знаю что до этого мы рассматривали от 2 до 23, это не важно)
EvIv
Первое число он тут примет любое. А второе и следующие будет спрашивать только при выполнении условия
EvIv
Используй while а не do while
Ohr
На сколько я понимаю, цикл while будет просто проверять введенные условия, и не выполняться в случае ошибки, а мне нужно что бы он сначала принял проверил, и в случае не верного ответа предложил ввести данные еще раз.
EvIv
do {
} while (условие)
по-русски это «сделай, проверь, продолжай делать если условие истинно»
while (условие) {
}
по-русски значит «делай пока условие истинно»

Вы на каком уровне JavaRush? Как выполняли задачи?
Ohr
Причем тут уровень?
Вы мне пытаетесь доказать то что я и так знаю, он должен СНАЧАЛА выполнить условие, потом проверить на правильность, (тут я конечно не много запутался) и в случае ВЫПОЛНЕНИЯ условия повторить, если же условие не выполнилось, закончить цикл.
Суть отсюда не меняется, Сначала условие, потом проверка!
EvIv
«выполнить условие» — условием здесь вы называете те действия что между {}? Если да, то верно (только терминология странная).
Давайте по шагам ваш код проверим:
Спросили высоту. Записали в h ответ пользователя. Например, 10.
Проверили: 24 > 10 — верно, 10 > 0 — тоже верно. Поэтому повторяем действия. Спросили высоту. Записали в h ответ, например, -5. Проверили: 24 > -5 — верно, -5 > 0 — не верно. Вышли из цикла.
Именно так работает ваша программа сейчас?
Ohr
Спасибо, я понял свою ошибку, правда чуть голова не лопнула)) Он не может проверить два не верных значения, после первого не верного значения он оканчивает цикл, и число присваивается переменной.
zeffir4ik
По условию задачи вы должны
1. получить некоторое число от пользователя
2. проверить находится ли оно в заданном диапазоне
3а. если да то продолжить выполнения задачи с этим числом
3б. если нет, то выдать ошибку/запросить новое число и проверить его.

Очень помогает в решении разбивать задачи на отдельные сегменты и делать все в строгом соответствии с поставленной задачей.

Надеюсь, что хоть в чем-то смог помочь))
Ohr
В принципе, само решение не сложное, просто я не совсем разобрался с do while сначала, но теперь я надеюсь я его постиг в полном объеме))
zeffir4ik
Позвольте попробовать мне.

1) Цикл типа
do
{
некоторые операции;
}
while (условие при котором повторяется цикл);

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

2) Цикл типа
while(условие)
{
некоторые операции;
}

Работает несколько иначе. В нем условие проверяется перед выполнением цикла. Если оно истинно, то выполняются операции внутри фигурных скобок (тело цикла). Если же при первой же проверке условие не будет соответствовать истине, то данный цикл вообще никогда не будет выполнять свое тело.
Ohr
Все верно, по этому я и хотел запихнуть в do {} while, потому что мне нужен сначала цикл, а потом проверка.
Ohr
К стати, я не вижу задач из хакерского задачника, не подскажите где вы их нашли?
zeffir4ik
Вот тут лежит официальный курс cs50

Правда он полностью на английском. Я прохожу его. Там даже за отдельную плату можно получить сертификат, что прошли Гарвардский курс))
Ohr
Спасибо
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.