C-Programm – Umrechnung von Zahlensystemen

Das Programm kann dezimale Zahlen in andere Zahlensysteme umrechnen… sowohl Vorkomma- als auch Nachkommastellen.

#include <stdio.h>

int main(void) {
	float kommazahl, kommazahl_darstellung;
	float array_kommazahl[32], array_kommazahl_ergebnis[32];
	char array_rest[32];
	int y=0, zahl, rest, ergebnis;
	int i=0, j=0, loop=0, basis, genauigkeit=30;

	/* mache etwas (min. 1-mal) ... */
	do { 
		printf("Bitte eine positive Kommazahl eingeben:");
		scanf("%f", &kommazahl);
	/* ... solange die Eingabe kleiner 0 */
	} while (kommazahl < 0);

	/* mache etwas (min 1-mal) ... */
	do {
		printf("Bitte eine Basis >=2 ein:");
		scanf("%d", &basis);
	/* ... solange die Eingabe kleiner 2 */ 
	} while (basis < 2 );

/*
	z.B.: die Dezimalzahl 8 soll ins 2er-System umgewandelt werden

	Verfahren:
	(1) Teile die Zahl mit Rest durch 2.
	(2) Der Divisionsrest ist die naechste Ziffer (von rechts nach links).
	(3) Falls der (ganzzahlige) Quotient = 0 ist, bist du fertig,
		andernfalls nimm den (ganzzahligen) Quotienten als neue Zahl 
		und wiederhole ab (1).

	8 : 2 = 4  Rest: 0
	4 : 2 = 2  Rest: 0
	2 : 2 = 1  Rest: 0
	1 : 2 = 0  Rest: 1

	-> Resultat: 1000
*/

	printf ("\nV O R K O M M A S T E L L E N:\n\n");

	/* nur die Vorkommastellen (Integer = ganze Zahl) in die Variable 'zahl' schreiben */
    zahl = (int) kommazahl;

	while (zahl > 0) { // (3)
		rest = zahl % basis; // (1)
		array_rest[y++] = rest; // Array fuer die umgekehrte Reihenfolge der Ausgabe
		ergebnis = zahl / basis;
		printf("%d : %d = %d  Rest: %d\n", zahl, basis, ergebnis, rest); // Ausgabe 
		zahl = zahl / basis; // (2)
	}

	printf("\n-> Resultat: ");
	while (--y >= 0) { // umgekehrte Reihenfolge der Ausgabe
 		printf("%d", array_rest[y]);
	}


/* 
	z.B: der Dezimalbruch  0,8  soll ins 2er System umgewandelt werden

	Verfahren fuer Nachkommaziffern:
	(1) Multipliziere die Zahl mit der Basis 2
	(2) Die Zahl vor dem Komma ist die naechste Ziffer des Ergebnisses
	(3) Schneide die Zahl vor dem Komma weg.
	(4) Wiederhole ab (1), bis der Rest 0 ist, sich ein Rest wiederholt
		oder die gewuenschte Genauigkeit erreicht ist.

	2 · 0,8 = 1,6    --> Ziffer: 1
	2 · 0,6 = 1,2    --> Ziffer: 1
	2 · 0,2 = 0,4    --> Ziffer: 0
	2 · 0,4 = 0,8    --> Ziffer: 0
	2 · 0,8 = 1,6    --> Ziffer: 1

	Der "Rest" 1,6 trat im 1. Schritt bereits auf.
	Ab dort wiederholen sich die Nachkommaziffern periodisch.

	-> Resultat: 0,1100110011001100110011001100110011001100110011001100...
*/

	printf ("\n\n\nN A C H K O M M A S T E L L E N:\n\n");

	kommazahl = kommazahl - (int) kommazahl; // z.B. kommazahl = 2,5 - 2 = 0,5
	kommazahl_darstellung = kommazahl; // nur zur Veranschaulichung in der Ausgabe

	do {
		kommazahl *= basis; // (1)
		kommazahl = ( (int) (kommazahl * 1000.0 + 0.5)) / 1000.0; // Runden auf 4 Nachkommastellen
		array_kommazahl[j] = kommazahl; // Restwert in ein Array schreiben

		for ( j=0; j < i; j++ ) { 
			// printf("\ntest - [%d][%d] - %f\n", i, j, array_kommazahl[j]); // test - Ausgabe
			if ( array_kommazahl[j] == kommazahl ) { // (4) - Wiederholung feststellen
				loop = j;
			}
		}

		if ( (int) kommazahl == 0 && loop == 0) { // (2)
			printf ("%d * %.1f = %.1f  --> Ziffer: %d\n", basis, kommazahl_darstellung, kommazahl, (int) kommazahl); // Ausgabe
			array_kommazahl_ergebnis[j] = (int) kommazahl;
		} else if ( (int) kommazahl != 0 && loop == 0) { // (2) 
			printf ("%d * %.1f = %.1f  --> Ziffer: %d\n", basis, kommazahl_darstellung, kommazahl, (int) kommazahl); // Ausgabe
			array_kommazahl_ergebnis[j] = (int) kommazahl;
			kommazahl -= (int) kommazahl; // (3)
		}

		if ( loop >= 1 ) {
			printf ("\nDer \"Rest\" von %f trat im %d. Schritt bereits auf.\nAb dort wiederholen sich die Nachkommaziffern periodisch.\n", array_kommazahl[j-1], loop); 
			printf ("\n-> Resultat: 0,");
			for ( j=0; j < i; j++ ) {
				printf ("%d", (int) array_kommazahl_ergebnis[j]);
			}
			printf ("\n");
		}

		if ( kommazahl == 0.0 ) {
			printf ("\nEs ist kein Rest mehr uebrig... :-)");
			printf ("\n-> Resultat: 0,");
			for ( j=0; j < i; j++ ) {
				printf ("%d", (int) array_kommazahl_ergebnis[j]);
			}
			printf ("\n");
		}

		if ( i >= genauigkeit ) {
			printf ("\nDie Genauigkeit sollte nun ausreichen... (%d Bit)", genauigkeit);
			printf ("\n-> Resultat: 0,");
			for ( j=0; j < i; j++ ) {
				printf ("%d", (int) array_kommazahl_ergebnis[j]);
			}
			printf ("\n");
			break;
		}

		kommazahl_darstellung *= basis; // nur zur Veranschaulichung in der Ausgabe
		kommazahl_darstellung = ( (int) (kommazahl_darstellung * 1000.0 + 0.5)) / 1000.0; // nur zur Veranschaulichung in der Ausgabe
		kommazahl_darstellung -= (int) kommazahl_darstellung; // nur zur Veranschaulichung in der Ausgabe

		i++;
		j++;
//	} while ( ( i < genauigkeit ) || !(!(loop == 0 && kommazahl != 0.0 ) && !(loop == 0 && kommazahl != 0.0 )) ); // (4) + Logisches XOR
	} while ( !(!(loop == 0 && kommazahl != 0.0 ) && !(loop == 0 && kommazahl != 0.0 )) ); // (4) + Logisches XOR

	return(0);
}

Backup to USB-Stick per udev


Udev-tux“udev überwacht und wertet hotplug-Ereignisse aus. Finden sich dort Informationen über ein neu angeschlossenes Gerät, werden zusätzliche zu diesem Gerät vorhandene Informationen dem sysfs-Dateisystem entnommen und eine neue Gerätedatei im /dev-Verzeichnis erzeugt. Dabei ist der für die spezielle Datei verwendete Name und die Zugriffsberechtigung frei durch Regeln konfigurierbar.” – wiki


Wir möchten ein Backup auf unseren USB-Stick durchführen, sobald wir diesen mit dem PC verbinden! Dafür müssen wir als erstes einige Infos sammeln, somit schauen wir uns folgnde Datei zeitgleich zum einstecken des USB-Speichers an.


tail -f /var/log/messages

Ausgabe:

Nov  2 22:10:30 suckup-netbook kernel: [13570.309562] scsi 5:0:0:0: Direct-Access     USB 2.0  Flash Drive      8.07 PQ: 0 ANSI: 2

Nov  2 22:10:30 suckup-netbook kernel: [13570.320160] sd 5:0:0:0: Attached scsi generic sg2 type 0

Nov  2 22:10:30 suckup-netbook kernel: [13570.338740] sd 5:0:0:0: [sdc] 3938304 512-byte logical blocks: (2.01 GB/1.87 GiB)

Nov  2 22:10:30 suckup-netbook kernel: [13570.339345] sd 5:0:0:0: [sdc] Write Protect is off

Nov  2 22:10:31 suckup-netbook kernel: [13570.342397]  sdc:

Nov  2 22:10:31 suckup-netbook kernel: [13570.778378] sd 5:0:0:0: [sdc] Attached SCSI removable disk

Somit wissen wir schon einmal, wo sich der Speicher befindet… mit dem folgendem Befehl können wir uns nun alle Partitionen anschauen….
cat /proc/partitions

… und ggf. mit dem nächsten Befehl eine neue Partition anlegen.

fdisk /dev/sda


Als nächstes wollen wir nun die spezifischen Infos vom USB-Stick abfragen:

udevadm info -a -p $(udevadm info -q path -n /dev/sdc)

Ausgabe:

looking at parent device ‘/devices/pci0000:00/0000:00:1d.7/usb1/1-3’:

KERNELS==”1-3″

SUBSYSTEMS==”usb”

DRIVERS==”usb”

[…]

ATTRS{idVendor}==”058f”

ATTRS{idProduct}==”6387″

[…]

ATTRS{manufacturer}==”Generic”

ATTRS{product}==”Mass Storage”

ATTRS{serial}==”9D853A1BCAC440404FEF”

Um das Gerät (USB-Stick) eindeutig zu identifizieren benötigen wir nun die folgenden Angaben: “idVendor”, “idProduct” und “serial”


sudo vim /etc/udev/rules.d/80-backup-stick.rules

KERNEL==”sd?”, ATTRS{idVendor}==”058f“, ATTRS{idProduct}==”6387“, ATTRS{serial}==”9D853A1BCAC440404FEF“, SYMLINK+=”backup-stick“, RUN+=”/home/lars/bin/bash/backup-stick.shBackup‘ ‘to_Stick'”

  • ggf. Partition mit angeben: sd?1
  • RUN+= -> muss der Pfad zu deinem Skript sein
  • idProdukt u.s.w. muss natürlich noch mit den Werten von deinem Stick angepasst werden
sudo /etc/init.d/udev restart


Als nächstes müssen wir ein Skript erstellen, welches auf einem User-Desktop per root eine Pop-Up erzeugen kann…

sudo vim /usr/local/bin/root-notify-send
#!/bin/sh
user=`whoami`
pids=`pgrep -u $user gnome-panel`
title=$1
text=$2
timeout=$3
icon=$4

if [ -z "$title" ]; then
 echo You need to give me a title >&2
 exit 1
fi
if [ -z "$text" ]; then
 text=$title
fi
if [ -z "$timeout" ]; then
 timeout=60000
fi

for pid in $pids; do
 DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS \
 /proc/$pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'`

 if [ -z $icon ]; then
 DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \
 notify-send -u low -t $timeout "$title" "$text"
 else
 DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \
 notify-send -u low -t $timeout -i "$icon" "$title" "$text"
 fi
done
sudo chmod +x /usr/local/bin/root-notify-send


vim ~/bin/bash/backup-stick.sh
#!/bin/bash

su lars -c "/bin/bash root-notify-send "$1" "$2" 6000 "/home/lars/Bilder/backup.png""
mount /dev/backupstick /media/backupstick
su lars -c "/usr/bin/rsync -rlptgzu --delete-after  /home/lars/bin/ /media/backupstick"
umount /media/backupstick

An dieser Stelle macht sich natürlich ein Bild vom Stick besondes gut. ;-) Dann noch schnell ggf. einige Programme nach-installieren, ein Verzeichnis anlegen und Rechte ändern, fertig!

chmod +x ~/bin/bash/backup-stick.sh
sudo aptitude install libnotify-bin rsync
sudo mkdir /media/backupstick




Backup to Stick
Backup to Stick


C-Programm – doppelte Schleife

In diesem Beispiel zeige ich, wie sich eine doppelte Schleife auswirkt…

#include 

main() {
    /* Integer (ganze Zahl) */
    int x,y;

    /* die erste Schleife wird 10-mal durchlaufen */
    for(x=1; x< =10; x=x+1) {
        /* als erstes wird ein Zeillenumbruch (\n) dargestellt */
        printf("\n");

        /* die zweite Schleife befindet sich in der ersten,
           so dass diese jeweills 10*20-mal durchlaufen wird */
        for(y=1; y<=20; y=y+1) {
            /* Feldbreite von 4-Stellen (1234,  34,   4),
               nun wird 1*1, 1*2 [20-mal],
               dann     2*1, 2*2 [20-mal] gerechnet */
            printf("%4i", x*y);
        }
    }
}

/*
   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20
   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30  32  34  36  38  40
   3   6   9  12  15  18  21  24  27  30  33  36  39  42  45  48  51  54  57  60
   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60  64  68  72  76  80
   5  10  15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90  95 100
   6  12  18  24  30  36  42  48  54  60  66  72  78  84  90  96 102 108 114 120
   7  14  21  28  35  42  49  56  63  70  77  84  91  98 105 112 119 126 133 140
   8  16  24  32  40  48  56  64  72  80  88  96 104 112 120 128 136 144 152 160
   9  18  27  36  45  54  63  72  81  90  99 108 117 126 135 144 153 162 171 180
  10  20  30  40  50  60  70  80  90 100 110 120 130 140 150 160 170 180 190 200
*/

C-Programm – Kommandozeilenparameter

In diesem Beispiel zeige ich, wie du Parameter in einem C-Programm einsetzen kannst…

/* 
read_args.c 

Achtung: 
        - bei Platzhaltern (*) !!! Wird hier noch nicht beruecksichtigt
        - die Hilfe ist nur per '-h' und nicht '--help' aufrufbar
        - Fehlermeldungen werden nicht ausgegeben
*/

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
        int option, i;
        char *out_filename=NULL;

        /* argc -> Anzahl Kommandozeilenparameter + Programmnamen (1), somit ist der Wert min. 1 */

        /* argv -> ist ein Zeiger auf das Feld (Array) mit der in argc angegebene Anzahl von Elementen...
                   ... und die Elemente (z.B.: argc[0] sind Zeiger auf eine Zeichenkette...

                   arg[0] -> Programmname
                   arg[1] -> 1. Parameter 
                   arg[2] -> 2. Parameter
                   [...]
                   arg[n] -> letzter Parameter
                    0L    -> das letzte Element von argv[] einthaelt eine Null
        */

        /* 
           getopt() sortiert zunaechst das Feld argc[] 
           1. Optionen
           2. Argumente

           Rueckgabewert: erste in der Kommandozeile angegebene Option oder -1 wenn keine Option angegeben wurde...
                          ... beim naechen Durchlauf jeweills die naechste angegebene Option...
                          ... und zum Schluss -1

           x:  -> 'x' waehre hier eine Option
           x:: -> 'x' waehre hier eine optinale Option
           xy: -> 'x' und 'y' waehren hier die Optionen (Optionsliste)  
        */
        while((option = getopt(argc, argv, "ho:")) >= 0) {
                switch(option) {
                        case 'h':
                                printf("Usage: %s [-o output-file] [input-file ...]\n", argv[0]);
                                return(0);
                        case 'o':
                                out_filename = optarg;
                                break;
                        /* wenn ein unzulaessige Option angegeben wurde, gibt getopt() ein '?' aus */
                        case '?':
                                return(1); /* unbekannte Option ... Abbruch */
                }
                /* die globale Variable 'optind' gibt den Index des ersten Arguments dem Feld argv[] weiter */
                for (i=optind; i<argc; i++) {
                        printf("'%s'\n", argv[i]);
                }
                if (out_filename) {
                        printf("output is '%s'\n", out_filename);
                }
        }
        return(0);
}

/*
Ausgabe:
./read_args -o test1 1 2 3 4 5 
'1'
'2'
'3'
'4'
'5'
output is 'test1'
*/

C-Programm – Primzahlen & Makefiles

Das folgende Programm gibt alle Primzahlen von 1 bis 100 aus, dabei wurde die Berechnung in eine eigene Funktion ausgelager.

/*
primzahlen.c
*/

#include <stdio.h>
#include <math.h>

/*
gcc -Wall -lm primzahlen.c -o primzahlen -O3
*/

int ist_primzahl(int zahl) {
    int teiler=2;

    /* solange der 'teiler' kleiner/gleich der (²)Wurzel aus 'zahl' ist ...
    ...  denn Primzahlen haben -keinen- Teiler der kleienr als dessen Quadratwurzel ist */
    while (teiler <= sqrt(zahl)) {
    /* alternativ, dann ohne <math.h> */
    /* while (teiler*teiler <= zahl) { */
        /* wenn kein Rest, dann... */
        if (zahl % teiler == 0) {
            /* ... 'false' */
            return(0);  /* 'zahl' ist keine Primzahl */
        }
        /* teiler und einen erhoehen */
        teiler++;
    }
    /* ... ansonsten 'true' */
    return(1);          /* 'zahl' ist eine Primzahl */
}

int main() {
    int zahl;

    /* solange bis 1 nicht mehr kleiner/gleich 100 bis, 1 erhoehen */
    for (zahl=1; zahl<=100; zahl++) {
        /* wenn Funktion='true' dann ...*/
        if (ist_primzahl(zahl)) {
            /* ... Zahl ausgebn */
            printf("%d\n", zahl);
        }
    }
    return(0);
}


Bei großen Projekten kann es hilfreich sein, diese Funktionen in verschiedenen Dateien zu organisieren und später wieder zusammen zu fügen…

1.) Den Quellcode in einen beliebigen ASCII-Texteditor eintippen und abspeichern.

2.) Den Quellcode mit einem Compiler übersetzen, wodurch eine Objektdatei (*.pbj oder *.o) erzeugt wird.

3.) Die Objektdatei mit einem Linker binden, so dass eine ausführbare Datei erzeugt wird. Der Linker sucht außerdem alle benötigten Funktionen aus den Standard-Bibliotheken heraus und fügt diese anschließend dem fertigen Programm hinzu.


zu 2.)

gcc -c primz_haupt.c
gcc -c primz_math.c

zu 3.)

gcc primz_haupt.o primz_math.o -lm -O3 -Wall -o primzahl


/*
primz_haupt.c
*/

#include <stdio.h>
#include "primz_math.h"

int main() {
        int zahl;

        for(zahl=1; zahl<=100; zahl++) {
                if (ist_primzahl(zahl)) {
                        printf("%d\n", zahl);
                }
        }
        return(0);
}
/*
primz_math.c
*/

#include <math.h>

int ist_primzahl(int zahl) {
        int teiler=2;

        while(teiler <= sqrt(zahl)) {
                if(zahl % teiler == 0) {
                        return(0);
                }
                teiler++;
        }
        return(1);
}


Um die zuvor beschriebene Prozedur zu beschleunigen, gibt es die sogenannten Makefiles, welche alle Informationen zum kompilieren enthalten und den Prozess somit automatisch durchführen können.

Als erstes ein ausführliches Beispiel:

# Makefile
#

#4.) 'primz_haupt.o' + 'primz_math.o' zusammenfuehren
primzahl:       primz_haupt.o primz_math.o
                gcc primz_haupt.o primz_math.o -lm -o primzahl

#3.) 'primz_haupt.o' erzeugen + 'primz_math.h' einfuegen
# Info: 'primz_math.h' ist die Verknuepfung zu 'primz_math.c'
primz_haupt.o:  primz_haupt.c primz_math.h
                gcc -c primz_haupt.c

#2.) 'primz_math.o' erzeugen
primz_math.o:   primz_haupt.c
                gcc -c primz_math.c

#1.) aufraeumen
clean: 
                rm -f primz_haupt.o prinz_math.o

Und hier die komprimierte Version: :-)

# Makefile2
#

TARGET  = primzahl
OBJECTS = primz_haupt.o primz_math.o
HEADERS = primz_math.h
LIBS    = -lm

$(TARGET):      $(OBJECTS)
                gcc $^ $(LIBS) -o $@

primz_%.o:      primz_%.c $(HEADERS)
                gcc -c $&lt; -o $@

clean: 
                rm -f $(OBJECTS)

C-Programm – Größe von Variablen

Mit diesem kleinem Programm kannst du dir die minimale und maximale Größe von Variablen ausgeben lassen. :-)

#include <stdio.h>
#include <limits.h>
#include <float.h>

int main(void) {
        printf("min. char-Wert          : %d\n", SCHAR_MIN);
        printf("max. char-Wert          : +%d\n", SCHAR_MAX);
        printf("min. unsigned-char      : 0\n");
        printf("max. unsigned-char      : %u\n\n", UCHAR_MAX);

        printf("min. short-Wert         : %d\n", SHRT_MIN);
        printf("max. short-Wert         : +%d\n", SHRT_MAX);
        printf("min. unsigned-short     : 0\n");
        printf("max. unsigned-short     : %u\n\n", USHRT_MAX);

        printf("min. int-Wert           : %d\n", INT_MIN);
        printf("max. int-Wert           : +%d\n", INT_MAX);
        printf("min. unsigned-int       : 0\n");
        printf("max. unsigned-int       : %u\n\n", UINT_MAX);

        printf("min. long-Wert          : %ld\n", LONG_MIN);
        printf("max. long-Wert          : +%ld\n", LONG_MAX);
        printf("min. unsigned-long      : 0\n");
        printf("max. unsigned-long      : %lu\n\n", ULONG_MAX);

        printf("min. long long-Wert     : %lld\n", LLONG_MIN);
        printf("max. long long-Wert     : +%lld\n", LLONG_MAX);
        printf("min. unsigned-llong     : 0\n");
        printf("max. unsigned-llong     : %llu\n\n", ULLONG_MAX);


        printf("min. float-Wert         : %f\n", FLT_MIN);
        printf("max. float-Wert         : +%f\n", FLT_MAX);
        printf("float Genauigkeit       : %d\n\n", FLT_DIG);

        printf("min. double-Wert        : %lf\n", DBL_MIN);
        printf("max. double-Wert        : +%lf\n", DBL_MAX);
        printf("double Genauigkeit      : %d\n\n", DBL_DIG);

        printf("min. long double        : %Lf\n", LDBL_MIN);
        printf("max. long double        : +%Lf\n", LDBL_MAX);
        printf("long double Genu.       : %d\n\n", LDBL_DIG);

        return 0;
}


Ausgabe:

min. char-Wert : -128
max. char-Wert : +127
min. unsigned-char : 0
max. unsigned-char : 255

min. short-Wert : -32768
max. short-Wert : +32767
min. unsigned-short : 0
max. unsigned-short : 65535

min. int-Wert : -2147483648
max. int-Wert : +2147483647
min. unsigned-int : 0
max. unsigned-int : 4294967295

min. long-Wert : -2147483648
max. long-Wert : +2147483647
min. unsigned-long : 0
max. unsigned-long : 4294967295

min. long long-Wert : -9223372036854775808
max. long long-Wert : +9223372036854775807
min. unsigned-llong : 0
max. unsigned-llong : 18446744073709551615

min. float-Wert : 0.000000
max. float-Wert : +340282346638528859811704183484516925440.000000
float Genauigkeit : 6

min. double-Wert : 0.000000
max. double-Wert : +179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889[…]

min. long double : 0.000000
max. long double : +1189731495357231765021263853030970205169063322294624200440323733891737005522970722616410290336528882853545697807495577314427443153670[…]


Wenn du das nächste C-Programm einmal kompiliert hast und es mehrere male nacheinander ausführst siehst du, dass die Variable ggf. an einer anderen Stelle im Speicher abgelegt wurde.

#include <stdio.h>

int main(void) {
        int var=0;
        printf("Die Adresse von var lautet: %p\n", &var);
        return 0;
}

C-Programm – letzte Ziffer anzeigen

Die letzte Ziffer einer Zahl ausgeben lassen…

#include <stdio.h>

void main(void) {
    int n,letzteZiffer;

    /* 
       
      n mod 10 
    = n % 10 
    = Rest, nach der Division durch 10
     
    "Die Division mit Rest (Modulo) wird in der Programmierung relativ häufig verwendet. 
    Die Syntax ist dabei die eines Operators. Mit mod kann geprüft werden, 
    ob eine Zahl gerade ist: if ( (x mod 2) == 0), dann ist x gerade. 
    Modulo kann man immer benutzen, wenn man alle X Schleifendurchläufe einen speziellen 
    Programmcode ausführen will. Auch bei vielen Berechnungen und Algorithmen ist er 
    sinnvoll einsetzbar. Allgemein kann man mit mod prüfen, 
    ob eine Zahl durch eine andere genau teilbar ist, dann ist der Modulo nämlich Null." - wiki

    */

    printf("Bitte eine Zahl eingeben: ");
    scanf("%d", &n);
    letzteZiffer = n % 10;
    printf("\nletzteZahl %d\n", letzteZiffer);
}

Nginx + Varnish auf Debian/Ubuntu

Zurück zur “Webseiten beschleunigen” – Übersicht

5.4) Nginx mit Varnish


“Varnish ist ein Web-Beschleuniger für dynamische Web-Seiten mit viel Inhalt. Im Gegensatz zu anderen Web-Beschleunigern, die häufig aus clientseitigen Proxies oder aus Servern entstanden, wurde Varnish von Grund auf als Web-Beschleuniger konzipiert.” – Wiki


Als erstes erweitern wir unsere sources.list, so dass wir die Varnish-Software einfach installieren / updaten können:


Ubuntu:

echo "http://repo.varnish-cache.org/ubuntu/ lucid varnish-2.1" >> /etc/apt/sources.list


Debian:

echo "deb http://repo.varnish-cache.org/debian/ lenny varnish-2.1" >> /etc/apt/sources.list


Nun installieren wir Varnish…

curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -
aptitude install varnish


Nun müssen wir einige Eistellungen an Varnish vornehmen, so dass dieser als erstes angesprochen wird…

vim /etc/default/varnish
# Configuration file for varnish
#
# /etc/init.d/varnish expects the variables $DAEMON_OPTS, $NFILES and $MEMLOCK
# to be set from this shell script fragment.
#

# Should we start varnishd at boot?  Set to "yes" to enable.
START=yes

# Maximum number of open files (for ulimit -n)
NFILES=131072

# Maximum locked memory size (for ulimit -l)
# Used for locking the shared memory log in memory.  If you increase log size,
# you need to increase this number as well
MEMLOCK=82000

# Default varnish instance name is the local nodename.  Can be overridden with
# the -n switch, to have more instances on a single server.
INSTANCE=$(uname -n)

## Configuration with VCL
#
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"

## TEST
#
#DAEMON_OPTS="-a :80 \
#             -T localhost:6082 \
#             -f /etc/varnish/default.vcl \
#             -s malloc,512M \
#             -p lru_interval=3600 \
#             -p thread_pool_max=2000 \
#             -p listen_depth=2048 \
#             -p 'cc_command=exec cc -fpic -shared -Wl,-x -L/usr/include/libmemcached/memcached.h -lmemcached -o %o %s' \
#             -h classic,500009 \
#             -t 0"

## Alternative 3, Advanced configuration
#
# See varnishd(1) for more information.
#
# # Main configuration file. You probably want to change it :)
# VARNISH_VCL_CONF=/etc/varnish/default.vcl
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
# VARNISH_LISTEN_PORT=6081

#
# # Telnet admin interface listen address and port
# VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
# VARNISH_ADMIN_LISTEN_PORT=6082
#
# # The minimum number of worker threads to start
# VARNISH_MIN_THREADS=1
#
# # The Maximum number of worker threads to start
# VARNISH_MAX_THREADS=1000
#
# # Idle timeout for worker threads
# VARNISH_THREAD_TIMEOUT=120
#
# # Cache file location
# VARNISH_STORAGE_FILE=/var/lib/varnish/$INSTANCE/varnish_storage.bin
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
# VARNISH_STORAGE_SIZE=1G
#
# # File containing administration secret
# VARNISH_SECRET_FILE=/etc/varnish/secret
#
# # Backend storage specification
# VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
#
# # Default TTL used when the backend does not specify one
# VARNISH_TTL=120
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
# DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
#              -f ${VARNISH_VCL_CONF} \
#              -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
#              -t ${VARNISH_TTL} \
#              -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
#              -S ${VARNISH_SECRET_FILE} \
#              -s ${VARNISH_STORAGE}"
#


Nun muss du die Konfig anpassen, ich zeige hier ein Beispiel für meinen WordPress Blog… ggf. musst du für deine Webseiten jedoch noch weitere Einstellungen ändern.


vim /etc/varnish/default.vcl
backend default {
        .host = "127.0.0.1";
        .port = "8080";
}

acl purge {
        "localhost";
}

sub vcl_fetch {
        set beresp.ttl = 12h;
        set req.grace = 24h;
        if (req.url ~ "wp-(login|admin)") {
                return (pass);
        }
        if (req.url ~ "feed") {
                return (pass);
        }
        return (deliver);
        unset beresp.http.set-cookie;
        if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|txt|gz|zip|rar|bz2|tgz|tbz|html|htm|pdf|pls|torrent)$") {
                set beresp.ttl = 48h;
        }

        remove req.http.X-Forwarded-For;
        set    req.http.X-Forwarded-For = req.http.rlnclientipaddr;
        if (req.url ~ "^/w00tw00t") {
                error 403 "Not permitted";
        }
        return(deliver);
}

sub vcl_deliver {
        if (obj.hits > 0) {
                set resp.http.X-Cache = "HIT";
                set resp.http.X-Cache-Hits = obj.hits;
        } else {
                set resp.http.X-Cache = "MISS";
        }
        remove resp.http.X-Varnish;
        remove resp.http.Via;
        remove resp.http.Age;
        remove resp.http.X-Powered-By;
}

sub vcl_recv {
        set req.grace = 6h;
        if (req.request == "PURGE") {
                if(!client.ip ~ purge) {
                        error 405 "Not allowed.";
                }
                purge("req.url ~ ^" req.url "$ && req.http.host == "req.http.host);
        }
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
                remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
                set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
                set req.http.Accept-Encoding = "deflate";
        } else {
                remove req.http.Accept-Encoding;
        }
        if( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ) {
                return (pass);
        }
        if (!(req.url ~ "wp-(login|admin)")) {
                unset req.http.cookie;
        }
        if (req.request != "GET" &&
                req.request != "HEAD" &&
                req.request != "PUT" &&
                req.request != "POST" &&
                req.request != "TRACE" &&
                req.request != "OPTIONS" &&
                req.request != "DELETE") {
                return (pipe);
        }
        if (req.request != "GET" && req.request != "HEAD") {
                return (pass);
        }
        if (req.http.Authorization || req.http.Cookie) {
                return (pass);
        }
        if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|txt|gz|zip|rar|bz2|tgz|tbz|html|htm|pdf|pls|torrent)(\?.*|)$") {
                unset req.http.Authenticate;
                unset req.http.POSTDATA;
                set req.request = "GET";
                set req.url = regsub(req.url, "\?.*$", "");
                return (lookup);
        }
        unset req.http.cookie;
        return (lookup);
}

sub vcl_pipe {
        set bereq.http.connection = "close";
        if (req.http.X-Forwarded-For) {
                set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;
        } else {
                set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");
        }
}

sub vcl_pass {
        set bereq.http.connection = "close";
        if (req.http.X-Forwarded-For) {
                set bereq.http.X-Forwarded-For = req.http.X-Forwarded-For;
        } else {
                set bereq.http.X-Forwarded-For = regsub(client.ip, ":.*", "");
        }
}


Parallel müssen wir nun unseren Webserver, egal ob Apache oder in diesem Fall Nginx, auf den Port 8080 lauschen lassen.  Beim Nginx ist dies relativ simpel, du muss nur “listen 80” -> “listen 8080” ändern. Ich zeige an dieser Stelle jedoch einmal meine Nginx-Konfiguration für meinen WordPress Blog.

[stextbox id=”warning”]Wie immer gilt, erst verstehen, dann kopieren… :-)[/stextbox]

server {
        listen 8080;
        server_name suckup.de www.suckup.de blog.voku-online.de linux.voku-online.de windows.voku-online.de ubuntu.voku-online.de allgemein.voku-online.de cdn1.voku-online.de cdn2.voku-online.de cdn3.voku-online.de cdn4.voku-online.de cdn5.voku-online.de *.suckup.de;
        root /var/www/www.suckup.de/web/;
        index index.php;
        access_log /var/log/nginx/suckup.access.log main;
        error_log /var/log/nginx/suckup.error.log;
        log_not_found on;

        ## Cache - testen
        open_file_cache max=2500 inactive=24h;
        open_file_cache_valid    24h;
        open_file_cache_min_uses 2;
        open_file_cache_errors   on;

        location ~* ^.+.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)(\?[0-9]+)?$ {
                root /var/www/www.suckup.de/web/;
                access_log off;
                expires max;
                break;
        }

        ## Optimierung - "(css/js).php" to "(css/js)"
        location /wp-content/plugins/wp-special-textboxes/css/ {
                location ~* \.(css.php)$ {
                        if ($args ~* ver=(.*)$) {
                                rewrite ^ $scheme://$host/wp-content/cache/wp-special-textboxes.css? permanent;
                        }
                }
        }
        location /wp-content/plugins/wp-special-textboxes/js/ {
                location ~* \.(js.php)$ {
                        if ($args ~* ver=(.*)$) {
                                rewrite ^ $scheme://$host/wp-content/cache/wstb.js? permanent;
                        }
                }
        }
        if ($args ~* ver=3.0.1$) {
                rewrite ^ $scheme://$host/wp-content/cache/wp-special-textboxes.css? permanent;
        }

        if (-f $request_filename) {
                break;
        }
        if (!-e $request_filename) {
                rewrite ^(.+)$ /index.php?q=$1 last;
        }

        # -----------------------------------------
        # http://wiki.nginx.org/Wordpress

        ## remove any multislashes //
        if ($request_uri ~* "\/\/") {
                rewrite ^/(.*) $scheme://$host/$1 permanent;
        }

        ## Slash am Ende anfuegen ?!?
        #if ($request_uri ~* "^[\w\-\/]+[^\/?]$") {
                #rewrite ^(.*)$ $scheme://$host$1/ permanent;
        #}

        ## www eifuegen
        #if ($host !~* ^(www|subdomain)) {
                #rewrite ^/(.*)$ $scheme://www.$host/$1 permanent;
        #}

        ## www vorne entfernen
        if ($host ~* ^www\.(.*)) {
                set $host_without_www $1;
                rewrite ^(.*)$ http://$host_without_www$1 permanent;
        }

        ## immer SSL verwenden
        #rewrite ^(.*) https://$server_name$1 permanent;

        ## immer HTTP verwenden
        #rewrite ^(.*) http://$server_name$1 permanent;

        ## Feedburner
        rewrite ^/e107_plugins/rss_menu/rss.php?(.*)$ http://suckup.de/feed/ last;
        if ($http_user_agent !~ (FeedBurner|Googlebot)) {
                rewrite ^/feed/?$ http://feeds.feedburner.com/suckup last;
                break;
        }

        ## WordPress3
        #if (!-e $request_filename) {
                #rewrite ^(.+)$ /index.php?q=$1 last;
                #break;
        #}

        ## WordPress3 MU
        #if (!-e $request_filename) {
                #rewrite ^.+/?(/wp-.*) $1 last;
                #rewrite ^.+/?(/.*\.php)$ $1 last;
                #rewrite ^(.+)$ /index.php?q=$1 last;
                #break;
        #}

        ## WordPress3 Multi-Domain
        rewrite ^.*/files/(.*)$ /wp-includes/ms-files.php?file=$1 last;
        if (!-e $request_filename) {
                rewrite ^.+/?(/ms-.*) $1 last;
                rewrite ^/files/(.+) /wp-includes/ms-files.php?file=$1 last;
                rewrite ^.+/?(/wp-.*) $1 last;
                rewrite ^.+/?(/.*.php)$ $1 last;
                rewrite ^(.+)$ /index.php?q=$1 last;
                break;
        }
        location ~* ^.+.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)(\?[0-9]+)?$ {
                access_log off;
                expires max;
                root /var/www/www.suckup.de/web/;
                rewrite ^/.(/wp-.*/.*.(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js))(\?[0-9]+)?$ $1 last;
                break;
                rewrite ^.*/files/(.*(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js))(\?[0-9]+)?$ /wp-includes/ms-files.php?file=$1 last;
                break;
                if (!-e $request_filename) {
                        rewrite ^.+/?(/wp-.*) $1 last;
                        rewrite ^.+/?(/.*.php)$ $1 last;
                        rewrite ^(.+)$ /index.php?q=$1 last;
                        break;
                }
        }

        ## WordPress-Forum
        if (!-e $request_filename) {
                rewrite ^/forums/topic/(.*)$ /forums/topic.php?q=$1 last;
                rewrite ^/forums/forum/(.*)$ /forums/forum.php?q=$1 last;
                rewrite ^/forums/profile/(.*)$ /forums/profile.php?q=$1 last;
                rewrite ^/forums/view/(.*)$ /forums/view.php?q=$1 last;
                rewrite ^/forums/tags/(.*)$ /forums/tags.php?q=$1 last;
                rewrite ^/forums/rss/(.*)$ /forums/rss.php?q=$1 last;
                rewrite ^/forums/bb-admin/ /forums/bb-admin/index.php last;
                rewrite ^/forums/ /forums/index.php last;
                break;
        }

        ## WordPress W3 Total Cache
        set $totalcache_file '';
        set $totalcache_uri $request_uri;
        if ($request_method = POST) {
                set $totalcache_uri '';
        }
        if ($query_string) {
                set $totalcache_uri '';
        }
        if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
                set $totalcache_uri '';
        }
        if ($totalcache_uri ~ ^(.+)$) {
                set $totalcache_file /wp-content/w3tc-suckup.de/pgcache/$1/_default_.html.gzip;
        }
        if (-f $document_root$totalcache_file) {
                rewrite ^(.*)$ $totalcache_file break;
        }

        ## WordPress SuperCache
        #set $supercache_file '';
        #set $supercache_uri $request_uri;
        #if ($request_method = POST) {
                #set $supercache_uri '';
        #}
        #if ($query_string) {
                #set $supercache_uri '';
        #}
        #if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
                #set $supercache_uri '';
        #}
        #if ($supercache_uri ~ ^(.+)$) {
                #set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
        #}
        #if (-f $document_root$supercache_file) {
                #rewrite ^(.*)$ $supercache_file break;
        #}

        #if (!-e $request_filename) {
                #rewrite . /index.php last;
        #}

        # -----------------------------------------

        ## memchached test
        #location / {
                #default_type text/html;
                #add_header "Content" "text/html; charset=utf8";
                #charset utf-8;
                #set $memcached_key $uri;
                #memcached_pass 127.0.0.1:11211;
                #error_page 500 404 405 = @fallback;
        #}
        #location @fallback {
                #try_files $uri $uri/ @suckup;
        #}

        location / {
                try_files $uri $uri/ @suckup;
                sub_filter suckup.de:8080
                'suckup.de:80';
                sub_filter_once on;
        }

        location @suckup {
                include /etc/nginx/fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root/index.php;
                fastcgi_param QUERY_STRING q=$uri&$args;
                fastcgi_param SCRIPT_NAME /index.php;
                fastcgi_pass 127.0.0.1:11000;
        }

        location ~ \.php$ {
                try_files $uri @suckup;
                ## memchached test
                #set $memcached_key $uri;
                #memcached_pass  127.0.0.1:11211;
                fastcgi_index index.php;
                fastcgi_pass 127.0.0.1:11000;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include /etc/nginx/fastcgi_params;
        }

        ## .htaccess & .htpassword sperren
        location ~ /\.ht {
                deny  all;
        }
}

C-Programm – Steuerzeichen

“Als Steuerzeichen bezeichnet man die Zeichen eines Zeichensatzes, die keine darstellbaren Zeichen repräsentieren. (Darstellbare Zeichen sind z. B. Buchstaben, Ziffern und Satzzeichen). Ursprünglich wurden sie zur Ansteuerung von Textausgabegeräten wie Textdruckern, Telegrammgeräten oder Fernschreibern verwendet. Durch Steuerzeichen ist es möglich, Steuerungsbefehle für die Ausgabegeräte innerhalb des Zeichensatzes zu übertragen, anstatt die Steuerungsinformationen über ein anderes Protokoll zu übertragen.” – Wiki


(Einige dieser Steuerzeichen habe ich bereits in meiner .bashrc eingetragen, um den Bash-Prompt Farbe zu verleihen.)


Steuerzeichen Bedeutung
\a
BEL (bell) – akkustisches Warnsignal
\b
BS (backspace) – setzt Cursor um eine Position nach links
\f
FF(formfeed) – ein Seitenvorschub wird ausgelöst.
\n
NL (newline) – Cursor geht zum Anfang der nächsten Zeile
\r
CR (carriage return) – Cursor springt zum Anfang der aktuellen Zeile
\t
HT (horizontal tab) – Zeilenvorschub zur nächsten horizontalen Tabulatorposition (meistens acht Leerzeichen weiter)
\v
VT (vertical tab) – Cursor springt zur nächsten vertikalen Tabulatorposition
\"
” wird ausgegeben
\'
‘ wird ausgegeben
\?
? wird ausgegeben
\\
\ wird ausgegeben
\0
NULL (ist die Endmarkierung eines Strings)
\nnn
Ausgabe eines Oktalwerts (z.B. \033 = ESCAPE-Zeichen)
\xhh
Ausgabe eines Hexdezimalwerts
\033[0m
normaler Text
\033[1m
Fettschrift
\033[4m
unterstrichen
\033[30m
Schriftfarbe Schwarz
\033[31m
Schriftfarbe Rot
\033[32m
Schriftfarbe Grün
\033[33m
Schriftfarbe Gelb
\033[34m
Schriftfarbe Blau
\033[35m
Schriftfarbe Violett
\033[36m
Schriftfarbe Türkis
\033[40m
Hintergrundfarbe Schwarz
\033[41m
Hintergrundfarbe Rot
\033[42m
Hintergrundfarbe Grün
\033[43m
Hintergrundfarbe Gelb
\033[44m
Hintergrundfarbe Blau
\033[45m
Hintergrundfarbe Violett
\033[46m
Hintergrundfarbe Türkis


Es folge Beispiele, wo dies angewendet wurde…

#include <stdio.h>

main() {
    printf("\033[1m\033[31mDieser Text ist fett und rot.\033[0m\n");
    return(0);
}
#include <stdio.h>

int main() {
        printf("Dies ist ein Test und es folgt ein Zeilenumbruch\n");
        printf("\tTab einfügen und noch ein Zeilenumbruch\n");
        printf("Dieser Text wird überschrieben\r");
        printf("Das Leer \bzeichen wird entfernt");
        printf("\n\n\n");
        printf("\tJ\n");
        printf("\tu\n");
        printf("\ts\n");
        printf("\tt for\tF\n");
        printf("\t\tu\n");
        printf("\t\tn");
        return 0;
}

/* Ausgabe:

Dies ist ein Test und es folgt ein Zeilenumbruch
        Tab einfügen und noch ein Zeilenumbruch
Das Leerzeichen wird entfernt%

        J
        u
        s
        t for   F
                u
                n
*/

C-Programm – Schaltjahr Berechnung

ALGORITHMUS Schaltjahr


Beschreibung:

  • das Programm soll testen, ob eine Folge von Jahren jeweills ein Schaltjahr ist
  • wenn das Jahr größer 1582 ist
  • wenn das Jahr durch 4, aber nicht durch 100 teilbar ist, handelt es sich um ein Schaltjahr
  • ist das Jahr durch 400 teilbar, handelt es sich ebenfalls um ein Schaltjahr


Daten:

  • Jahr (Startwert)
  • Jahr (Endwert)
  • Schrittweite


Kern-(Algorithmus):

Einlesen von "Startwert" + "Endwert" + "Schrittweite"
WENN "Startwert" < 1582 ODER "Startwert" >= "Endwert" ODER Schrittweite <= 0
	DANN Fehler-Meldung
ANSONSTEN
	FÜR "Startwert" BIS "Endwert"
		WENN ("Startwert" / 4 ohne Rest UND "Startwert / 100 mit Rest) ODER ("Startwert" / 400 ohne Rest)
			DANN Ausgabe: "Ja"
		ANSONSTEN
			Ausgabe: "Nein"
		ENDE WENN
	ENDE FÜR
ENDE WENN


C-Programm:

#include "stdio.h"

int main(void) {
	int jahr_startwert,jahr_endwert,schrittweite;

	printf("\n\tK a l e n d e r\n");

	printf("\nBitte den Startwert (Jahrszahl) eingeben: ");
	scanf("%d", &jahr_startwert);

	printf("Bitte den Endwert (Jahreszahl) eingeben: ");
	scanf("%d", &jahr_endwert);

	printf("Bitte die Schrittweite (Jahre) eingeben: ");
	scanf("%d", &schrittweite);

	/* Beginn des gregorianischen Kalerndes - 1582*/
	if (jahr_startwert < 1582 || jahr_startwert >= jahr_endwert || schrittweite <= 0) {
		printf("\nFalsche Angabe!");
	} else {
		printf("\nJahr | Schaltjahr?");
		printf("\n------------------");

		for (jahr_startwert; jahr_startwert <= jahr_endwert; jahr_startwert=jahr_startwert+schrittweite) {
			if ((jahr_startwert % 4 == 0) && (jahr_startwert % 100 != 0) || (jahr_startwert % 400 == 0)) {
				printf("\n%d | Ja",jahr_startwert);
			}
			else {
				printf("\n%d | Nein",jahr_startwert);
			}
		}
	printf("\n\n");
	}
	return (0);
}