[C++] Zeiger auf 2D-Arrays

Im Zuge meiner Implementierung der Software für mein Matrixlicht hatte ich vor eine Routine zu schreiben, die es mir erlaubt von der ID des Musters, welches per DIP-Schalter ausgewählt werden kann, automatisiert auf das zugehörige 2D-Array zu schließen.

Nach einiger Recherche kam ich auf diesen Code:

int pattern0[X][Y] = {...};

/* N: Anzahl der Elemente im Pointer-Array */
int (*pattern_collection[N])[X] = {pattern0,...};

/* A: Index des Elements aus dem Pointer-Array */
int *p_selected_pattern = reinterpret_cast<int*>(*(pattern_collection + A) + X);

/* Prints pattern0[1][1] if Y is set to 0 and X to 0 */
std::cout << *(p_selected_pattern + Y) << std::endl;

EDIT: Es gab einige Fehler im Code, diese wurden berichtigt.

Werbeanzeigen

INT zu BCD Algorithmus

In der Ausbildung kamen wir an einen Punkt, wo wir einen Zahlenwert in die BCD-Schreibweise überführen mussten. Bevor ich erfahren habe, dass die SPS-Software einen vorgefertigten Baustein hat, habe ich mir selber einen Algorithmus ausgedacht.

Der Algorithmus für Zahlen von 0-99 ist wie folgt aufgebaut:

\text{I} = \text{int}(\frac{x}{10})

\text{II} = x - (\text{I} \cdot 10)

\text{III} = (\text{I} << 4)

\text{IV} = \text{II} + \text{III}

Als Rust-Programm:

fn int_to_bcd(x: i32) -> i32 {
    let tenths: i32;
    tenths = (x / 10) as i32;
    let ones: i32;
    ones = x - (tenths * 10);
    let shifted_tenths: i32;
    shifted_tenths = tenths << 4;
    shifted_tenths + ones
}

Als Funktionsblockdiagramm:

screenshot_20170111_180821

Dokumentation 2 Go

Ich habe vor kurzem entschieden aus einem Projekt auszutreten und war gezwungen meinen Code zu dokumentieren. Ich suchte nach Tools, um mir das Leben einfacher zu machen. Da ich einen Teil des Codes bereits mit docstrings kommentiert habe, konnte ich hier mit apigen eine ansehnliche PHP-Dokumentation basteln.

Da das aber nicht alles war, was ich dokumentieren musste, bin ich zu http://sphinx-doc.org gekommen. Sphinx ist ein wunderbares Tool und ich hatte es schnell aufgesetzt und die ersten Seiten geschrieben. Tmux und Vim machten dies unfassbar schnell möglich.

Um die Dokumentation schöner zu gestalten, habe ich das ReadTheDocs-Theme benutzt und ein paar Tricks von ReadTheDocs und anderen Quellen genutzt, um die Dokumentation effektiver zu gestalten.

Das Hinzufügen neuer Seiten ist unglaublich einfach und ich habe so viel Zeit gespart, die ich sonst mühselig in LibreOffice verbracht hätte.

Obwohl ich sagen muss, dass ich bei ` und ^ die Taste zweimal drücken muss, und so Überschriften dritten Gerades etwas mühselig sind, bin ich zufrieden.

REST-CodeSchnipsel: RestRecipes

Vor kurzem ist bei mir die Notwendigkeit nach eine REST API aufgekommen und ich wollte keine großen Frameworks dafür nutzen, die viel zu viel Overhead mitliefern.

Aus dem Grund habe ich mir selber eine kleine Sammlung an Hilfsklassen erstellt, die mir das Leben einfacher machen. Die Sammlung habe ich RestRecipes getauft.

Zu finden unter: https://github.com/maikwoehl/rest-recipes

Nutzbar wie folgt:

require_once "RestRecipes/autoload.php";

use RestRecipes\Router;

$app = new Router();

$app->route("/order/<id>", "GET", function($id) {
    // Fancy stuff with $id
});

$app->route("/order/<id>", "PUT", function($id, $data) {
    // Fancy stuff with $id and $data
});

$app->route("/order/<id>", "POST", function($id, $data) {
    // Fancy stuff with $id and $data
});

$app->route("/order/<id>", "DELETE", function($id) {
    // Fancy stuff with $id
});

Das ganze kann auch per Composer im eigenen Projekt eingebunden werden:

~$ composer require maikwoehl/rest-recipes

Objektorientierung in PHP

Die  Web-Skriptsprache PHP ist an sich ja schon in einigen Kreisen verpönt, aber ich habe zugestimmt eine einfache Web-Shop Software für einen Freund zu programmieren.
Natürlich habe ich nicht vor xt:commerce nachzuprogrammieren, aber etwas kleines und feines sollte es schon sein. Also habe ich mich drangesetzt und mich in OOP mit PHP eingearbeitet und war erst beeindruckt und an einigen Stellen enttäuscht. Meine Erfahrungen möchte ich in diesem Beitrag teilen.

Interfaces

Interface heißt auf Deutsch Schnittstelle und ist das, was es bedeutet. Ein Interface bietet eine Schnittstelle zu einem Projekt und ihren Objekten. Entscheidet sich ein Programmierer dazu, solch ein Projekt zu modifizieren, dann kann der ein Interface implementieren und stellt damit sicher, dass das Projekt die gleichen Signaturen vorfindet.

Nicht nur ein anderer Programmierer, sondern auch man selber profitiert von Interfaces, weil diese Flüchtigkeitsfehler schnell aufdecken können.

Lange Rede, kurzer Sinn: Ein Interface wird wie folgt geschrieben:

interface iMyClass {
  public function sampleMethod();
  public function exampleMethod($someVariable);
}

Klassen

Klassen im einfachen Sinne sind Baupläne für Objekte. Auch hier ist PHP mittlerweile gut dabei, denn Type Hinting erlaubt es einem, bestimmte Variablen an Typen zu binden. Mehr dazu in der PHP-Dokumentation.

class MyClass implements iMyClass {
  public $someProperty;
  public array $someArrayProperty;
  public AnotherClass $someAnotherClassProperty;

  protected $someProtectedProperty;
  private $somePrivateProperty;

  public function __construct()
  {
    // Constructor
  }

  public function getSomeProperty()
  {
    return $this->someProperty;
  }

  public function setSomeProperty($someProperty)
  {
    $this->someProperty = $someProperty;
  }
}

Das ist ja alles schon ganz nett. Doch kommen wir jetzt zu den Ärgernissen.

Ärgernis 1: Überladung von Konstruktoren

Ab und zu kommt es vor, dass man Konstruktoren überladen möchte. In PHP ist es nicht möglich eine Methode innerhalb einer Klasse zweimal zu deklarieren. Dadurch kommt ein typisches Überladen, wie man es aus Java oder C# kennt, nicht infrage.

Vielmehr muss hier zu einem Trick gegriffen werden, der in der PHP-Dokumentation in einem Kommentar erklärt wird.

Ärgernis 2: Überladung von Methoden

Das Überladen von Methoden ist auch etwas umständliches in PHP. Hier muss zu sogenannten Magic Methods gegriffen werden. In diesem Fall werden diese über __call() aufgerufen.

class AnotherClass {
    public function __call($name, $arguments)
    {
        if ($name == "someFunction")
        {
              switch (count($arguments))
              {
                  case 0:
                      // Do something
                      break;

                  case 1:
                     // Do something different with one Argument
                     break;
              }
        }
    }
}

Das ist eine Möglichkeit an die Sache heranzugehen. Es gibt aber noch mehr. Welche man nutzt, liegt beim persönlichen Geschmack.

Fazit

Wenn ich nicht müsste, dann würde ich nicht in PHP programmieren. Wider Erwarten hat sich PHP in den letzten Jahren zu einer anderen Sprache entwickelt. Es ist für mich zu einer Skriptsprache geworden, die ich nicht mehr allzu sehr verabscheue. Auch wenn es wahrscheinlich ein Großteil an Erfahrung ist, der in diese Erkenntnis einfließt.

TypeScript Entwicklungsworkflow

Seit ein paar Tagen stelle ich meinen Entwicklungsworkflow für HTML5-Applikationen um. Ich nutze jetzt viel mehr TypeScript und möchte mir das Entwickeln damit natürlich erleichtern. Zum Glück bietet der TypeScript Compiler einige Features, die einem dabei helfen.

Zu aller erst:

~$ tsc --init

Mit diesem Befehl wird eine Datei mit dem Namen tsconfig.json angelegt. Nach dieser Datei sucht der TypeScript Compiler automatisch und führt den darin beschriebenen Kompiliervorgang aus.

~$ tsc -w

Dieser Parameter veranlasst tsc dazu, das Verzeichnis zu überwachen und bei jeder gespeicherten Änderung die Datei(en) neu zu kompilieren.

~$ tsc -d

TSC bietet außerdem die Möglichkeit aus dem Projekt Definitionen zu erzeugen, damit fremde Programmierer Statement Completion nutzen können, ohne die TypeScript-Datei zu laden.

Visual Studio Code und eigene TypeScript Definition Files

Vor kurzem bin ich über Visual Studio Code gestolpert und bin angenehm überrascht. Ich hätte nicht gedacht, dass Microsoft es wirklich schafft, die Annehmlichkeiten einer großen IDE in einen leichtgewichtigen Editor zu verpacken.

Nun habe ich begonnen VSCode auch im Alltag einzusetzen. Ich bin damit deutlich schneller unterwegs als mit Brackets. In den letzten Tagen habe ich meine Vertretungsplan-Webapp erweitert und wollte jetzt für meine Vertretungsplan-Bibliothek, die ich geschrieben habe, TypeScript Definition Files anlegen. Mit denen kann VSCode die IntelliSense-Dienste anbieten.

Nach einigem hin und her und ganz viel Gesuche habe ich endlich die Lösung des Rätsels gefunden. Und ich musste einen Fehler akzeptieren.
Das alte Resultat ist folgendes:

interface VP {
    new (webViewElementID: string): VP;
    prototype: VP;
     
    username: string;
    password: string;
    webView: string;
    classID: number;
    CW: number;
    genericPlanStart: string;
    genericTeacherPlanStart: string;
    classList: string[];
    teacherList: string[];
    roomList: string[];
    teacherMode: boolean;
     
    setType(type: string): void;
    navigate(): void;
    getCurrentCW(): number;
    retrieveClassList(): void;
    parseRawData(newRawData: string): void;
    parseTeacherRawData(newRawData: string): void;
    getClassList(listType: string): string[];
    setClassID(id: number): void;
    parseClassID(): string;
}
 
declare var Vertretungsplan: VP;
 
declare var classFavList: string[];
declare var classList: string[];
declare var isFaved: boolean; 
declare var isAlreadyFav: boolean;
declare var classID: number;
 
declare function refreshFavListSelector(): void;

Hier die d.ts-Datei für lose Typen-Definitionen:

declare var classFavList: string[];
declare var classList: string[];
declare var isFaved: boolean; 
declare var isAlreadyFav: boolean;
declare var classID: number;

declare function refreshFavListSelector(): void;
declare function getWeekNumber(): number;
declare class VertretungsplanTP {
    webView: string;
    classID: number;
    CW: number;
    currentType: string;
    genericPlanStart: string;
    genericTeacherPlanStart: string;
    bigPlanEnding: string;
    classList: string[];
    teacherList: string[];
    roomList: string[];
    teacherMode: boolean;
    username: string;
    password: string;
    constructor(webViewElementID: string);
    setType(type: string): void;
    navigate(): void;
    getCurrentCW(): number;
    retrieveClassList(): void;
    parseRawData(newRawData: any): void;
    parseTeacherRawData(newRawData: string): void;
    getClassList(listType: string): void;
    setClassID(id: number): void;
    parseClassID(): string;
}

Mit dieser Datei bot mir VSCode endlich IntelliSense-Dienste für meine Bibliothek an. Wenn man seine Bibliothek nicht gerade selber mit TypeScript schreibt und danach kompilieren lässt, dann ist das hier eine nützliche Methode, um IntelliSense-Unterstützung für eigene JS-Dateien zu bekommen.

Eventuell werde ich die Klasse in TypeScript neu implementieren, das ist aber grundsätzlich nicht nötig.


Nachtrag: Ich habe nun die Klasse in TypeScript neu implementiert und habe die Definitionen nun in zwei d.ts-Dateien aufgeteilt. Eine Definition beinhaltet lose Funktionen und Variablen innerhalb der App und die andere wird mit tsc generiert und beinhaltet die Deklarationen und Typen-Definitionen der Vetretungsplan-Klasse.