Antonshka Опубликовано 3 апреля, 2019 Поделиться Опубликовано 3 апреля, 2019 Задание из книги Лафоре Спойлер При помощи цикла for изобразите на экране пирамиду из символов 'X'. Верхняя часть пирамиды должна выглядеть следующим образом: х ххх ххххх ххххххх ххххххххх Вся пирамида должна быть высотой не 5 линий, как изображено здесь, а 20 линий. Одним из способов ее построения может служить использование двух вложенных циклов, из которых внутренний будет заниматься печатанием символов 'X' и пробелов, а другой осуществлять переход на одну строку вниз. Кто-нибудь пробовал его решить? У меня заняло это несколько часов. Непросто мне она далась. Скрипт Спойлер #include "pch.h" //precomile #include <iostream> //cout, cin using namespace std; int main(){ int level; char x,y; cout << "Enter char 1: "; cin >> x; cout << "Enter char 2: "; cin >> y; cout << "Enter level: "; cin >> level; for (int i = level; i < (level/2+1) * level; i++){ if (i != level && i % level == 0) cout << endl; i % level >= level - (i / level + (i / level - 1)) ? cout << x : cout << y;} return 0;} Если кто-то из вас решал эту задачу, я с удовольствием посмотрел бы на ваши методы. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 Спойлер Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 #include <string> #include <iostream> using namespace std; void DrawLine(int tabs); int main() { int tabs = 20; DrawLine(tabs); return 0; } void DrawLine(int tabs) { if (tabs < 0) return; cout << string(tabs, ' ') << string(20 - tabs, 'x') << endl; DrawLine(--tabs); } Мой вариант. Затрачено где-то минуты три )) Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 Оу, так надо было выравнивать по одной стороне. Черт, я думал типичное задание с елочкой. Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 4 апреля, 2019 Автор Поделиться Опубликовано 4 апреля, 2019 Да, согласно заданию, пирамида должна быть выравнена по правому краю. Также с каждой новой линией количество символов 'x' должно увеличиваться не на 1, но таким образом х ххх ххххх Значит пока у вас нет решения. Вот еще чуть более изощренный вариант решения с моей стороны Скрипт Спойлер #include "pch.h" #include <iostream> using namespace std; int main(){ for (int l = 20 * 2, i = l; i < (l /2+1) * l; i++){ if (i != l && !(i % l)) cout << endl; i % l >= l - (i / l + (i / l - 1)) ? cout << 'x' : cout << ' ';}cout << "\r\n"; return 0;} Результат с пробелом Спойлер Результат с '0' вместо пробела Спойлер Как видно из последнего изображения, пирамида должна быть зеркальной, должна начинаться от левого края, должна выравниваться по правому краю, должна иметь 20 строчек. '0' - здесь просто для наглядности что пирамида зеркальная и что начинается от левого края. Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 Мне кажется, подобные задания бесполезные для практического применения. Не могу даже придумать, где бы подобный алгоритм/опыт пригодился. Спойлер Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 4 апреля, 2019 Автор Поделиться Опубликовано 4 апреля, 2019 (изменено) 1 час назад, partoftheworlD сказал: Показать контент Интересный вариант! Более простой чем у меня. Наверно это от того, что я не использовал string(). Впрочем немудрено - ведь до string() я ещё не дошел. 1 час назад, partoftheworlD сказал: Мне кажется, подобные задания бесполезные для практического применения. Не могу даже придумать, где бы подобный алгоритм/опыт пригодился. Понял твою точку зрения. Возможно действительно так. Мне думается это задание на запоминание правил написания кода, на запоминание употребляемых выражений, - словом для практики, также и на развитие мышления. P.S. Написать без использования string() смог бы? Изменено 4 апреля, 2019 пользователем Antonshka Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 29 минут назад, Antonshka сказал: P.S. Написать без использования string() смог бы? Очень странно писать на C++ и не использовать std::string Это больше в алгоритмы тогда. Очень советую начинать с вот этого прекрасного курса, ребята рассказывают вполне современный C++: https://www.coursera.org/specializations/c-plus-plus-modern-development А дальше время и cppreference.com. Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 4 апреля, 2019 Автор Поделиться Опубликовано 4 апреля, 2019 3 минуты назад, srg91 сказал: Очень странно писать на C++ и не использовать std::string Это больше в алгоритмы тогда. Конечно странно. Просто в книге Лафоре, это задание предваряет обьяснение std::string. Потому читающий не имеет возможности использовать такой метод. Отсюда и вопрос. А курсы - по отзывам я понял, что они равносильны самостоятельному обучению. Разница лишь в том, что на курсах даётся материал более правильно последовательный. Но за совет спасибо. Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 51 минуту назад, Antonshka сказал: P.S. Написать без использования string() смог бы? Конечно, но зачем лишние костыли, когда спецификация позволяет? По мне, так это какие-то жесткие и не здоровые извращения.? Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 40 минут назад, partoftheworlD сказал: По мне, так это какие-то жесткие и не здоровые извращения.? А давайте ещё в один цикл ? А, не увидел что подобное решение уже есть (но кажется у меня получилось чуть лаконичнее) Спойлер #include <iostream> int main() { unsigned int height = 20, width = height * 2 - 1; unsigned char space = ' ', letter = 'X'; for (unsigned int i = 1; i <= width * height; i++) { std::cout << ((i % width <= width - (i / width) * 2) ? space : letter); if (!(i % width)) std::cout << std::endl; } return 0; } Спойлер X XXX XXXXX XXXXXXX XXXXXXXXX XXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 43 минуты назад, Antonshka сказал: Но за совет спасибо. После каждой темы ещё дополнительно тестовое задание с проверкой автоматической системой и в конце - курсовой. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 4 апреля, 2019 Автор Поделиться Опубликовано 4 апреля, 2019 8 минут назад, srg91 сказал: А давайте ещё в один цикл ? Скрыть контент #include <iostream> int main() { unsigned int height = 20, width = height * 2 - 1; unsigned char space = ' ', letter = 'X'; for (unsigned int i = 1; i <= width * height; i++) { std::cout << ((i % width <= width - (i / width) * 2) ? space : letter); if (!(i % width)) std::cout << std::endl; } return 0; } Работает исправно, но печатает со второй строки. По задумке нужно с первой. Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 10 минут назад, srg91 сказал: но кажется у меня получилось чуть лаконичнее Лаконичней это как в Python, все остальное это изврат.? Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 апреля, 2019 Поделиться Опубликовано 4 апреля, 2019 26 минут назад, Antonshka сказал: Работает исправно, но печатает со второй строки. По задумке нужно с первой. Да, забавно, я и не заметил. Но похоже лучше уже не сделаю, я очень плох в алгоритмике ) Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 6 апреля, 2019 Автор Поделиться Опубликовано 6 апреля, 2019 (изменено) В 03.04.2019 в 23:58, Antonshka сказал: несколько часов В 04.04.2019 в 09:00, Xipho сказал: где-то минуты три В 04.04.2019 в 14:29, partoftheworlD сказал: Конечно В 04.04.2019 в 15:04, srg91 сказал: А давайте ещё в один цикл Кто-нибудь сможет решить задание вообще без использования for, while, do, recursive function, string(), но с тем же cout? Изменено 6 апреля, 2019 пользователем Antonshka Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 6 апреля, 2019 Автор Поделиться Опубликовано 6 апреля, 2019 Сегодня начал читать главу "функции". Возник вопрос. @Xipho , почему в твоём скрипте код имеет такой вид Спойлер void DrawLine(int tabs); int main() { int tabs = 20; DrawLine(tabs); return 0; } void DrawLine(int tabs) { } вместо такого Спойлер void DrawLine(int); // без tabs int main() { int tabs = 20; DrawLine(tabs); return 0; } void DrawLine(int tabs) { } или такого? Спойлер void DrawLine(int); // без tabs int main() { // без int tabs DrawLine(20); return 0; } void DrawLine(int tabs) { } В книге автор пишет что объявление (прототип) функции должно содержать возвращаемый тип функции "void", имя функции и типы аргументов функции void DrawLine(int); а определение функции должно содержать возвращаемый тип функции "void", имя функции, типы и имена а̶р̶г̶у̶м̶е̶н̶т̶о̶в параметров функции в том же порядке. void DrawLine(int tabs) { } Больше всего мне интересно почему у тебя в объявлении функции указан не только тип, но и имя аргумента. Спрашиваю для того, чтобы понять как на самом деле нужно объявлять. Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 6 апреля, 2019 Автор Поделиться Опубликовано 6 апреля, 2019 1 час назад, Antonshka сказал: Больше всего мне интересно почему у тебя в объявлении функции указан не только тип, но и имя аргумента. Наверно нашёл ответ в интернете - "Имена аргументов, при объявления прототипов являются необязательными." Вариант решения задания без for, while, do, recursive function, string(), но с тем же cout Спойлер #include "pch.h" #include <iostream> using namespace std; int main(){ int l = 20 * 2, i = l; l1: if (i < (l / 2 + 1) * l){ if (i != l && !(i % l)) cout << endl; i % l >= l - (i / l + (i / l - 1)) ? cout << 'x' : cout << ' '; ++i; goto l1;} cout << "\r\n"; return 0;} Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 6 апреля, 2019 Поделиться Опубликовано 6 апреля, 2019 1 час назад, Antonshka сказал: Вариант решения задания без for, while, do, recursive function, string() GOTO это тот же jmp label(цикл) и считается дурным тоном использовать его. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 6 апреля, 2019 Автор Поделиться Опубликовано 6 апреля, 2019 11 минут назад, partoftheworlD сказал: GOTO это тот же jmp label(цикл) и считает дурным тоном использовать его. Порой он полезен. Кстати, как оказалось в оригинале книги пирамида не выравнивается по правому краю, а имеет вид - x xxx xxxxx У тебя правда она получилась немного кривоватая, наверно это от того, что разница между количеством "x" не 2 а 1.. Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 6 апреля, 2019 Поделиться Опубликовано 6 апреля, 2019 1 час назад, Antonshka сказал: Порой он полезен. Как говорилось в одной книге, кажется Страуструпа. "Если есть смысл в использовании goto, то стоит задуматься о том, чтобы переписать код" Проблемы с использованием goto еще обсуждались в 1968 году, т.е да он как бы не плох, но вреда от него больше, чем пользы, особенно если это крупный проект. 1 час назад, Antonshka сказал: У тебя правда она получилась немного кривоватая Ну я "программист", а не художник, пусть красивостями другие занимаются.? Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 6 апреля, 2019 Поделиться Опубликовано 6 апреля, 2019 7 часов назад, Antonshka сказал: Больше всего мне интересно почему у тебя в объявлении функции указан не только тип, но и имя аргумента. Банально привычка - если код разделен на хедеры и cpp файлы, то мне привычнее и в хедере прототип функции читать с именами параметров - так сразу получаешь представление, что это за параметр. По типу не всегда можно понять, за что этот параметр отвечает, а так, как говорится, наглядно, особенно, если используется венгерская нотация 6 часов назад, Antonshka сказал: goto l1; Зло злейшее и никогда так не делай больше. 7 часов назад, Antonshka сказал: DrawLine(20); магические цифры - зло. В таком малом коде ничего страшного, разумеется, но если кода много - лучше вынести в отдельную переменную, или даже дефайн (если константа). Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 6 апреля, 2019 Автор Поделиться Опубликовано 6 апреля, 2019 31 минуту назад, Xipho сказал: ... Понятно, буду знать. Что если использовать "goto" в такой ситуации? Спойлер #include "pch.h" #include <iostream> using namespace std; int main() { int a, b, c, d; char dummy = 'a'; char method = 'a'; char stop = 'y'; while (stop != 'n') { cout << "enter first fraction (a / b): "; cin >> a >> dummy >> b; cout << "enter second fraction (c / d): "; cin >> c >> dummy >> d; cout << "method: "; cin >> method; switch (method) { case '+':cout << a * d + b * c << " / " << b * d << endl; break; case '-':cout << a * d - b * c << " / " << b * d << endl; break; case '*':cout << a * c << " / " << b * d << endl; break; case '/':cout << a * d << " / " << b * c << endl; break; default: cout << "wrong method" << endl; } metka: cout << "calculate again? (y\\n): "; cin >> stop; if (stop == 'y' || stop == 'n') if (stop == 'n') break; else continue; else cout << "wrong answer" << endl; goto metka; } return 0; } Этот скрипт на задание из книги. Первое что мне пришло в голову, это использовать goto для прыжка назад. Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 6 апреля, 2019 Поделиться Опубликовано 6 апреля, 2019 Немного лучше так. Спойлер #include <iostream> using namespace std; void header(char dummy, int &a, int &b, int &c, int &d) { cout << "enter first fraction (a / b): "; cin >> a >> dummy >> b; cout << "enter second fraction (c / d): "; cin >> c >> dummy >> d; cout << "method: "; } bool calculate(char m, int &a, int &b, int &c, int &d) { switch (m) { case '+':cout << a * d + b * c << " / " << b * d << endl; break; case '-':cout << a * d - b * c << " / " << b * d << endl; break; case '*':cout << a * c << " / " << b * d << endl; break; case '/':cout << a * d << " / " << b * c << endl; break; default : cout << "wrong method" << endl; return 0; } return 1; } int main() { int a, b, c, d; char dummy = 'a'; char method = 'a'; char stop = 'y'; while (stop != 'n') { header(dummy, a, b, c, d); cin >> method; if(calculate(method, a, b, c, d)) { cout << "calculate again? (y\\n): "; cin >> stop; switch(stop) { case 'y': continue; case 'n': break; default : cout << "wrong answer" << endl; return 0; } } else { break; } } return 0; } Немного офтопа о cpp. Т.к. это лучшее объяснение как работать с языком. Цитата И тут мы поняли, что многие не знают как правильно пользоваться этой функцией. Так вот, правильное использование — не пользоваться. Ссылка на комментарий Поделиться на другие сайты Поделиться
Antonshka Опубликовано 7 апреля, 2019 Автор Поделиться Опубликовано 7 апреля, 2019 (изменено) 10 часов назад, partoftheworlD сказал: Немного лучше так. Скрыть контент #include <iostream> using namespace std; void header(char dummy, int &a, int &b, int &c, int &d) { cout << "enter first fraction (a / b): "; cin >> a >> dummy >> b; cout << "enter second fraction (c / d): "; cin >> c >> dummy >> d; cout << "method: "; } bool calculate(char m, int &a, int &b, int &c, int &d) { switch (m) { case '+':cout << a * d + b * c << " / " << b * d << endl; break; case '-':cout << a * d - b * c << " / " << b * d << endl; break; case '*':cout << a * c << " / " << b * d << endl; break; case '/':cout << a * d << " / " << b * c << endl; break; default : cout << "wrong method" << endl; return 0; } return 1; } int main() { int a, b, c, d; char dummy = 'a'; char method = 'a'; char stop = 'y'; while (stop != 'n') { header(dummy, a, b, c, d); cin >> method; if(calculate(method, a, b, c, d)) { cout << "calculate again? (y\\n): "; cin >> stop; switch(stop) { case 'y': continue; case 'n': break; default : cout << "wrong answer" << endl; return 0; } } else { break; } } return 0; } Спасибо, интересный способ. Единственное что мне пока не понятно - Спойлер if (calculate(method, a, b, c, d)) { cout << "calculate again? (y\\n): "; cin >> stop; switch (stop) { case 'y': continue; case 'n': break; default: cout << "wrong answer" << endl; return 0; //как влияет return 0 на программу? } } Функция calculate и оператор switch в определенной ситуации могут вернуть - return 0. Если calculate вернет 0, то условие "if (calculate(method, a, b, c, d))" - будет ложно, и сработает brear для цикла while (stop != 'n'), - этот момент понятен. Не понятно почему while (stop != 'n') зависит от этого возвращаемого нуля - "default: cout << "wrong answer" << endl; return 0;". Ведь в условии выполнения while только значение переменной stop. Или этот 0 возвращается для int main()? Если 0 для while , то верно ли то, что любой цикл, будь то for, while, do, можно завершить не только изменив условие цикла или выполнив break, но и вернув ему (циклу) 0? А значит можно записать код так? switch (stop) { case 'y': continue; case 'n': return 0; //case 'n': break; default: cout << "wrong answer" << endl; return 0; } А если 0 из "default: cout << "wrong answer" << endl; return 0;" для int main(), то значит ли это то, что return 0 минует все множество вложенных циклов, и всегда предназначен для текущей конкретной фунции (для возврата текущей функцией в вызывающий её оператор этого нуля (или может не 0, а чего другого). Если при выполнении функции случится выполниться методу "return чего либо", например в середине функции, то значит ли это то, что функция на этом самом месте немедленно прекратит свою работу, вернув результат, несмотря на то, что другая часть/части этой функции также желали быть исполненными? Ответ на эти вопросы я возможно ещё встречу в книге, но мне уже сейчас хочется его узнать. P.S. если ввести не 'y' и не 'n' программа завершится. Но что если нужно снова спросить о желании расчёта? Ведь GOTO я и использовал для этого. Изменено 7 апреля, 2019 пользователем Antonshka Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 7 апреля, 2019 Поделиться Опубликовано 7 апреля, 2019 3 часа назад, Antonshka сказал: Если calculate вернет 0, то условие "if (calculate(method, a, b, c, d))" - будет ложно, и сработает brear для цикла while (stop != 'n'), - этот момент понятен. Не понятно почему while (stop != 'n') зависит от этого возвращаемого нуля - "default: cout << "wrong answer" << endl; return 0;". Ведь в условии выполнения while только значение переменной stop. Или этот 0 возвращается для int main()? calculate возвращает состояние 1 если посчиталось, 0 при wrong method и выходит из calculate, ведь какой смысл если вычисления не удались выдавать cout << "calculate again? (y\\n): "; 3 часа назад, Antonshka сказал: default: cout << "wrong answer" << endl; return 0; //как влияет return 0 на программу? выход не из цикла, а сразу из main для завершения программы. Не лучший способ, но за ошибки надо платить, хотя бы выходом из программы.? 3 часа назад, Antonshka сказал: Но что если нужно снова спросить о желании расчёта? Ну что ж, придется быть внимательным и вводить всегда "y". 3 часа назад, Antonshka сказал: Если 0 для while , то верно ли то, что любой цикл, будь то for, while, do, можно завершить не только изменив условие цикла или выполнив break, но и вернув ему (циклу) 0? А значит можно записать код так? Не, break выходит из цикла/свича, return выходит из метода. т.е break используется, когда не надо завершать программу и продолжать выполнение/повторение. return используется, когда надо завершить выполнение метода. 3 часа назад, Antonshka сказал: Если при выполнении функции случится выполниться методу "return чего либо", например в середине функции, то значит ли это то, что функция на этом самом месте немедленно прекратит свою работу, вернув результат, несмотря на то, что другая часть/части этой функции также желали быть исполненными? Именно так. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения