[C++] Trójkąt w ramce z gwiazdek

CinU331
Użytkownik
Użytkownik
Posty: 1
Rejestracja: 4 lis 2014, o 18:46
Płeć: Mężczyzna
Lokalizacja: Łódź

[C++] Trójkąt w ramce z gwiazdek

Post autor: CinU331 »

Witam

Mam pewien problem z programem, który po wpisaniu liczby n rysuje trójkąt z gwiazdek i ramkę wokół niego z gwiazdek.
Ma wyglądać tak jak tutaj (liczba n=20)
AU
AU
70212298366869857285.jpg (5.52 KiB) Przejrzano 490 razy
[/url]

Nie mogę sobie poradzić z tą ramką i u mnie niby się tworzy, ale tylko kawałek.
AU
AU
72208568043558440938_thumb.jpg (5.52 KiB) Przejrzano 490 razy
[/url]

Moglibyście zobaczyć co jest źle w kodzie i napisać mi jak go poprawić? Byłbym bardzo wdzięczny.

Kod: Zaznacz cały

#include <cstdio>
#include <iostream>

using namespace std;

int main()
{
    int i,j,n;
    cout<<"Podaj liczbe n "<<endl;
    cin>>n;
    cout<<endl;
   for (int i=1;n>=i;i++)
    {
	for (int j=1;n>=j;j++)
	{
		if(j==1 || j==n || i==1 || i==n) cout << "*";
		else             cout << " ";
	}
	 for(i=1; i<=n; i++)
    {
        for(j=1; j<=n-i; j++)
        {
            cout<<" ";
        };
        for(j=n-i; j<n; j++)
        {
            cout<<" *";
        };
        cout<<endl;
    };
	cout <<"
";
    }
        cout<<endl;
return 0;
}
Awatar użytkownika
Dasio11
Moderator
Moderator
Posty: 10223
Rejestracja: 21 kwie 2009, o 19:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 40 razy
Pomógł: 2361 razy

[C++] Trójkąt w ramce z gwiazdek

Post autor: Dasio11 »

Analiza.

Kod: Zaznacz cały

    for( int i = 1; n >= i; i++ )
    {
        for( int j = 1; n >= j; j++ )
        {
            if( j == 1 || j == n || i == 1 || i == n ) cout << "*";
            else                                       cout << " ";
        }
        ...
1. Najpierw ustawiasz i = 1, a następnie dla j = 1, 2, ..., n wykonujesz zawartość wewnętrznej pętli. Za każdym razem jest i == 1, więc warunek w pętli jest spełniony, czyli narysuje się n gwiazdek.

Kod: Zaznacz cały

        ...
        for( i = 1; i <= n; i++ )
        {
            for( j = 1; j <= n-i; j++ )
            {
                cout << " ";
            }
            for( j = n-i; j < n; j++ )
            {
                cout << " *";
            }
            cout << endl;
        }
        ...
Teraz, dla i = 1, 2, ..., n wypisujesz n-i spacji oraz i+1 gwiazdek poprzedzonych spacją, a następnie znak nowej linii. W rezultacie rysujesz trójkąt w n liniach, tylko że przed pierwszą z nich nie ma znaku nowej linii '\n', więc pierwsza z nich jest zlepiona z n gwiazdkami narysowanymi przez część 1.

Kod: Zaznacz cały

/* 
Początek pętli: 
    for( int i = 1; n >= i; i++ )
    {
*/
        ....
        cout << "\n";
    }
3. (Fragment kodu pomiędzy znakami /* */ jest komentarzem dodanym przeze mnie, żeby było widać, koniec jakiej pętli przedstawia ten kawałek kodu.)
Tutaj wypisujesz jeszcze jeden znak nowej linii. W wyniku działania pętli w części 2 zmienna i ma teraz wartość n+1, więc sterowanie wyskoczy z przedstawionej pętli (mimo, że to pierwszy jej przebieg) i program się zakończy (przedtem wykona jeszcze jedno cout << endl;, którego nie cytuję).


Poprawki.

1. Jak zaznaczyłem w analizie, użyłeś zmiennej i do indeksowania wewnętrznej pętli, podczas gdy ta zmienna służyła już jako zmienna zewnętrznej pętli. To spowodowało nieoczekiwane zachowanie (wyjście z pętli po pierwszym przebiegu), bo wartość i została nadpisana przez tę wewnętrzną pętlę. Dlatego do indeksowania wewnętrznej pętli powinieneś użyć użyć innej zmiennej.

2. Do tego zadania można zastosować zasadniczo dwa podejścia: sekwencyjne lub warunkowe (nazwy wymyślone przeze mnie). Podejście sekwencyjne wyglądałoby tak:

Kod: Zaznacz cały

for( int j = 0; j < 2*n+3; ++j ) cout << "*"; // Rysuj górną część ramki. 
for( int i = 1; i <= n; ++i )
{
    cout << "*"; // Rysuj kawałek lewego boku ramki. 
    
    // Rysuj i-ty wiersz trójkąta. 
    for( int j = 0; j < n-i; ++j ) cout << " ";
    for( int j = n-i; j < n; ++j ) cout << " *";

    // Wypełnij spacjami resztę wiersza, żeby dojść do prawego boku ramki. 
    for( int j = 0; j <= n-i; ++j ) cout << " ";

    // Rysuj kawałek prawego boku ramki i przejdź do następnej linii. 
    cout << "*\n";
}
for( int j = 0; j < 2*n+3; ++j ) cout << "*"; // Rysuj dolną część ramki. 
a podejście warunkowe - tak:

Kod: Zaznacz cały

for( int i = 0; i < 2*n+3; ++i )
{
    for( int j = 0; j < 2*n+3; ++j )
    {
        if( pole (i, j) ma być puste ) cout << " "; // Trzeba wymyślić, jak dokładnie ma wyglądać warunek. 
        else                           cout << "*";
    }
    cout << "\n";
}
Twój kod jest mieszaniną powyższych dwóch strategii: ramka warunkowo, trójkąt sekwencyjnie. Tak też się da, ale jest trudniej i mniej elegancko, no i twój kod robi to źle.

3. Zmienne i, j są u ciebie dwukrotnie zadeklarowane:

Kod: Zaznacz cały

int i, j;
...
for( int i = 1; ... )
...
for( int j = 1; ... )
Deklaracje w pętlach przykrywają tę na początku (zmienne i, j są traktowane jak nowe zmienne pomimo identycznej nazwy), więc nie wynika stąd żaden błąd, ale wobec tego ta pierwsza deklaracja jest zbędna. Powinieneś ją usunąć i zostawić tylko deklaracje w pętlach.
ODPOWIEDZ