FAQs – Andere Programmiersprachen

FAQs – Andere Programmiersprachen

Was ist der Unterschied zwischen Structs und Klassen?

Ein Struct ist genauso wie eine Klasse ein Datentyp. Ein Struct funktioniert wie ein Container der mehrere Datentypen enthalten kann. Damit ist es möglich, komplexe Datentypen zu erzeugen.

Eine Klasse kann genauso wie ein Struct ein Container für verschiedene Datentypen sein. Darüber hinaus kann eine Klasse Methoden enthalten.

Ein Struct beschreibt also eine Menge von Zuständen. Eine Klasse beschreibt Zustände und Verhalten.

Beispiel:

Java: Die Klasse Article beschreibt den Zustand (description, price, weight) und das Verhalten printArticle() eines Objekts.

public class Article {

    String description;
    int price;
    double weight;

    void printArticle() {
        System.out.printf("%-20s %5d€ %5.2fkg\r\n", description, price, weight);
    }
}

// Anwendung:

Article a1 = new Article();
a1.description = "Java-Buch";
a1.price = 20;
a1.weight = 0.48;

a1.printArticle();

C: Der Struct Article beschreibt die Zustände description, price, weight. Im Gegensatz zum Java-Beispiel besitzt die Instanz a1 des Structs kein Verhalten. Die Methode printArticle() ist kein Bestandteil des Structs. Will man also in der Methode printArticle() auf die Werte des Structs zugreifen, muss beim Methodenaufruf ein Pointer auf das Struct als Argument übergeben werden (Zeile 19).

#include <stdio.h>

typedef struct {
    char *description;
    int price;
    double weight;
} Article;

void printArticle(Article *a){
    printf("%-20s %5d€ %5.2fkg\r\n", a->description, a->price, a->weight);
}

// Anwendung:

Article a1;
a1.description = "Java-Buch";
a1.price = 20;
a1.weight = 0.48;
printArticle(&a1);

Warum kann eine Funktion nur einen Wert zurückgeben und nicht mehrere?

In Java ist das durch Designentscheidungen, die von den Entwicklern und Entwicklerinnen der Sprache getroffen wurden, festgelegt. In anderen Programmiersprachen wurden diesbezüglich andere Konzepte entwickelt.

In den folgenden Implementierungen wird verglichen, wie Methoden zur Zerlegung von Minuten in Stunden und Minuten umgesetzt werden können.

In Python kann eine Funktion mehrere Werte zurückgeben. Die zwei Werte h und m werden gesetzt, zurückgegeben und den Variablen stunden und minuten zugewiesen.

Python:

def m_to_hm(x):
    m = x % 60
    h = x // 60
    return h, m

stunden, minuten = m_to_hm(175)
print(str(stunden) + ':' + str(minuten))

# Ausgabe: 2:55

In C# gibt es den Mechanismus des out-Parameters. In der Main-Methode werden zwei out-Parameter für Stunde (h) und Minute (m) festgelegt, übergeben und in der Methode m_to_hm() gesetzt.

C#:

static void m_to_hm(int x, out int h, out int m) {
    m = x % 60;
    h = (int)(x / 60);
}

static void Main(string[] args) {
    int h, m;
    m_to_hm(175, out h, out m);
    Console.WriteLine(h + ":" + m);
}
// Ausgabe: 2:55

Allerdings wird die Rückgabe von mehreren Parametern in unterschiedlichen Programmiersprachen oft so realisiert, dass mehrere Parameter implizit zusammengefasst werden, – in Python beispielsweise in ein Tupel. In Java kann man mehrere Parameter zurückgeben, indem man sie in ein Objekt oder Array verpackt.

Java:

class Time {
    final int h, m;

    Time(int h, int m) {
        this.h = h;
        this.m = m;
    }
}

static Time m_to_hm(int x) {
    return new Time(x / 60, x % 60);
}

public static void main(String[] args) {
    Time t = m_to_hm(175);
    System.out.println(t.h + ":" + t.m);
}
// Ausgabe: 2:55

Was ist der Unterschied zwischen “continue” and “break” and “pass”?

Mit der break-Anweisung wird eine Schleife abgebrochen. Der Schleifenkörper wird verlassen und der Programmlauf mit der Instruktion unterhalb der Schleife fortgesetzt.

Mit der continue-Anweisung wird eine Schleifeniteration abgebrochen und mit der nächsten weiter gemacht.

Mehr dazu findest du hier.

In Python gibt es die pass-Anweisung. Diese Anweisung bewirkt nichts. Sie wird als Platzhalter an Stellen verwendet, an denen aus syntaktischen Gründen eine Anweisung erwartet wird.

Was sind Pointer? Worauf zeigen Pointer? Was ist wenn ich den Wert ändere?

Wird in einem Programm auf einen Wert zugegriffen, erfolgt das implizit über eine Speicher-Adresse. Der Zugriff auf eine Speicheradresse kann mit einem Pointer (Zeiger) erfolgen. Man sagt auch, ein Pointer zeigt auf eine Speicheradresse.

In C haben Pointer einen Typ. Die Deklaration: int *p; kann man lesen als: *p ist vom Typ int, p ist ein Zeiger auf den int-Wert *p. Mit *p kann also auf den int-Wert, auf den der Zeiger p zeigt, zugegriffen werden.

C:

int a, *pa;
a = 123;
pa = &a;
*pa = 456;
printf("%d %d %p\n", a, *pa, pa); // Ausgabe: 456 456 0028fee0

In Zeile 1 wird die int-Variable a sowie ein Zeiger pa auf eine int-Variable deklariert.
In Zeile 3 wird mit dem Adressoperator (&) die Adresse von a bestimmt und dem Zeiger pa zugewiesen. Man sagt, der Zeiger pa zeigt auf a.
In Zeile 4 wird mit dem Inhaltsoperator / Dereferenzierungsoperator (*) der Wert an der Speicherstelle, auf die der Zeiger pa zeigt, verändert. a hat jetzt den Wert 456.
In Zeile 5 wird a, der Inhalt auf den pa zeigt, sowie die Speicheradresse auf die pa zeigt, ausgegeben.

Zeiger auf Arrays:

int *p;
int ar[] = { 1, 4, 9, 16 };
p = ar;
printf("%d %p\n", *p, p); // 1 0028fee0
p++;
printf("%d %p\n", *p, p); // 4 0028fee4

In Zeile 1 wird ein Pointer vom Typ int angelegt.
In Zeile 2 wird das Array ar[] deklariert und initialisiert.
In Zeile 3 wird der Pointer p auf das Array ar[] gesetzt. D.h. p enthält die Speicheradresse von ar[0]. Als Synonym für den Code-Sequenz p = ar; könnte man also theoretisch auch die Code-Sequenz p = &ar[0]; verwenden.
In Zeile 4 wird der Wert von ar[0] und die Speicheradresse von ar[0] ausgegeben.
In Zeile 5 wird der Zeiger p inkrementiert. Er zeigt jetzt also auf ar[1].
In Zeile 6 wird der Wert von ar[1] und die Speicheradresse von ar[1] ausgegeben.

Vergleicht man die zwei ausgegebenen Speicheradressen, sieht man, dass die Differenz 4 beträgt. Dieser Wert entspricht der Byte-Breite eines int-Wertes im Speicher.

Beispiel Pointerarithmetik:

Mittels Pointer und Pointer-Arithmetik lassen sich verschiedene Algorithmen sehr kompakt formulieren. Im folgenden Code-Sample wird eine Methode zur Bestimmung der Länge eines Strings gezeigt.

int strlen(char *s) {
    int len = 0;
    while (*s++) {
        len++;
    }
    return len;
}

Der Methode strlen() wird ein Zeiger auf eine Zeichenkette übergeben.

In Zeile 3 wird mit dem Inhaltsoperator auf das aktuelle Zeichen zugegriffen und als Schleifenbedingung verwendet. Im Anschluss daran wird der Zeiger inkrementiert. Wenn der Zeiger auf das Terminierungssymbol der Zeichenkette zeigt, wird die Schleife beendet. In jedem Iterationsschritt wird der Zähler für die Länge der Zeichenkette um 1 erhöht und nach Beenden der Schleife als Rückgabewert verwendet.

Anmerkung:

Zeichenketten werden in C durch char-Arrays die null-terminiert sind dargestellt. Das letzte Zeichen einer null-terminierten Zeichenkette hat den ASCII-Code 0 (‘\0’). In C gibt es keinen Datentyp für Wahrheitswerte. Der Wert 0 wird in einem boolschen Ausdruck auf false evaluiert. Alle anderen numerischen Werte werden auf true evaluiert.

Beispiel: Inhaltsoperator / Adressoperator:

Der Inhaltsoperator verhält sich invers zum Adressoperator.

*(&a) ≡ a

Was sind Module? Wie installiere ich Sie?

Module in Python sind Code-Bibliotheken. Sie werden mit dem Paketverwaltungsprogramm pip (pip installs packages) installiert. Eine Anleitung dazu findest du hier.

Listen und Tupel in Python. Was sind die Gemeinsamkeiten / Unterschiede?

Listen und Tupel sind geordnete und indizierbare Datenstrukturen. Listen sind veränderbar. Das heißt, man kann Elemente hinzufügen, entfernen oder modifizieren. Tupel sind nicht veränderbar.

Um Veränderungen an einem Tupel vorzunehmen, muss man den Umweg über eine Liste gehen:

a = ("Apfel", "Banane", "Zitrone")
b = list(a)
b[2] = "Kirsche"
a = tuple(b)
print(a) # ('Apfel', 'Banane', 'Kirsche')

In Zeile 1 wird ein Tupel a angelegt. Um ein Element des Tupels ändern zu können, wird aus dem Tupel in Zeile 2 die Liste b erzeugt. In Zeile 3 wird ein Listenelement verändert. In Zeile 4 wird aus der Liste wieder ein Tupel erzeugt und der Variable a zugewiesen.

Wie füge ich ‘nested lists’ in Python zusammen?

Das Zusammenfügen von nested-lists funktioniert genauso, wie bei einfachen Listen:

a1 = [[1, 2], 3]
a2 = [["Apfel","rot"], ["Banane", "gelb"]]

a3 = a1 + a2
print(a3) # [[1, 2], 3, ['Apfel', 'rot'], ['Banane', 'gelb']]

a4 = [a1, a2]
print(a4) # [[[1, 2], 3], [['Apfel', 'rot'], ['Banane', 'gelb']]]

In Zeile 4 werden die Listen a1 und a2 mit dem +-Operator zusammengefügt. Die Elemente der Listen a1 und a2 werden in einer neuen Liste a3 gespeichert. Die Liste a1 enthält 2 Elemente, wobei ein Element wieder eine Liste ist. Die Liste a2 enthält 2 Elemente. Die zusammengefügte Liste a3 besteht daher aus 4 Elementen.

In Zeile 7 wird eine neue Liste a4 erzeugt, mit a1 als erstes Listenelement und a2 als zweites Listenelement.

Welche Bedeutung haben Zeiger und Referenzen bei Arrays?

In verschiedenen Programmiersprachen werden Pointer- oder Zeigerkonzepte umgesetzt. In C beispielsweise beschreibt ein Pointer auf ein Array eine Adresse im Speicher, an der der Wert des Arrayelements mit dem Index 0 abgespeichert ist.

Pointer-Arithmetik:
Inkrementiert man beispielsweise in C den Pointer auf ein Array um eins wird auf den Wert des nachfolgenden Arrayelements gezeigt. Details dazu findet man in unserer FAQ hier.

In Java wird nicht mit Pointern sondern mit Referenzen gearbeitet. Auch eine Referenz bezieht sich auf eine Speicheradresse. Allerdings gibt es für Referenzen keine arithmetischen Operationen.

Wie funktioniert das __init__ in Python?

Die Methode __init__() wird beim Erzeugen eines Objekts aufgerufen.

Im folgenden Beispiel sieht man, wie diese Methode zum Initialisieren eines Objekts eingesetzt wird. Im Unterschied zu anderen objektorientierten Programmiersprachen besitzt jede Objekt-Methode in Python einen Parameter über den die Objektreferenz übergeben wird. Im Code-Beispiel hat diese Referenz den Namen self.

class Person:

  def __init__(self, name, age):
    self.name = name
    self.age = age
    
  def print(self):
    print(self.name + " ist " + str(self.age) + " Jahre alt.")


p = Person("John", 36)
p.print()

Ist Javascript eine einfache Variante von Java?

Nein.

Java und Javascript sind prozedurale und objektorientierte Programmiersprachen. Der Umgang mit verschiedenen Konzepten wie Schleifen und Exceptions sind in beiden Sprachen ähnlich.

Javascript ist – im Unterschied zu Java – keine typisierte Sprache. D. h. Variablen werden dynamisch typisiert, indem man ihnen Werte eines Typs zuweist. Außerdem wird Javascript nicht kompiliert sondern interpretiert. Das hat zur Folge, dass viele Programmierfehler, die in Java schon beim Compilieren erkannt werden, in Javascript erst zur Laufzeit sichtbar werden.

Javascript wird hauptsächlich für die Webentwicklung verwendet.

Wie führe ich ein Python-Programm mit einem Argument in der Konsole aus?

Zuerst wird auf der Konsole ins Verzeichnis navigiert, in dem sich die auszuführende Python-Datei befindet. Dann gibt man die Anweisung python <dateiname> <argument> ein.