LINUX.ORG.RU

Помогите с простенькой программой на C++


0

1

Здавствуйте, изучаю потихоньку C++ по книге Бьерна Страуструпа. В конце каждой главы есть небольшие задания, в частности есть задачка на угадывание целого числа от 1 до 100 за максимум 7 попыток. Набрасал следующий код:

#include <iostream>
#include <string>
#include <cmath>
#include <vector>

double round(double number)
{
        return int(number + .5);
}
int main()
{
        std::vector<double> a(9);
        std::vector<std::string> s(8);
        a[0] = 105; s[0] = "???";
        a[1] = 50;
        std::string c = "???";
        std::cout << "Задумайте любое целое число от '1' до '100' \n" << "Программа будет задавать вопросы, если соглашаетесь введите 'y', иначе 'n'. \n";
        for (int i=0; i < 7; ++i)
            {
/*                      for (int k = 0; k < i+1; ++k)
                          {
                                          if (a[k] == a[i+1])
                                                    {
                                                                 s[i+1]=s[k];
                                                                 c = s[i+1];
                                                                 goto metka2;
                                                    }

                           }
*/
                      std::cout << i+1<<") Задуманное число меньше " << a[i+1] <<"? Ваш ответ: " ;
                      metka1:
                      std::cin >> c;
                      s[i+1] = c;
//                    metka2:
                      double r = a[i] - a[i+1];
                      double m = pow(r,2);
                      double m1 = pow(m,0.5);

                      if (c == "y")  a[i+2] = a[i+1] - m1/2; //*
                      else if (c  == "n") a[i+2] = a[i+1] + m1/2; //*
//                    if (c == "y")  a[i+2] = round(a[i+1] - m1/2);
//                    else if (c  == "n") a[i+2] = round(a[i+1] + m1/2);

                      else goto metka1;
           }

        std::cout << "\nВы задумали число " << round(a[8]) <<"\n"; //*
//      std::cout << "\nВы задумали число " << a[8] <<"\n";
        return 0;
}

Программа работает, но не так как мне хотелось бы, а хочется, чтобы вместо рациональных чисел она выводила целые в вопросах, но фокус с округлением не удался :( (случай если закоментировать строки, которые я обозначил «*», и раскоментировать те, что закоментены в приведённом примере). Что мне нужно изменить, чтобы добиться желаемого результата? Спасибо.

Ответ на: комментарий от Zorn

C++ это же ООП! Могли бы всё зделать объектами и запилить один метод! )

«я хочу написать функцию, которая бы ВСЕ делала!»

AIv ★★★★★
()
Ответ на: комментарий от qnikst

А в Common Lisp круче всех. Там есть throw-catch, который позволяет вам развернуть стек от места вызова throw до catch, для обработок ошибок есть полоностью аналогичный try-catch (или как там в C++?) handler-case, а так же система рестартов, которую больше я нигде не видел

Zorn
()
Ответ на: комментарий от Zorn

так же мимоходом заметили, что их нет в чистом C, про который код.

так или доп условиями костылить, или код в функцию выносить и return делать (а функцию инлайнить) или goto :)

qnikst ★★★★★
()
Ответ на: комментарий от Zorn

подозреваю, что для задач где логично использовать C это минимум оверкил :)

а про яву, я имел ввиду решение с метками: там позволено делать метки на «объявлении» циклов, таким образом можно делать continue/break на вложенных массивах, при этом не городя достаточно дорогие исключения.

qnikst ★★★★★
()
Ответ на: комментарий от user_2190

Вообще то ::abs и std::abs это две совсем разных функции;-)

Про бинарный поиск - куда веселей, когда границы заранее неизвестны, числа вещественные, ответ надо найти с заданной точностью, функционал немонотонен (для чисел вне некоторого неизвестного диапазона отвечают невпопад), а один вопрос занимает от 10 минут до неск часов машинного времени;-)

AIv ★★★★★
()
Ответ на: комментарий от Zorn

Там есть throw-catch, который позволяет вам развернуть стек от места вызова throw до catch,

В питоне так же. А вот рестартов из коробки я не видел... хотя мысль любопытная, надо будет попробовать запилить;-)

AIv ★★★★★
()
Ответ на: комментарий от Zorn

Сказали же уже: исключения вам помогут.

А, ну или так, да. Хотя я где-то читал, что так делать не особо хорошо, там какие-то траблы могут возникнуть. Хотя не помню, с чем это связано.

Zhbert ★★★★★
()
Ответ на: комментарий от AIv

Вообще то ::abs и std::abs это две совсем разных функции;-)

Ну да.

Про бинарный поиск - куда веселей, когда границы заранее неизвестны, числа вещественные, ответ надо найти с заданной точностью, функционал немонотонен (для чисел вне некоторого неизвестного диапазона отвечают невпопад), а один вопрос занимает от 10 минут до неск часов машинного времени;-)

А это в какой области такие задачи?

user_2190
()
Ответ на: комментарий от AIv

return Вам поможет;-)

Это надо отдельную функцию лепить для циклов. А стоит ли оно того? Костыли ж куда как проще, удобней, эстетичней и элегантней...

Zhbert ★★★★★
()
Ответ на: комментарий от jessey

А чем goto плох? Я слышал, что его применение нежелательно, но почему?

Неужели пользователь может загадать дробное число? Иначе, почему промежуточные значения у тебя могут быть дробными?

Почему? Допустим я загадал 87, при выполнении программы я увижу следующее

 
Задумайте любое целое число от '1' до '100' 
Программа будет задавать вопросы, если соглашаетесь введите 'y', иначе 'n'.
1) Задуманное число меньше 50? Ваш ответ: n
2) Задуманное число меньше 77.5? Ваш ответ: n
3) Задуманное число меньше 91.75? Ваш ответ: y
4) Задуманное число меньше 84.875? Ваш ответ: n
5) Задуманное число меньше 88.4375? Ваш ответ: y
6) Задуманное число меньше 86.2188? Ваш ответ: n
7) Задуманное число меньше 87.1094? Ваш ответ: y
Вы задумали число 87
Ведь то, что 87 < 87.1094 сомнений никаких не возникает

hikkikamori
() автор топика
Ответ на: комментарий от Zhbert

опять же костыли хороши при 1-2 вложенных массивах, потом начинается ад, правда это только числодробилках так

qnikst ★★★★★
()
Ответ на: комментарий от user_2190

Ну я так искал сепаратрису в пространстве параметров, отделяющую переход дефлаграции в детонацию от просто дефлаграции (два режима горения). Берем набор параметров и считаем, смотрим есть переход или нету (пошла ударная волна или так все выгорело). В некоторой области есть монотонная зависимость (температура преднагрева больше - переход раньше, меньше - переход позже, надо найти температуру когда переход совсем исчезает). Фигня в том, что границы этой монотонной области неизвестны, а за ее пределами перехода может вообще не быть.

AIv ★★★★★
()
Ответ на: комментарий от hikkikamori

А чем goto плох? Я слышал, что его применение нежелательно, но почему?

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

Почему? Допустим я загадал 87, при выполнении программы я увижу следующее

у тебя 8 шагов не? имхо нужно на 7 шаге уже называть число. При твоём подходе, твоя программа сломается если загадать 50.

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

qnikst ★★★★★
()
Ответ на: комментарий от hikkikamori

А чем goto плох? Я слышал, что его применение нежелательно, но почему?

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

Ведь то, что 87 < 87.1094 сомнений никаких не возникает

Потому что во первых будут нужны лишние итерации, во вторых это учебная задача, и она именно на целые числа;-)

AIv ★★★★★
()
Ответ на: комментарий от hikkikamori

А чем goto плох? Я слышал, что его применение нежелательно, но почему?

Потому что программу можно продумать так, что все переходы будут следовать из каких-то условий. goto хорош только для выхода из многовложенных итерационных конструкций (там, где нет тех же исключений)

Zorn
()
Ответ на: комментарий от AIv

То есть искались параметры, при которых не будет детонации?

Фигня в том, что границы этой монотонной области неизвестны, а за ее пределами перехода может вообще не быть.

И как тогда, линейный поиск этой области?

user_2190
()
Ответ на: комментарий от user_2190

То есть искались параметры, при которых не будет детонации?

Искались параметры, при которых она исчезает при понижении температуры преднагрева. Потому что она исчезает еще и при повышении выше некоторого значения.

И как тогда, линейный поиск этой области?

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

AIv ★★★★★
()
Ответ на: комментарий от qnikst

у тебя 8 шагов не? имхо нужно на 7 шаге уже называть число. При твоём подходе, твоя программа сломается если загадать 50.

Так, но вопросов 7, что и требовалось в задаче. Действительно сломалась когда загадал 50 :(

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

учту, спасибо за наводку :)

hikkikamori
() автор топика
Ответ на: комментарий от AIv
#include <iostream>
using namespace std;

int main() {
	int max = 101;
	int min = 0;

	cout<<"А ну ка загадайте как че нить от 0 до 100!"<<endl;
	for(int i = 0; i < 7; i++) {
		char c;

		cout << i << "оно СТРОГО МЕНЬШЕ чем "<< (max+min)/2 <<" [y/любая другая фигня]?" << endl;
		cin >> c;
		if(c == 'y') {
			max = (max+min)/2;
		} else {
			min = (max+min)/2;
		}
		if(max-min <= 1)break;
	}
	cout << "я телепат, Вы задали "<< (max+min)/2 << endl;
}

/thread?

son_of_a_gun
()
Ответ на: комментарий от user_2190

Нет, сходиться к ответу будет только на вещественных числах.

Вот сколько описаний и воплощений этого бессмертного алгоритма встречал, ни разу кроме целых чисел ничего не использовалось.

delete83 ★★
()
Ответ на: комментарий от son_of_a_gun

Блин, оказывается всё как просто, а я как всегда всё усложнил :( . Спасибо.

hikkikamori
() автор топика
Ответ на: комментарий от qnikst

Кстати, если в качестве a[0] использовать не 105, а 101, как это сделал Alv то программа не ломается

hikkikamori
() автор топика

Ну, раз уж пошла такая пьянка (много double'ов в int'овой задаче), угадай-ка мне число за 7 шагов, ну знака хотя бы до 4-го.

PS. Подсказываю, я загадал 3.141592654…

Delirium_veritas
()
Ответ на: комментарий от Delirium_veritas

Да ладно, понял я уже, что можно без double

угадай-ка мне число за 7 шагов, ну знака хотя бы до 4-го.

Изначально условия задачи были другие: загаданное число должно быть целым. По крайней мере я доволен, самое главное - уяснил благодаря ЛОРу насколько просто можно решить эту задачу не используя double и массивы, ну и второе, пусть мой код и ужасен тем, что всё усложнил, но зато «математика» работает. Только 2.5 недели как в программировании, а ошибки совершать иногда полезно, т.к. на них учатся :)

hikkikamori
() автор топика
Ответ на: комментарий от hikkikamori

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

delete83 ★★
()

8 пробелов, омг! 2-4 пробела используй, как нормальные белые люди, читать же невозможно.

anonymous
()

Твоя ошибка содержится в первом же предложении:

изучаю потихоньку C++ по книге Бьерна Страуструпа.

начинай с SICP и будет тебе счастье.

ugoday ★★★★★
()
Ответ на: комментарий от Zorn

Из вложенных циклов исключениями выходят только мудаки.©

LamerOk ★★★★★
()
Ответ на: комментарий от anonymous

8 пробелов, омг!

Ужас. 8 пробелов можно заменить одним табом.

2-4 пробела используй, как нормальные белые люди,

Белые люди пользуются табом. Пробелы - для негров.

LamerOk ★★★★★
()
Ответ на: комментарий от Delirium_veritas

Начинать изучать программирование по Кнуту --- это всё равно, что начинать изучать физику с Ландавшица.

ugoday ★★★★★
()
Ответ на: комментарий от delete83

delete83

double m = pow(r,2);
double m1 = pow(m,0.5);

Объясните, ЧТО ЭТО???

это
1. возведение во вторую степень
2. вычисление квадратного корня от п1

drBatty ★★
()
Ответ на: комментарий от LamerOk

При нажатии tab редактор вставляет заранее обозначенное число прообелов. На shift-tab (или бакспейс, если курсор на границе отступа) он это число пробелов удаляет. Надо использовать правильные редакторы, нотепад.ехе сукс.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

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

JackyTreehorn
()
Ответ на: комментарий от PolarFox

Есть достойная альтернатива кроме имакса? ;)

LamerOk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.