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.