C Tannenbaum Programm

Psycho-Dad

Admiral Special
Mitglied seit
11.11.2001
Beiträge
1.711
Renomée
1
Standort
Regensburg
Hi Leute,

ich mach hier grad ein paar Fingerübungen zu C. Dabei bin ich auf ein Programm gestoßen welches ein rechtwinkeliges Dreieck aus Sternchen auf dem Bildschirm ausgibt. Ich dachte mir das Programm müsste sich doch so modifizieren lassen das eine Art Tannenbaum entsteht, nur irgendwie waren meine Versuche noch nicht so sehr von Erfolg gekrönnt.

Kann mir vielleicht einer von euch sagen wo mein Denkfehler bei folgenden Programm liegt.

Code:
#include <stdio.h>

main () {
	int zeile, spalte, leer;
	for(zeile=1; zeile<=20; zeile=zeile+1) {
		for(spalte=1; spalte<=zeile; spalte=spalte+1) {
			for(leer=10; leer>=spalte; leer=leer-1) {
				printf(" ");
				}
			printf("*");
			}
		printf("\n");
		}
	}
 
Nur mal so als Anstoß (gefüllter Baum, Spitze in Spalte 10):

in Zeile 1, 9 Leerzeichen, dann Sternchen.
für jede weitere Zeile, ein Leerzeichen weniger, zwei Sternchen mehr.

Mit dem Ansatz solltest du die Schleifen mal durchgehen.
 
So hab jetzt rausgefunden, die Leerzeichenschleife gehört auch in die Hauptschleife, vor die Sternchenschleife.

Code:
#include <stdio.h>

main () {
	int zeile, spalte, leer;
	for(zeile=1; zeile<=20; zeile=zeile+1) {
		for(leer=20; leer>=zeile; leer=leer-1) {
				printf(" ");
				}
		for(spalte=1; spalte<=zeile; spalte=spalte+1) {
			printf("**");
		}
		printf("\n");
	}
}
 
Ich habe mir den Spaß auch mal gemacht und es mit einer Schleife (nur die Zeilen-Schleife) hinbekommen, aber mit nem kleinen Trick ;)
Code gibt es morgen.

Btw:
Probier mal die Anzahl Zeilen/Spalten in eine constante zu extrahieren, das ist sauberer (#define groesse 10) und dann size verwenden.
Oder - noch besser - du knallst das in ne Funktion - so was wie zeichneBaum(int groesse) und rufst die aus dem Hauptprogramm auf.
 
Zuletzt bearbeitet:
Hier der Code (mit Baumstamm ;) )

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

#define TREESIZE 10

main ()
{
  int zeile, spalte, leer, sterne;
  char leaf[TREESIZE * 2];
  // Baum
  for (zeile = 0; zeile < TREESIZE; zeile++)
    {
      sprintf (leaf, "%%%ds/%%%ds\\\n", TREESIZE-zeile, ((zeile) * 2));
      printf (leaf, "", "");
    }
  // Unteres Ende der Blätter
  for (spalte = 0; spalte < (TREESIZE * 2) + 2; spalte++)
    {
      printf ("-");
    }
  printf ("\n");
  // Stamm
  for (zeile = 1; zeile < 4; zeile++)
    {
      sprintf (leaf, "%%%ds||\n", TREESIZE);
      printf (leaf, "");
    }
}
Hier der Baum
Code:
[FONT="Lucida Console"]
          /\
         /  \
        /    \
       /      \
      /        \
     /          \
    /            \
   /              \
  /                \
 /                  \
----------------------
          ||
          ||
          ||
[/FONT]
 
Zuletzt bearbeitet:
hmm ein const hätte es an stelle des #define auch gemacht
 
hmm ein const hätte es an stelle des #define auch gemacht

Sicher, bin aber (eigentlich) kein C-Programmierer und ignoriere mal solche Feinheiten ;)

Aber wie schon gesagt, am besten ist sowieso wenn man das in ne Funktion haut und die Größe als Parameter übergibt (man ersetze main(...) durch zeichneBaum(int size) oder so und rufe die aus der main auf.
 
So ich habe das Ganze noch einmal etwas aufgeblasen;D

// Tannenbaum.cpp : Defines the entry point for the console application.
//

#define linecount 100 //Gibt die Höhe der Darstellung an
#define linesize 80 //Die Breite der Darstellung (nicht über 80, da es sonst zu Zeilenüberläufen kommt)

#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))

#include "stdafx.h"
#include "conio.h"
#include "stdio.h"

void draw_triangle(char **memory,char character,int x1,int y1,int x2,int y2,int x3,int y3);
void display(char **memory);

int main(int argc, char* argv[])
{
//memory initialisieren mit Leerzeichen
char **memory = new char *[linecount];

for(int i=0;i<linecount;i++)
memory=new char[linesize];

for(int i=0;i<linecount;i++)
for(int j=0;j<linesize;j++)
memory[j]=' ';

//Baum zeichnen
draw_triangle(memory,'X',25,0,35,0,25,45); //Stamm erster Teil
draw_triangle(memory,'X',35,0,25,45,35,45); //Stamm zweiter Teil (zwei Aufrufe, weil kein Rechteck möglich)
draw_triangle(memory,'X',0,15,25,15,25,30); //Unterer Ast linker Teil
draw_triangle(memory,'X',35,15,60,15,35,30); //Unterer Ast rechter Teil
draw_triangle(memory,'X',5,30,25,30,25,45); //Mittlerer Ast links
draw_triangle(memory,'X',35,30,55,30,35,45); //Mittlerer Ast rechts
draw_triangle(memory,'X',10,45,50,45,30,60); //Oberer Ast (links und rechts)

//Baum anzeigen
display(memory);
}

//Zeichnet ein Dreick (muss nicht rechtwinkelig sein)
void draw_triangle(char **memory,char character,int x1,int y1,int x2,int y2,int x3,int y3)
{
int x[3]={x1,x2,x3}; //Speichert die Koordinaten in ein Feld
int y[3]={y1,y2,y3};

int i_t; //Index für oben, mitte, unten (top,middle,bottom)
int i_m;
int i_b;

//Top suchen
if(y1>=y2&&y1>=y3)
i_t=0;
else if(y2>=y3)
i_t=1;
else
i_t=2;

//Bottom suchen
if(y1<y2&&y1<y3)
i_b=0;
else if(y2<y3)
i_b=1;
else
i_b=2;

//Middle ist das andere
i_m=0+1+2-i_t-i_b;

int y_t=y[i_t]; //Einlesen der y-Werte für oben,unten,mitte
int y_m=y[i_m];
int y_b=y[i_b];

int x_b=x[i_b]; //Einlesen der x-Werte für oben,unten,mitte
int x_m=x[i_m];
int x_t=x[i_t];

int dy_tb=y_t-y_b; //Differenzen in der y-Koordinaten zwischen oben,mitte,unten
int dy_mb=y_m-y_b;
int dy_tm=y_t-y_m;

int dx_tb=x_t-x_b; //Dasselbe für die x-Koordinaten
int dx_mb=x_m-x_b;
int dx_tm=x_t-x_m;

//Untere Hälfte (Unterteilung in zwei Dreiecke, wobei jeweils eine Seite parallel zur y-Achse liegt
int x_cutpoint=x_b+dy_mb*(dx_tb/(double)dy_tb); //Berechnet den x-Wert des Punktes, der auf der selben Höhe wie die Mitte auf der Seite von unten nach oben

double d_min=(double)(min(x_m,x_cutpoint)-x_b)/dy_mb; //Berechnet die Veränderung von x bei einer Änderung von y um 1 (min ist links, max ist rechts)
double d_max=(double)(max(x_m,x_cutpoint)-x_b)/dy_mb;

double x_min=x_b; //Beginnen beim unternen Punkt
double x_max=x_b;

for(int y_current=y_b;y_current<=y_m;y_current++) //Alle Zeile von unten nach oben durchwandern
{
for(int i=x_min;i<x_max;i++) //Den jeweiligen Bereich auffüllen
memory[y_current]=character;

x_min+=d_min;
x_max+=d_max;
}

//Obere Hälfte (funktioniert so wie vorher, nur von oben nach unten

x_min=x_t;
x_max=x_t;

d_min=(double)(min(x_m,x_cutpoint)-x_t)/dy_tm;
d_max=(double)(max(x_m,x_cutpoint)-x_t)/dy_tm;

for(int y_current=y_t;y_current>=y_m;y_current--)
{
for(int i=x_min;i<x_max;i++)
memory[y_current]=character;

x_min+=d_min;
x_max+=d_max;
}
}

//Gibt alles auf dem Bildschirm aus
void display(char **memory)
{
for(int i=linecount-1;i>=0;i--)//Dreht die Ausgabe um damit das normale Koordinatensystem erhalten bleibt (Zeile2 2 ist über Zeile1)
{
for(int j=0;j<linesize;j++)
printf("%c",memory[j]);
}
}
.
EDIT :
.

Das ist er der Baum:

XXXX
XXXXXX
XXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX

Edit: In Wirklichkeit ist er schön symetrisch. Das kann anscheinend nur das Forum nicht anzeigen. Das frisst bei mir die Leerzeichen.
 
Hi Leute,

ich hätte da mal noch ein Problem und ich hoffe einer von euch kann mir helfen. Ich kämpf immer noch mit C und bin noch nicht bereit den Kampf aufzugegeben ;)

Also die Aufgabe lautet. Ich soll ein Programm schreiben welches double-Werte einliest und je nachdem ob es <0, =0 oder >0 ist -1, 0 oder +1 als int-Wert zurück gibt.

Ich hab das ganze so realisiert, aber bei 0 bekomm ich immer -1 zurück.

Code:
#include <stdio.h>

int betrag(double zahl) {
	if (zahl > 0.0)
		return (1);
	else if (zahl == 0.0)
		return (0);
	else 
		return (-1);
}

double eingabe () {
        float einlesen;
	printf("\nBitte Wert eingeben: ");
	scanf("%lf", &einlesen);
	return (einlesen);
}

int main () {
	int anzahl, i;
	printf("\nWieviele Werte wollen sie eingeben: ");
	scanf("%i", &anzahl);
	for (i=1; i <= anzahl; i++) {
		printf("\nDer Rückgabewert der Zahl beträgt: %i\n", betrag(eingabe(i)));
	}
    return (0);
}
EDIT: Fehler gefunden, man sollte halt dann beim vergleichen == benutzen und nicht die Zuweisung = argh. verdammter Anfängerfehler
REDIT: Gibt es eigentlich die Möglichkeit eine Unterfunktion aufzurufen und 2 oder mehr Werte an das Hauptprogramm zurück zu geben???
 
Zuletzt bearbeitet:
REDIT: Gibt es eigentlich die Möglichkeit eine Unterfunktion aufzurufen und 2 oder mehr Werte an das Hauptprogramm zurück zu geben???

"C" kann alles:

void MeinUnterprogramm (int* ersterRueckgabewert, char* zweiterRueckgabewert)
{
...
*ersterRueckgabewert = 1;
*zweiterRueckgabewert = 'A';
}

Aufruf:
int i;
char c;
MeinUnterprogramm (&i, &c);

Bei vielen Werten ist ein Struktur zu empfehlen.;)

Hilfreich ist, wenn man die Begriffe Pointer und Adresse sicher anwenden kann.
 
Zuletzt bearbeitet:
Zurück
Oben Unten