Háromszög kirajzolása egyszerűbben

 ( 4R0N | 2016. október 16., vasárnap - 14:55 )

Sziasztok!

Az alábbi C kóddal kapcsolatban kérnék segítséget:

#include <stdio.h>
#include <stdlib.h>

/**
  * Adott a "telt haromszog" algoritmus
  * Modositsa az algoritmust: csak haztetot, illetve csak a haromszog keretet rajzolja ki!
**/

int main()
{
    //telt haromszog (feladatban megadott algoritmussal)
    int sor, magassag, i;

    printf("Magassag: ");
    scanf("%d", &magassag);

    for(sor=1; sor <= magassag; sor++){
        for(i=1; i <= magassag-sor; i++){
            printf(" ");
        }
        for(i=1; i <= (sor*2)-1; i++){
            printf("*");
        }
        printf("\n");
    }

    printf("\n\n");

    //csak hazteto
    for(sor=1; sor <= magassag; sor++){
        for(i=1; i <= magassag-sor; i++){
            printf(" ");
        }
        printf("*");
        for(i++;i < magassag+sor-1; i++){
            printf(" ");
        }
        if(!(sor == 1)) { //az elso sorban csak 1 csillag szukseges
            printf("*");
        }
        printf("\n");
    }

    printf("\n\n");

    //haromszog keret
    for(sor=1; sor <= magassag-1; sor++){ // ki: 1. sortol utolso elotti sorig
        for(i=1; i <= magassag-sor; i++){
            printf(" ");
        }
        printf("*");
        for(i++;i < magassag+sor-1; i++){
            printf(" ");
        }
        if(!(sor == 1)) { //az elso sorban csak 1 csillag szukseges
            printf("*");
        }
        printf("\n");
        }
    for(i=1; i <= magassag*2-1; i++){ //az utolso sor teljes
        printf("*");
    }

    return 0;
}

A "telt haromszog" algoritmus adott volt pszeudo-kóddal, ezt írtam át C-re. Ezt módosítva kellett kiíratni a "háztetőt" és a háromszög keretét.

Kérdés, hogy a "csak hazteto" és a "haromszog keret" rész egyszerűsíthető-e valahogyan tovább?
Most próbálgatással meg tudtam írni, de nem vagyok benne biztos, hogy 1 hónap múlva ezt papíron is tudni fogom reprodukálni. Ezért érdekelne más nézőpontja is, hátha megoldható egyszerűbben is a feladat.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

    for(sor=1; sor <= magassag; sor++){
        for(i=1; i <= magassag + sor - 1; i++) {
            int keret = (i == magassag - sor + 1 || i == magassag + sor - 1);
            // a haromszoghoz az alabbi a sor is kell:
            // keret |= (magassag == sor);
            printf(keret ? "*" : " ");
        }
        printf("\n");
    }

vagy a mégtömörebb verzió imp példáját mutálva (csak összevonogatva;)):

for(sor=1; sor <= magassag; sor++){
    for(i=1; i <= magassag + sor - 1; i++) printf((i == magassag - sor + 1 || i == magassag + sor - 1) ? "*" : " ");
    printf("\n");
}


// Happy debugging, suckers
#define true (rand() > 10)

Köszönöm mindkettőtöknek. Elég hasznos dolog ez a feltételes kifejezés.

A "for(i++;" kezdetű ciklusod eggyel elcsúsztatja az i változó szemantikáját az előző ciklushoz képest. Az előző ciklus ugyanis eggyel többször növeli i-t, mint ahány karaktert kiír, majd van még egy külön printf, amelyik egálba hozza. Tehát üres inicializálás tartaná fenn ugyanazt a szemantikát (oszlop száma 1-gyel kezdve). Így a jelen kód ékes példája annak, hogy addig pofozod a feltételekben plusz-mínusz a konstansokat, amíg működni nem látszik a kód, miközben talán nem igazán érted, de legalábbis nincs jól megfogható egységes koncepció amögött hogy mit is csinálsz.

Hosszú távon sokkal jobban jársz, ha rászoksz arra, hogy az indexek 0-val kezdődnek, és a bennmaradási feltétel általában úgy néz ki, hogy "index < összdarabszám". Így a legkisebb az eggyel elcsúszás (off by one) veszélye. A "< valami - 1" alakú feltétel (kiszámolsz egy értéket, kivonsz egyet, és még annál is szigorúan kisebbnek kell lennie, vagyis a kiszámolt "valami" értéknél legalább kettővel kisebbnek) tipikusan eléggé gyanús (ún. code smell).

Szőrszálhasogatás:

"!(sor == 1)" helyett "sor != 1"

A harmadik szekció nagy for ciklusának bezáró kapcsos zárójele hibásan van indentálva.

Nem szeretnék indentálási hitvitába belemenni, de tapasztalatom szerint abban szinte mindenki egyetért, hogy beépített kulcsszavak (for, if, ...) után szóközt szokás tenni, valamint a sorvégi nyitó kapocs (ha ezt a stílust választod, nem új sorban nyitod ki) elé is.

Az output-ot legalább egy newline karakterrel zárjuk, különben a prompt fura helyen jelenik meg és egyéb rondaságok is történnek.

Hasznos tanácsok, köszönöm szépen. Azonban az első bekezdésed nem igazán értem.

Így kellene kinéznie a kódnak?

    for (sor=1; sor <= magassag; sor++) {
        for (i=1; i <= magassag-sor; i++) {
            printf(" ");
        }
        printf("*");
        for (;i <= magassag+sor-3; i++) {
            printf(" ");
        }
        if (sor != 1) { //az elso sorban csak 1 csillag szukseges
            printf("*");
        }
        printf("\n");
    }

Vagy így?

    for (sor=1; sor <= magassag; sor++) {
        for (i=1; i <= magassag-sor; i++) {
            printf(" ");
        }
        printf("*");
        for (i=1; i < sor*2-2; i++) {
            printf(" ");
        }
        if (sor != 1) { //az elso sorban csak 1 csillag szukseges
            printf("*");
        }
        printf("\n");
    }

És ha igen, miért célszerűbb ezt a megoldást alkalmazni, mint az enyémet?