🤪 Kapitel 1.06.2 - Wie erkennt man eine Primzahl?

Anfang der 1990’er Jahre hat Karl Bihlmeier eine Comicfigur entwickelt, die bei Amiga Fans zum Kult wurde.
Es war „Hermann der User“, er beschäftigt sich mit den typischen Problemen eines Computer-Nerd in und mit seinem Umfeld.
Veröffentlicht wurden diese unter anderem im „Amiga Magazin“ des Markt & Technik Verlags.
Vielen Dank an Karl Bihlmeier für die Erlaubnis zur Veröffentlichung 😉
Es war „Hermann der User“, er beschäftigt sich mit den typischen Problemen eines Computer-Nerd in und mit seinem Umfeld.
Veröffentlicht wurden diese unter anderem im „Amiga Magazin“ des Markt & Technik Verlags.
Vielen Dank an Karl Bihlmeier für die Erlaubnis zur Veröffentlichung 😉
🤪 Kapitel 1.06.2 - Wie erkennt man eine Primzahl?
Eine ↗ Primzahl ist eine Zahl, die nur durch eins und sich selbst teilbar ist. Wie kann ich jetzt eine gegebene Ganzzahl prüfen, ob diese eine Primzahl ist?Das vorgestellte Programm akzeptiert eine Ganzzahl zwischen 2 und 999999 und prüft die angegebene Zahl, ob es sich um eine Primzahl handelt.
Zuerst werden zwei einfache Prüfungen durchgeführt zum einen, ob die eingegebene Zahl die Zahl 2 ist und zum andern ob die Zahl durch zwei teilbar ist. Laut der mathematischer Definition gilt die Zahl 2 als Primzahl und alle durch zwei teilbare Zahlen sind somit keine Primzahlen mehr.
🤔 Die Zeilen 1 - 15
Der Kopf des Programms als Kommentar.//+------------------------------------------------------------------
//|
//| 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
//|
//+------------------------------------------------------------------
//|
//| 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
//|
//+------------------------------------------------------------------
🤔 Die Zeilen 18 - 20
Mit dem #include Keyword werden so genannte Header-Dateien eingebunden. Diese enthalten meist Prototypen für Funktionen, Konstanten oder (oft in älterem Code) auch Makros.Alle Keywords die mit einem Hash beginnen, werden vom Präprozessor verarbeitet.
// 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)
#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)
🤔 Die Zeilen 23 - 40
Der Einsprung Punkt in jedem C-Programm - Diese Funktion muss immer existieren, sonst meldet der Linker einem Fehler, das die main() Funktion fehlt.Es wird die erweiterte Variante der main() Funktion genutzt. Vom Terminal wird jetzt die zu prüfende Zahl entgegengenommen und ausgewertet.
Die Variable argc enthält die Anzahl der auf dem Terminal übergebenen Argumente. Laut C-Standart ist dies mindestenes ein Argument. Nämlich das erste Argument ist immer der Dateiname des eigenen Binärcodes.
Die Liste (Array) argv[] besteht aus jedem Argument als normale C-Zeichenkette. Siehe nächsten und übernächsten Absatz.
//+------------------------------------------------------------------------
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! 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[] )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! 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[] )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
🤔 Die Zeilen 41 - 60
Mit dem if Keyword wird geprüft, ob genug Argumente übergeben wurden (Variable argc). Sollten weniger Argumente angegeben worden sein, wird ein Hilfstext ausgegeben. Dieser beschreibt, wie das Programm aufzurufen ist und welche Bedingungen existieren wie zum Beispiel, dass die angegebene Zahl ein Wert zwischen zwei und 1 Million haben muss. Nach der Ausgabe des Textes wird das Programm regulär über das return Keyword beendet mit Statuscode 0 also es ist kein Fehler aufgetreten.Der Platzhalter %s in der printf() Funktion steht für einene Zeichenkette, diese wird in der Argumentenliste duch den Programmnamen ersetzt. Das erste Element (Das erste Elenent ist immer der 0. Index) in der Array-Liste argv[ 0 ]
// *
// ** 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 );
}
// ** 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 Zeilen 62 - 80
Die Variable argv ist eine Liste (Array) aller übergebener Argumente.Das if Keyword prüft jetzt zwei Punkte - Ob mindestens zwei Argumente übergeben worden und ob der zweite Eintrag in argv eine gültige Adresse ist. Wie immer in C, beginnt der Index ab dem Wert 0 (Null). Was eine gültige Adresse ist, ist in C etwas schwammig definiert, die Binäre Null gilt als illegale Adresse und wird im Programmen benutzt, als Platzhalter, um festzustellen oder festzulegen, dass es sich hier um eine undefinierte Adresse handelt, die noch auf keinen gültigen Speicherbereich weist. Für ungültige Adressen gibt es die Konstante NULL - was intern nichts anderes ist als eine Binäre Null mit dem Datentyp eines Zeigers (Pointer).
Beide Bedingungen des if Keywords sind mit einem logischen UND Verknüpft && - Das Bedeutet, das beide Bedingungen "Wahr" sein müssen, damit die komplette Bedingung "Wahr" ist.
// *
// ** 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
)
{
// ** 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
)
{
🤔 Die Zeilen 82 - 88
Die übergebenen Zahl wird jetzt in eine Ganzzahl konvertiert und dabei wird geprüft, ob es sich wirklich um eine Zahl handelt oder ob um illegale Zeichen mit zum Beispiel Buchstaben oder irgendwelche Sonderzeichen mit enthalten sind. In diesem Fall wird die Konvertierung abgebrochen.Dazu werden drei Variablen benötigt zum einen eine Variable für die konvertierte Zahl selbst, diese heisst Zahl und ist als vorzeichenbehaftete 32 Bit Zahl deklariert int32_t.
Die Variable Eingabe enthält die Anfangsadresse der übergebenen Zeichenkette, die Variable wird mit dem Eintrag im 2. Element der argv-Liste gleichgesetzt (Index 1). Als Datentyp ist char * angegeben, was Bedeutet, das es sich hierbei um einen Zeiger (Pointer) auf einen Text handelt.
Die Variable Ende wird ebenfalls auf den Datentyp char * gesetzt und mit NULL vorinitialisiert.
Dann wird die Funktion strtol() aufgerufen, welche einen gegebenen Text in eine Binäre Ganzzahl konvertiert, mit einfachen Prüfungen.
Der Variablen "Zahl" wird das Ergebnis der Funktion strtol() zugewiesen, dieser Funktion müssen drei Argumente übergeben werden.
Eingabe - Ein Zeiger auf die zu konvertierende Zahl.
Ende - Ein Zeiger auf eine Variable in der die Adresse des letzten verarbeiteten Zeichens übergeben wird. Adressen von Variablen werden über das &-Zeichen angegeben - Hier: &Ende. Und als drittes Argument wird angegeben in welchem Zahlensystem sich die zu konvertierende Zahl befindet. In unserem Fall natürlich im Dezimalsystem auf der Basis zu 10.
// 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 );
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 );
🤔 Die Zeilen 90 - 103
Im nächsten Schritt wird geprüft, ob überhaupt eine gültige Zahl eingegeben worden ist. In der Variablen Ende wird die Adresse des zuletzt verarbeiteten Zeichen gespeichert. Wenn diese mit der Adresse in Eingabe identisch ist, wurde ein leerer Text übergeben. Die Abfrage erfolgt über eine if Anweisung, mit der "Binären Gleichheit" - dem == Operator. Wenn beide Adressen gleich sind, wird entsprechend eine Fehlermeldung ausgegeben, dazu wird die bekannte printf() Anweisung benutzt.Sollten beide Adressen ungleich sein, das heisst es wurde ein Teil des Textes verarbeitet wird jetzt über den else if Teil eine weitere Bedingung geprüft. Wenn der eingegebene Text eine Zahl ist, muss der gesamte Text verarbeitet worden sein d.h. das das letzte Byte muss jetzt auf den Null Terminator zeigen. Wenn wenn innerhalb des Textes ein Zeichen eingegeben wurde, welches nicht zur Zahl gehört, wird an dieser Stelle die Verarbeitung gestoppt. Auch in diesem Fall wird deine Fehlermeldung ausgegeben, dass keine korrekte Zahl eingegeben worden ist.
Um zu prüfen, ob das Ende der Zeichenkette nicht erreicht wurde, wird das Zeichen geprüft, auf das die Variable Ende zeigt. Ist dies ungleich dem Null Terminator, ist die Bedingung erfüllt und die Fehlermeldung wird ausgegeben. Der Operator für die "Binäre Ungleichheit" ist !=.
// 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" );
}
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" );
}
🤔 Die Zeilen 105 - 115
Im nächsten Schritt wird geprüft, ob die Zahl in den angegebenen Bereichen liegt also größer/gleich 2 und kleiner 1000000 ist. Dazu gibt es wieder eine zweigeteilte Bedingung, dazu wird geprüft, ob die angegebene Zahl außerhalb des angegebenen Preis ist. Also Zahl ist kleiner als 2 oder grössser/gleich 1000000, in diesem Fall wird eine Fehlermeldung ausgegeben.Beide Bedingungen weden über die logische ODER Verknüpfung verbunden ||, das heisst einer der Bedingen muss "Wahr" sein, damit die komplette Bedingung "Wahr" ist.
// Ist die Zahl zwischen 2 und 999999
else if (
( Zahl < 2 ) ||
( Zahl > 999999 )
)
{
printf( "*** Die Zahl muss zwischen 2 - 999999 liegen...\n" );
}
else
{
else if (
( Zahl < 2 ) ||
( Zahl > 999999 )
)
{
printf( "*** Die Zahl muss zwischen 2 - 999999 liegen...\n" );
}
else
{
🤔 Die Zeilen 114 - 135
Nach Abschluss der Vorprüfungen kann jetzt wirklich geprüft werden, ob es sich um bei der angegebene Zahl um eine Primzahl handelt. Die Zahl wird über die printf() Funktion ausgegeben, der Platzhalter %d steht für eine vorzeichenbehaftete Dezimalzahl. Die Anweisung wird aber nicht mit einem Newline abgeschlossen, da ja noch nicht klar ist, ob die Zahl Prim ist oder nicht...Zuerst wird ein Sonderfall geprüft (Zeile 124), die Zahl 2 selbst. Laut mathematischer Definition handelt es sich dabei um eine Primzahl, dies wird entsprechend ausgegeben.
Der zweite Sonderfall ist, wenn die Zahl selbst durch 2 teilbar ist, damit ist sie natürlich keine Primzahl. Die Prüfung (Zeile 131) erfolgt über die Berechnung des Modulus mit 2. Unter Modulus versteht man den Rest einer Division, also zum Beispiel wenn ich 3 durch 2 Teile ist der Modulus 1, weil das der Rest der Division ist. Wenn eine Zahl durch 2 teilbar ist und der Modulus erstellt wird, ist es Ergebnis eine Null, weil natürlich bei der Division kein Rest auftritt. Der Operator für den Modulus ist das % Zeichen. Da das Ergebnis aber 0 (Null) ist, währe die Aussage "Falsch", da in der Programmlogik aber an der Stelle eine "Wahr" Aussage benötigt wird, wird der Wahrheitswert invertiert - Dazu gibt es den ! Operator. Dieser Invertiert eine logische Aussagt.
Programmiererwitz:
!false is funny - Because it's true...
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" );
}
{
// 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" );
}
🤔 Die Zeilen 136 - 159
Die Prüfung der Sonderfälle ist jetzt abgeschlossen. Jetzt kommt die wirkliche Prüfung auf eine Primzahl. Dies erfolgt mithilfe einer Schleife. Dazu wird zuerst eine spezielle schleifvariable deklariert int32_t s;Persönliche Anmerkung:
Ja ich weiss es - Ideologie ist dein Freund...
Zu Zeiten von ↗ FORTRAN wurden bereits einige Variablen im voraus deklariert um Lochkarten zu sparen. Alle Buchstaben des Alphabets waren reale Zahlen, ausser I, J, K und L - Das waren Ganzzahlen (Integer). Dies hat sich so sehr eingebürgert, dass bis zum heutigen Tag jede erste Integer Variable in einem Programm als "I" bezeichnet wird.
Vor gefühlten 30 Jahren habe ich aber die erste Schleifenvariable als "S" benannt und die zweite "T". Bis zum heutigen Tag... Also bitte keine Mails in der Preisklasse "Das muss aber 'I' heissen... (Heul)" - Ich bin anders als die anderen 😱 oder um die 1980'er zu Zitieren: "It's safe to dance..."
Das C-Keyword for( < Variable> ; < Bedingung > ; < Optionaler Ausdruck > ) ermöglicht es eine Schleife zu bilden. Wie immer in C wird der zur Schleife gehörende Block in geschweifte Klammern { ... } eingeschlossen.
Die Variable wird auf den Wert 3 gesetzt s = 3, die erste Primzahl.
Die Abbruchbedingung ist s < Zahl also solange s kleiner als die gesuchte Zahl, wird die Schleife ausgeführt.
Nach jedem Durchlauf wird die Schleifenvariable s um zwei erhöht. s += 2 ist für faule Programmierer die Kurzform für s = s + 2.
Dann wird in Zeile 146 der Modulus von "Zahl geteilt durch s" erstellt - ( Zahl % s ).
Wenn dieser 0 (Null) ergibt, war Zahl durch s teilbare und Zahl ist somit keine Primzahl. Da die Programmlogig an dieser Stelle wieder eine invertierte Logik verlangt, wird über den ! Operator wieder invertiert. Und die Meldung "keine Prinzahl" mit Newline ausgegeben und das Programm wird beendet - Mit dem return() Keyword und dem Statuscode 0.
Wenn der Modulus einen Wert ungleich 0 (Null) ergibt, gab keine Restlose Division und die Schleife wird wiederholt mit einem um 2 erhöhten Wert von s.
Wenn die Schleife komplett durchlaufen wurde, ohne eine restlose Division zu finden, ist Zahl eine Primzahl. Was dann durch die Textausgabe bestätigt wird. Damit ist das Programm beendet und wird mit return( 0 ); abgeschlossen.
// 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
{
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" );
}
🤔 Die Zeilen 163 - 169
Am Anfang wurde geprüft, if (
( argc >= 2) && // Mindestens zwei Argumente wurden uebergeben
( argv[ 1 ] != NULL ) // Die Speicheradresse ist ein gueltiger Zeiger
)
{
( argc >= 2) && // Mindestens zwei Argumente wurden uebergeben
( argv[ 1 ] != NULL ) // Die Speicheradresse ist ein gueltiger Zeiger
)
{
ob die Variablen argc und argv[] vernünftige Werte enthalten. Wenn nein, wird das Programm direkt abgebrochen.
}
else
{
// Es ist ein Problem beim auslesen der Argumente aufgetreten!
printf( "Problem bein Auslesen der Argumente *** Abbruch!\n" );
}
else
{
// Es ist ein Problem beim auslesen der Argumente aufgetreten!
printf( "Problem bein Auslesen der Argumente *** Abbruch!\n" );
}
Alle Downloads zu diesem Projekt:
💾 Primzahl.c
💾 Primzahl.pro
Inhalt von: Primzahl.c
..1: //+------------------------------------------------------------------
..2: //|
..3: //| Projekt : Kapitel1 - Wie erkennt man eine Primzahl?
..4: //|
..5: //| Projektbeschreibung : Es wird eine eingegebene Ganzzahl darauf
..6: //| : geprueft, ob es sich um eine Primzahl handelt
..7: //| :
..8: //| Versionsnummer : V1.00
..9: //| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: //|
.11: //| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: //| Programmierung mit C und C++ ohne ideologischen Ballast
.13: //| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: //|
.15: //+------------------------------------------------------------------
.16:
.17: // Einbinden aller benötigten Header-Dateien (.h)
.18: #include "stdio.h" // Standard-Input-Output (Funktionen aus dem C-Standard)
.19: #include "stdlib.h" // Funktionen aus der Standard-C Bibliothek (libc)
.20: #include "inttypes.h" // Integer Datentypen (Wird teilweise automatisch einbebunden)
.21:
.22:
.23: //+------------------------------------------------------------------------
.24: //! Einsprung in das Programm, die main() Funktion muss in einem C Programm
.25: //! immer existieren.
.26: //!
.27: //! Als erstes Argument wird eine Ganzzahl uebergeben, die darauf geprueft
.28: //! wird, ob es sich um eine Primzahl handelt.
.29: //+------------------------------------------------------------------------
.30: //! Argumente :
.31: //! \param [in] argc - Anzahl der übergebenen Argumente
.32: //! \param [in] *argv[] - Liste aller Argumente als Zeiger im C-Stil
.33: //!
.34: //+------------------------------------------------------------------------
.35: //! Rückgabewert :
.36: //! \return int - Fehlercode (0 für alles OK, kein Fehler)
.37: //!
.38: //+------------------------------------------------------------------------
.39: int main( int argc, char *argv[] )
.40: {
.41: // *
.42: // ** Wurden ueberhaupt Argumente uebergeben?
.43: // ** Pruefe die Anzahl der uebergeben Argumente
.44: // ** Es muss mindestens ein Argument uebergeben werden.
.45: //
.46: if ( argc < 2 )
.47: {
.48: // In der ersten Variablen argc ist die Anzahl der uebergebenen Argumente angegeben.
.49: // Die Anzahl ist mindestens ein Argument, das erste Argument ist der Dateiname
.50: // ueber den das Programm aufgerufen wurde, dieser Eintrag existiert immer.
.51:
.52: // Wenn kein zusaetzliches Argument uebergeben wurde, wird eine Hilfemeldung ausgegeben.
.53: printf( "Aufruf:\n" );
.54: printf( "%s < Ganzzahl >\n\n", argv[ 0 ] ); // Zu argv siehe den Kommentar, etwas tiefer
.55: printf( "Die angegebene Zahl (2 ... 999999) wird darauf geprueft,\n");
.56: printf( "ob es sich um eine Primzahl handelt.\n" );
.57:
.58: // Das Programm wird beendet
.59: return( 0 );
.60: }
.61:
.62: // *
.63: // ** Die zweite Variable enthaelt eine Liste (Array) von Zeigern auf
.64: // ** jedes einzelne Argument hinter dem Programmnamen.
.65: // ** Wie immer in C, beginnt der Index ab dem Wert 0 (Null)
.66: // ** Der Stern vor dem Variablenname "char *argv[]" besagt, es handelt sich um eine Liste
.67: // ** aus Zeigern (Pointer), die auf die eigentlichen Texte zeigen. jeder Eintrag ist vom
.68: // ** Typ char mit einem Null-Terminator. Die Speicherverwaltung uebernimmt in diesem Fall das
.69: // ** Betriebssystem.
.70: // *
.71:
.72: // *
.73: // ** Pruefe ob das 2. Argument vorliegt?
.74: // ** Sind alle Argumente gueltig?
.75: // *
.76: if (
.77: ( argc >= 2) && // Mindestens zwei Argumente wurden uebergeben
.78: ( argv[ 1 ] != NULL ) // Die Speicheradresse ist ein gueltiger Zeiger
.79: )
.80: {
.81:
.82: // Benoetigte Variablen
.83: int32_t Zahl; // Die Konvertierte Ganzzahl
.84: char *Eingabe = argv[ 1 ]; // Anfangsadresse im Speicher
.85: char *Ende = NULL; // Wie weit wurde die Zahl abgearbeitet?
.86:
.87: // Konvertiere das 2. Argument in eine vorzeichenbehaftete Ganzzahl auf der Basis von 10
.88: Zahl = strtol( Eingabe, &Ende, 10 );
.89:
.90: // Wenn Eingabe und Ende auf die selbe Adresse Zeigen, wurde kein Text uebergeben
.91: if ( Eingabe == Ende )
.92: {
.93: printf( "*** Es wurde kein Text eingegeben...\n" );
.94:
.95: }
.96:
.97: // Wenn die Adresse in Ende nicht auf den abschliessenden Null-Terminator zeigt
.98: // wurde die konvertierung abgebrochen, z.B. durch ein falsches Zeichen
.99: else if ( *Ende != '\0' )
100: {
101: printf( "*** Es wurde keine gueltige Zahl eingegeben...\n" );
102:
103: }
104:
105: // Ist die Zahl zwischen 2 und 999999
106: else if (
107: ( Zahl < 2 ) ||
108: ( Zahl > 999999 )
109: )
110: {
111: printf( "*** Die Zahl muss zwischen 2 - 999999 liegen...\n" );
112:
113: }
114: else
115: {
116: // Die Zahl erfuellt alle kriterien, pruefe auf eine Prinzahl
117: printf( "Pruefe die Zahl %d ...", Zahl );
118:
119: // *
120: // ** Pruefe, ob die angegebene Zahl eine Prinzahl ist
121: // *
122:
123: // Sonderlocken ... (Die Zahl 2 selbst)
124: if ( Zahl == 2 )
125: {
126: printf( " ist eine Primzahl.\n" );
127:
128: }
129:
130: // Sonderlocken ... Vielfaches von 2
131: else if ( ! ( Zahl % 2 ) )
132: {
133: printf( " ist keine Primzahl.\n" );
134:
135: }
136: // Pruefung auf eine Prinzahl
137: else
138: {
139: int32_t s; // Schleifenvariable
140:
141: // Durchlaufe alle Zahlen von 3 bis zum eingegebenen Wert in Schritten von je 2
142: for( s = 3; s < Zahl; s += 2 )
143: {
144: // Wenn der Modulus von Zahl geteilt durch s 0 (Null) ist, ist es keine Primzahl,
145: // Abbrechen
146: if ( ! ( Zahl % s ) )
147: {
148: printf( " ist keine Primzahl.\n" );
149:
150: // Programm vorzeitig beenden
151: return( 0 );
152: }
153:
154: }
155:
156: // Es wurde kein Modulus mit 0 gefunden, also ist die angegebene Zahl eine Primzahl
157: printf( " ist eine Primzahl.\n" );
158:
159: }
160:
161: }
162:
163: }
164: else
165: {
166: // Es ist ein Problem beim auslesen der Argumente aufgetreten!
167: printf( "Problem bein Auslesen der Argumente *** Abbruch!\n" );
168:
169: }
170:
171: // Das Programm regulaer beenden
172: return( 0 );
173: }
174:
Inhalt von: Primzahl.pro
..1: #+------------------------------------------------------------------
..2: #|
..3: #| Projekt : Kapitel1 - Wie erkennt man eine Primzahl?
..4: #|
..5: #| Projektbeschreibung : Es wird eine eingegebene Ganzzahl darauf
..6: #| : geprueft, ob es sich um eine Primzahl handelt
..7: #| :
..8: #| Versionsnummer : V1.00
..9: #| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: #|
.11: #| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: #| Programmierung mit C und C++ ohne ideologischen Ballast
.13: #| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: #|
.15: #+------------------------------------------------------------------
.16:
.17: TARGET = Primzahl
.18: TEMPLATE = app
.19:
.20: SOURCES += Primzahl.c
💾 Primzahl.c
💾 Primzahl.pro
Inhalt von: Primzahl.c
..1: //+------------------------------------------------------------------
..2: //|
..3: //| Projekt : Kapitel1 - Wie erkennt man eine Primzahl?
..4: //|
..5: //| Projektbeschreibung : Es wird eine eingegebene Ganzzahl darauf
..6: //| : geprueft, ob es sich um eine Primzahl handelt
..7: //| :
..8: //| Versionsnummer : V1.00
..9: //| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: //|
.11: //| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: //| Programmierung mit C und C++ ohne ideologischen Ballast
.13: //| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: //|
.15: //+------------------------------------------------------------------
.16:
.17: // Einbinden aller benötigten Header-Dateien (.h)
.18: #include "stdio.h" // Standard-Input-Output (Funktionen aus dem C-Standard)
.19: #include "stdlib.h" // Funktionen aus der Standard-C Bibliothek (libc)
.20: #include "inttypes.h" // Integer Datentypen (Wird teilweise automatisch einbebunden)
.21:
.22:
.23: //+------------------------------------------------------------------------
.24: //! Einsprung in das Programm, die main() Funktion muss in einem C Programm
.25: //! immer existieren.
.26: //!
.27: //! Als erstes Argument wird eine Ganzzahl uebergeben, die darauf geprueft
.28: //! wird, ob es sich um eine Primzahl handelt.
.29: //+------------------------------------------------------------------------
.30: //! Argumente :
.31: //! \param [in] argc - Anzahl der übergebenen Argumente
.32: //! \param [in] *argv[] - Liste aller Argumente als Zeiger im C-Stil
.33: //!
.34: //+------------------------------------------------------------------------
.35: //! Rückgabewert :
.36: //! \return int - Fehlercode (0 für alles OK, kein Fehler)
.37: //!
.38: //+------------------------------------------------------------------------
.39: int main( int argc, char *argv[] )
.40: {
.41: // *
.42: // ** Wurden ueberhaupt Argumente uebergeben?
.43: // ** Pruefe die Anzahl der uebergeben Argumente
.44: // ** Es muss mindestens ein Argument uebergeben werden.
.45: //
.46: if ( argc < 2 )
.47: {
.48: // In der ersten Variablen argc ist die Anzahl der uebergebenen Argumente angegeben.
.49: // Die Anzahl ist mindestens ein Argument, das erste Argument ist der Dateiname
.50: // ueber den das Programm aufgerufen wurde, dieser Eintrag existiert immer.
.51:
.52: // Wenn kein zusaetzliches Argument uebergeben wurde, wird eine Hilfemeldung ausgegeben.
.53: printf( "Aufruf:\n" );
.54: printf( "%s < Ganzzahl >\n\n", argv[ 0 ] ); // Zu argv siehe den Kommentar, etwas tiefer
.55: printf( "Die angegebene Zahl (2 ... 999999) wird darauf geprueft,\n");
.56: printf( "ob es sich um eine Primzahl handelt.\n" );
.57:
.58: // Das Programm wird beendet
.59: return( 0 );
.60: }
.61:
.62: // *
.63: // ** Die zweite Variable enthaelt eine Liste (Array) von Zeigern auf
.64: // ** jedes einzelne Argument hinter dem Programmnamen.
.65: // ** Wie immer in C, beginnt der Index ab dem Wert 0 (Null)
.66: // ** Der Stern vor dem Variablenname "char *argv[]" besagt, es handelt sich um eine Liste
.67: // ** aus Zeigern (Pointer), die auf die eigentlichen Texte zeigen. jeder Eintrag ist vom
.68: // ** Typ char mit einem Null-Terminator. Die Speicherverwaltung uebernimmt in diesem Fall das
.69: // ** Betriebssystem.
.70: // *
.71:
.72: // *
.73: // ** Pruefe ob das 2. Argument vorliegt?
.74: // ** Sind alle Argumente gueltig?
.75: // *
.76: if (
.77: ( argc >= 2) && // Mindestens zwei Argumente wurden uebergeben
.78: ( argv[ 1 ] != NULL ) // Die Speicheradresse ist ein gueltiger Zeiger
.79: )
.80: {
.81:
.82: // Benoetigte Variablen
.83: int32_t Zahl; // Die Konvertierte Ganzzahl
.84: char *Eingabe = argv[ 1 ]; // Anfangsadresse im Speicher
.85: char *Ende = NULL; // Wie weit wurde die Zahl abgearbeitet?
.86:
.87: // Konvertiere das 2. Argument in eine vorzeichenbehaftete Ganzzahl auf der Basis von 10
.88: Zahl = strtol( Eingabe, &Ende, 10 );
.89:
.90: // Wenn Eingabe und Ende auf die selbe Adresse Zeigen, wurde kein Text uebergeben
.91: if ( Eingabe == Ende )
.92: {
.93: printf( "*** Es wurde kein Text eingegeben...\n" );
.94:
.95: }
.96:
.97: // Wenn die Adresse in Ende nicht auf den abschliessenden Null-Terminator zeigt
.98: // wurde die konvertierung abgebrochen, z.B. durch ein falsches Zeichen
.99: else if ( *Ende != '\0' )
100: {
101: printf( "*** Es wurde keine gueltige Zahl eingegeben...\n" );
102:
103: }
104:
105: // Ist die Zahl zwischen 2 und 999999
106: else if (
107: ( Zahl < 2 ) ||
108: ( Zahl > 999999 )
109: )
110: {
111: printf( "*** Die Zahl muss zwischen 2 - 999999 liegen...\n" );
112:
113: }
114: else
115: {
116: // Die Zahl erfuellt alle kriterien, pruefe auf eine Prinzahl
117: printf( "Pruefe die Zahl %d ...", Zahl );
118:
119: // *
120: // ** Pruefe, ob die angegebene Zahl eine Prinzahl ist
121: // *
122:
123: // Sonderlocken ... (Die Zahl 2 selbst)
124: if ( Zahl == 2 )
125: {
126: printf( " ist eine Primzahl.\n" );
127:
128: }
129:
130: // Sonderlocken ... Vielfaches von 2
131: else if ( ! ( Zahl % 2 ) )
132: {
133: printf( " ist keine Primzahl.\n" );
134:
135: }
136: // Pruefung auf eine Prinzahl
137: else
138: {
139: int32_t s; // Schleifenvariable
140:
141: // Durchlaufe alle Zahlen von 3 bis zum eingegebenen Wert in Schritten von je 2
142: for( s = 3; s < Zahl; s += 2 )
143: {
144: // Wenn der Modulus von Zahl geteilt durch s 0 (Null) ist, ist es keine Primzahl,
145: // Abbrechen
146: if ( ! ( Zahl % s ) )
147: {
148: printf( " ist keine Primzahl.\n" );
149:
150: // Programm vorzeitig beenden
151: return( 0 );
152: }
153:
154: }
155:
156: // Es wurde kein Modulus mit 0 gefunden, also ist die angegebene Zahl eine Primzahl
157: printf( " ist eine Primzahl.\n" );
158:
159: }
160:
161: }
162:
163: }
164: else
165: {
166: // Es ist ein Problem beim auslesen der Argumente aufgetreten!
167: printf( "Problem bein Auslesen der Argumente *** Abbruch!\n" );
168:
169: }
170:
171: // Das Programm regulaer beenden
172: return( 0 );
173: }
174:
Inhalt von: Primzahl.pro
..1: #+------------------------------------------------------------------
..2: #|
..3: #| Projekt : Kapitel1 - Wie erkennt man eine Primzahl?
..4: #|
..5: #| Projektbeschreibung : Es wird eine eingegebene Ganzzahl darauf
..6: #| : geprueft, ob es sich um eine Primzahl handelt
..7: #| :
..8: #| Versionsnummer : V1.00
..9: #| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: #|
.11: #| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: #| Programmierung mit C und C++ ohne ideologischen Ballast
.13: #| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: #|
.15: #+------------------------------------------------------------------
.16:
.17: TARGET = Primzahl
.18: TEMPLATE = app
.19:
.20: SOURCES += Primzahl.c
🤔 Programm Ausgaben
sjs@Mac MacOS % ./Primzahl
Aufruf:
./Primzahl < Ganzzahl >
Die angegebene Zahl (2 ... 999999) wird darauf geprueft,
ob es sich um eine Primzahl handelt.
Aufruf:
./Primzahl < Ganzzahl >
Die angegebene Zahl (2 ... 999999) wird darauf geprueft,
ob es sich um eine Primzahl handelt.
sjs@Mac MacOS % ./Primzahl ""
*** Es wurde kein Text eingegeben...
*** Es wurde kein Text eingegeben...
sjs@Mac MacOS % ./Primzahl 47elf
*** Es wurde keine gueltige Zahl eingegeben...
*** Es wurde keine gueltige Zahl eingegeben...
sjs@Mac MacOS % ./Primzahl 1
*** Die Zahl muss zwischen 2 - 999999 liegen...
*** Die Zahl muss zwischen 2 - 999999 liegen...
sjs@Mac MacOS % ./Primzahl 2
Pruefe die Zahl 2 ... ist eine Primzahl.
Pruefe die Zahl 2 ... ist eine Primzahl.
sjs@Mac MacOS % ./Primzahl 65
Pruefe die Zahl 65 ... ist keine Primzahl.
Pruefe die Zahl 65 ... ist keine Primzahl.
sjs@Mac MacOS % ./Primzahl 123457
Pruefe die Zahl 123457 ... ist eine Primzahl.
Pruefe die Zahl 123457 ... ist eine Primzahl.
sjs@Mac MacOS % ./Primzahl 123459
Pruefe die Zahl 123459 ... ist keine Primzahl.
Pruefe die Zahl 123459 ... ist keine Primzahl.
