Перейти к содержанию
Авторизация  
Antonshka

С++ задание

Рекомендуемые сообщения

Задание из книги Лафоре

Спойлер

При помощи цикла 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
#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);
}

Мой вариант. Затрачено где-то минуты три ))

 

image.png

 

image.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, согласно заданию, пирамида должна быть выравнена по правому краю. Также с каждой новой линией количество символов '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;}

 

 

 

Результат с пробелом

Спойлер

6551aae93ddf.jpg

Результат с '0' вместо пробела

Спойлер

bf9a32be96a1.jpg

Как видно из последнего изображения, пирамида должна быть зеркальной, должна начинаться от левого края, должна выравниваться по правому краю, должна иметь 20 строчек.

'0' - здесь просто для наглядности что пирамида зеркальная и что начинается от левого края.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется, подобные задания бесполезные для практического применения. Не могу даже придумать, где бы подобный алгоритм/опыт пригодился. 

 

Спойлер

image.thumb.png.1928a077c075ae18e707126eb246dea4.png

image.png.7a9b8754abebe26045e2adff7052ab46.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
1 час назад, partoftheworlD сказал:

 

  Показать контент

image.thumb.png.1928a077c075ae18e707126eb246dea4.png

image.png.7a9b8754abebe26045e2adff7052ab46.png

 

Интересный вариант! Более простой чем у меня.

Наверно это от того, что я не использовал string(). Впрочем немудрено - ведь до string() я ещё не дошел.

 

1 час назад, partoftheworlD сказал:

Мне кажется, подобные задания бесполезные для практического применения. Не могу даже придумать, где бы подобный алгоритм/опыт пригодился.

Понял твою точку зрения. Возможно действительно так.

 

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

 

P.S. Написать без использования string() смог бы?

Изменено пользователем Antonshka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
29 минут назад, Antonshka сказал:

P.S. Написать без использования string() смог бы?

Очень странно писать на C++ и не использовать std::string :) Это больше в алгоритмы тогда.

 

Очень советую начинать с вот этого прекрасного курса, ребята рассказывают вполне современный C++: https://www.coursera.org/specializations/c-plus-plus-modern-development

А дальше время и cppreference.com.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
3 минуты назад, srg91 сказал:

Очень странно писать на C++ и не использовать std::string :) Это больше в алгоритмы тогда.

 

Конечно странно.

Просто в книге Лафоре, это задание предваряет обьяснение std::string. Потому читающий не имеет возможности использовать такой метод. Отсюда и вопрос.

А курсы - по отзывам я понял, что они равносильны самостоятельному обучению. Разница лишь в том, что на курсах даётся материал более правильно последовательный. Но за совет спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
51 минуту назад, Antonshka сказал:

P.S. Написать без использования string() смог бы?

 

Конечно, но зачем лишние костыли, когда спецификация позволяет?

 

image.thumb.png.847140e5dd89db86488e5968254d2751.png

 

По мне, так это какие-то жесткие и не здоровые извращения.😄

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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;
}

 

 

 

Работает исправно, но печатает со второй строки. По задумке нужно с первой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
10 минут назад, srg91 сказал:

но кажется у меня получилось чуть лаконичнее

Лаконичней это как в Python, все остальное это изврат.😄

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
26 минут назад, Antonshka сказал:

Работает исправно, но печатает со второй строки. По задумке нужно с первой.

 

Да, забавно, я и не заметил. Но похоже лучше уже не сделаю, я очень плох в алгоритмике )

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В 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?

 

Изменено пользователем Antonshka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сегодня начал читать главу "функции". Возник вопрос.

@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) {
}

 

Больше всего мне интересно почему у тебя в объявлении функции указан не только тип, но и имя аргумента.

Спрашиваю для того, чтобы понять как на самом деле нужно объявлять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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;}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
1 час назад, Antonshka сказал:

Вариант решения задания без for, while, do, recursive function, string()

GOTO это тот же jmp label(цикл) и считается дурным тоном использовать его.

  • Понравилось 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
11 минут назад, partoftheworlD сказал:

GOTO это тот же jmp label(цикл) и считает дурным тоном использовать его.

Порой он полезен.

 

Кстати, как оказалось в оригинале книги пирамида не выравнивается по правому краю, а имеет вид -

           x

         xxx

       xxxxx

 

У тебя правда она получилась немного кривоватая, наверно это от того, что разница между количеством "x" не 2 а 1..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
1 час назад, Antonshka сказал:

Порой он полезен.

Как говорилось в одной книге, кажется Страуструпа. "Если есть смысл в использовании goto, то стоит задуматься о том, чтобы переписать код"
Проблемы с использованием goto еще обсуждались в 1968 году, т.е да он как бы не плох, но вреда от него больше, чем пользы, особенно если это крупный проект.

 

your slow connection sucks, get a faster one to see this image

 

1 час назад, Antonshka сказал:

У тебя правда она получилась немного кривоватая

Ну я "программист", а не художник, пусть красивостями другие занимаются.😄

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
7 часов назад, Antonshka сказал:

Больше всего мне интересно почему у тебя в объявлении функции указан не только тип, но и имя аргумента.

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

 

6 часов назад, Antonshka сказал:

goto l1;

Зло злейшее и никогда так не делай больше.

 

7 часов назад, Antonshka сказал:

DrawLine(20);

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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 для прыжка назад.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного лучше так.

 

Спойлер

#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. Т.к. это лучшее объяснение как работать с языком.


Цитата

И тут мы поняли, что многие не знают как правильно пользоваться этой функцией. Так вот, правильное использование — не пользоваться.

 


 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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 я и использовал для этого.

 

Изменено пользователем Antonshka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
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 чего либо", например в середине функции, то значит ли это то, что функция на этом самом месте немедленно прекратит свою работу, вернув результат, несмотря на то, что другая часть/части этой функции также желали быть исполненными?

Именно так.

 


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

×

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.