//+------------------------------------------------------------------
//|
//| Projekt              : Kapitel1 - Wie erkennt man eine Primzahl?
//|
//| Projektbeschreibung  : Es wird eine eingegebene Ganzzahl darauf
//|                      : geprueft, ob es sich um eine Primzahl handelt
//|                      :
//| Versionsnummer       : V1.00
//| Lauffähig unter      : Alle Systeme / Compiler ab ANSI-C 2011
//|
//| Autor                : Salomo Sokoll - ss@salomo-sokoll.de
//| Programmierung mit C und C++ ohne ideologischen Ballast
//| https://salomo-sokoll.de/Buch/C_CPP/index.html
//|
//+------------------------------------------------------------------

// Einbinden aller benötigten Header-Dateien (.h)
#include "stdio.h"          // Standard-Input-Output (Funktionen aus dem C-Standard)
#include "stdlib.h"         // Funktionen aus der Standard-C Bibliothek (libc)
#include "inttypes.h"       // Integer Datentypen (Wird teilweise automatisch einbebunden)


//+------------------------------------------------------------------------
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//!
//! Als erstes Argument wird eine Ganzzahl uebergeben, die darauf geprueft
//! wird, ob es sich um eine Primzahl handelt.
//+------------------------------------------------------------------------
//! Argumente :
//! \param [in] argc        - Anzahl der übergebenen Argumente
//! \param [in] *argv[]     - Liste aller Argumente als Zeiger im C-Stil
//!
//+------------------------------------------------------------------------
//! Rückgabewert :
//! \return int             - Fehlercode (0 für alles OK, kein Fehler)
//!
//+------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
    // *
    // ** Wurden ueberhaupt Argumente uebergeben?
    // ** Pruefe die Anzahl der uebergeben Argumente
    // ** Es muss mindestens ein Argument uebergeben werden.
    //
    if ( argc < 2 )
    {
        // In der ersten Variablen argc ist die Anzahl der uebergebenen Argumente angegeben.
        // Die Anzahl ist mindestens ein Argument, das erste Argument ist der Dateiname
        // ueber den das Programm aufgerufen wurde, dieser Eintrag existiert immer.

        // Wenn kein zusaetzliches Argument uebergeben wurde, wird eine Hilfemeldung ausgegeben.
        printf( "Aufruf:\n" );
        printf( "%s < Ganzzahl >\n\n", argv[ 0 ] ); // Zu argv siehe den Kommentar, etwas tiefer
        printf( "Die angegebene Zahl (2 ... 999999) wird darauf geprueft,\n");
        printf( "ob es sich um eine Primzahl handelt.\n" );

        // Das Programm wird beendet
        return( 0 );
    }

    // *
    // ** Die zweite Variable enthaelt eine Liste (Array) von Zeigern auf
    // ** jedes einzelne Argument hinter dem Programmnamen.
    // ** Wie immer in C, beginnt der Index ab dem Wert 0 (Null)
    // ** Der Stern vor dem Variablenname "char *argv[]" besagt, es handelt sich um eine Liste
    // ** aus Zeigern (Pointer), die auf die eigentlichen Texte zeigen. jeder Eintrag ist vom
    // ** Typ char mit einem Null-Terminator. Die Speicherverwaltung uebernimmt in diesem Fall das
    // ** Betriebssystem.
    // *

    // *
    // ** Pruefe ob das 2. Argument vorliegt?
    // ** Sind alle Argumente gueltig?
    // *
    if (
        ( argc >= 2) &&         // Mindestens zwei Argumente wurden uebergeben
        ( argv[ 1 ] != NULL )   // Die Speicheradresse ist ein gueltiger Zeiger
        )
    {

        // Benoetigte Variablen
        int32_t     Zahl;                   // Die Konvertierte Ganzzahl
        char        *Eingabe = argv[ 1 ];   // Anfangsadresse im Speicher
        char        *Ende = NULL;           // Wie weit wurde die Zahl abgearbeitet?

        // Konvertiere das 2. Argument in eine vorzeichenbehaftete Ganzzahl auf der Basis von 10
        Zahl = strtol( Eingabe, &Ende, 10  );

        // Wenn Eingabe und Ende auf die selbe Adresse Zeigen, wurde kein Text uebergeben
        if ( Eingabe == Ende )
        {
            printf( "*** Es wurde kein Text eingegeben...\n" );

        }

        // Wenn die Adresse in Ende nicht auf den abschliessenden Null-Terminator zeigt
        // wurde die konvertierung abgebrochen, z.B. durch ein falsches Zeichen
        else if ( *Ende != '\0' )
        {
            printf( "*** Es wurde keine gueltige Zahl eingegeben...\n" );

        }

        // Ist die Zahl zwischen 2 und 999999
        else if (
            ( Zahl < 2 ) ||
            ( Zahl > 999999 )
            )
        {
            printf( "*** Die Zahl muss zwischen 2 - 999999 liegen...\n" );

        }
        else
        {
            // Die Zahl erfuellt alle kriterien, pruefe auf eine Prinzahl
            printf( "Pruefe die Zahl %d ...", Zahl );

            // *
            // ** Pruefe, ob die angegebene Zahl eine Prinzahl ist
            // *

            // Sonderlocken ... (Die Zahl 2 selbst)
            if ( Zahl == 2 )
            {
                printf( " ist eine Primzahl.\n" );

            }

            // Sonderlocken ... Vielfaches von 2
            else if ( ! ( Zahl % 2 ) )
            {
                printf( " ist keine Primzahl.\n" );

            }
            // Pruefung auf eine Prinzahl
            else
            {
                int32_t s; // Schleifenvariable

                // Durchlaufe alle Zahlen von 3 bis zum eingegebenen Wert in Schritten von je 2
                for( s = 3; s < Zahl; s += 2 )
                {
                    // Wenn der Modulus von Zahl geteilt durch s 0 (Null) ist, ist es keine Primzahl,
                    // Abbrechen
                    if ( ! ( Zahl % s ) )
                    {
                        printf( " ist keine Primzahl.\n" );

                        // Programm vorzeitig beenden
                        return( 0 );
                    }

                }

                // Es wurde kein Modulus mit 0 gefunden, also ist die angegebene Zahl eine Primzahl
                printf( " ist eine Primzahl.\n" );

            }

        }

    }
    else
    {
        // Es ist ein Problem beim auslesen der Argumente aufgetreten!
        printf( "Problem bein Auslesen der Argumente *** Abbruch!\n" );

    }

        // Das Programm regulaer beenden
    return( 0 );
}

