Forum: PC-Programmierung C - Banknoten Check vereinfachen möglich?


von Müller (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebes Forum,

ich habe mal eine Frage bezüglich meiner Check Routine für den Euronoten 
Code. Ich werde das Gefühl nicht los, dass das noch einfacher geht. Ich 
finde es persönlich lang, wobei ich das schon seperat in eine eigene 
Datei mit Header ausgelagert habe.

Kurz um euch die Berechnungsroutine darzustellen:

Banknoten Code einlesen CheckCode("CODE"):

- Prüfe ob es exakt 12 Zeichen sind
- Prüfe ob erstes Zeichen ein Buchstabe ist
- Prüfe ob zweites Zeichen ein Buchstabe ist
- Ist Nur Zeichen 1 ein Buchstabe -> Rufe CheckCodeOldEuro() auf
- Sind Zeichen 1 und Zeichen 2 Buchstaben -> Rufe CheckCodeNewEuro() auf
- Sind es nicht 12 Zeichen abbruch

Funktion CheckCodeOldEuro()
- Prüfe ob nachfolgende Zeichen Zahlen sind
- Wenn Ja, dann bilde dort schon mal die Quersumme
- Wenn Nein, Abbruch
- Wandle Buchstabe in Zahl um (A=1, B=2, C=3 etc...)
- Ist die umgewandlete Zahl höher als 9, also 10 oder mehr
- Wenn ja Splitte die Zahlen auf und addiere auf zur Quersumme
- Beispiel: Ist die Zahl 11, dann mache Quersumme += 1 + 1
- Ansonsten einfach auf Quersumme aufrechnen
- Dann Berechne den Divisionsrest -> Quersumme % 9
- Berechne Differenz -> Differenz = 8 - Divisionsrest
- Übrprüfe Letzte Zahl im Kode, ob die übereinstimmt mit Differenz
- Wenn Ja, dann ist die Note Echt
- Wenn Nein, handelt es sich um eine Fälschung

Funktion CheckCodeNewEuro()
- Prüfe ob nachfolgende Zeichen Zahlen sind
- Wenn Ja, dann bilde dort schon mal die Quersumme
- Wenn Nein, Abbruch
- Wandle Buchstaben in Zahlen um (A=1, B=2, C=3 etc...)
- Sind die umgewandelten Zahlen höher als 9, also 10 oder mehr
- Wenn ja Splitte die Zahlen auf und addiere auf zur Quersumme
- Beispiel: Ist die Zahl 11, dann mache Quersumme += 1 + 1
- Ansonsten einfach auf Quersumme aufrechnen
- Dann Berechne den Divisionsrest -> Quersumme % 9
- Berechne Differenz -> Differenz = 7 - Divisionsrest
- Übrprüfe Letzte Zahl im Kode, ob die übereinstimmt mit Differenz
- Wenn Ja, dann ist die Note Echt
- Wenn Nein, handelt es sich um eine Fälschung


Ich hoffe ihr habt das soweit verstanden. NewEuro sind z.B. die neuen 5 
und 10 Euro Scheine, da gibt es immer 2 Buchstaben, der erste gibt die 
Druckerei an, der zweite eine Interne Bezeichnung vom Drucker(?). Bei 
den alten Euro Scheinen ist das der Ländercode.

Die Letzte Zahl ist immer die Prüfziffer, die darf man nicht zur 
Quersumme aufaddieren.

Ich hab beide Routinen mit meinem Geld getestet, das funktioniert 
soweit, also ich hab keine Fälschungen xD

Eventuell gibts ja noch eine einfache Möglichkeit. Ich hoffe ihr könnt 
den Code relativ gut lesen^^

Lieben Gruß

von Simpel (Gast)


Lesenswert?

Ich arbeite grad an einer Routine, welche die falschen 13-Euro-Scheine 
mit hoher Treffergenauigkeit erkennt und aussortiert...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dein Algorithmus, um einen Buchstaben in einen numerischen Wert 
umzuwandeln ist ziemlich umständlich.

Statt
1
        first[0] = toupper(string[0]);
2
        first[1] = 0;
3
4
        f_position = strcspn(lookup, first);

genügt hier ein
1
        f_position = toupper(string[0]) - '@';

... sofern man sich auf den ASCII-Code und die Reihenfolge der Zeichen 
darin verlässt. '@' ist das Zeichen, das unmittelbar vor 'A' kommt.

Mit isalpha kann man überprüfen, ob ein Zeichen ein Buchstabe ist; 
Vergleiche mit der Konstanten 27 sind daher überflüssig.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Rufus Τ. F. schrieb:
> ... sofern man sich auf den ASCII-Code und die Reihenfolge der Zeichen
> darin verlässt. '@' ist das Zeichen, das unmittelbar vor 'A' kommt.

Dann könnte man auch 'A' - 1 schreiben und könnte sich den Kommentar 
sparen, dass '@' das Zeichen genau vor dem 'A' ist ;-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Natürlich. Kann man auch.

von Müller (Gast)


Lesenswert?

Dass ich auf sowas nicht selber gekommen bin ;) Danke dir werde das 
entsprechend ändern.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ein paar Anmerkungen und Verbesserungsvorschläge:

Da höchstens ein Element der Struktur Error_t wahr werden kann, nimmt
man stattdessen besser ein Enum, das neben den einzelnen Fehlerfällen
auch einen Wert (üblicherweise den ersten) für "ok" enthält.

Statt den Fehlercode in einer globalen Variable zu speichern, würde ich
ihn als Funktionswert anstelle des bool zurückliefern.

Da die Funktionen CheckCodeOldEuro und CheckCodeNewEuro nur von
CheckCode aufgerufen werden und wegen der vielen globalen Variable
sinnvollerweise auch nur von dort aufgerufen werden sollten, würde ich
ihre Deklaration aus CheckCode.h streichen und sie stattdessen in
CheckCode.c als static deklarieren. Damit sind diese Funktionen für
andere C-Module verborgen, so dass sie auch nicht aus Versehen
aufgerufen werden können.

Warum kopierst du in CheckCode das Argument str in die neue, dynamisch
erzeugte Variable string? Reiche doch einfach str als Argument an die
beiden Funktionen CheckCodeOldEuro und CheckCodeNewEuro weiter. Da str
nirgends überschrieben wird, ist das überhaupt kein Problem und eine
weitere globale Variable (string) kann wegfallen, ebenso die Funktion
CheckFree.

Wo wird CheckFree überhaupt aufgerufen? Von extern? Das wäre erst recht
ein Grund, auf die dynamisch erzeugte Variable zu verzichten.

Kann es sein, dass du den dynamischen Speicher für mehrere Aufrufe von
CheckCode nutzen möchtest? Wenn ja, gibt es ein Problem, wenn CheckCode
zuerst mit einem kurzen und danach mit einem langen String aufgerufen
wird, da in diesem Fall der Speicherplatz für den zweiten String nicht
ausreicht.

Die Berechnung der Prüfsumme ist viel einfacher, als du es in deinem
Text beschrieben hast:

Anstatt bei der Summenbildung die letzte Ziffer auszusparen, kannst du
die Summe auch gleich über alle Ziffern bilden und ihren Neunerrest dann
mit einem konstanten Wert vergleichen. Dieser konstante Wert ist sowohl
für die alten als auch die neuen Scheine 0, wenn man für die Buchstaben
ihren ASCII-Code (als Großbuchstaben, also 'A'->65, 'B'->66 usw.) und
für die Ziffern ihren numerischen Wert (also '0'->0, '1'->1 usw.)
summiert.

Für zweistellige Summanden (bei den ASCII-Codes) musst nicht gesondert
die Quersumme bilden, denn diese Quersumme ist nichts anderes als der
Neunerrest des Summanden, und es genügt, diesen ganz am Schluss von der
Gesamtsumme zu berechnen.

Im folgenden Code sind die obigen Bemerkungen umgesetzt:

1
#include <stdio.h>
2
#include <ctype.h>
3
4
enum Err { E_OK, E_TOOSHORT, E_TOOLONG, E_BADCHAR, E_BADSUM };
5
6
enum Err CheckCode(const char *str) {
7
  int n, sum = 0;
8
  enum Err err = E_OK;
9
10
  for(n=0; n<12 && !err; n++) {
11
    char c = *str++;
12
    if(n < 2 && isupper(c))
13
      sum += c;
14
    else if(n >= 1 && isdigit(c))
15
      sum += c - '0';
16
    else
17
      err = c ? E_BADCHAR : E_TOOSHORT;
18
  }
19
  if(err == E_OK) {
20
    if(*str)
21
      err = E_TOOLONG;
22
    else if(sum % 9)
23
      err = E_BADSUM;
24
  }
25
  return err;
26
}

Dabei werden keine globalen Variablen verwendet, und die alten und die
neuen Scheine werden in ein und derselben Routine behandelt.

Da ich gerade keinen neuen Schein zum Testen da habe, hoffe ich, dass
ich trotzdem keinen Mist gebaut habe ;-)


Edit:

Die Prüfung der letzten Ziffer für die neuen Scheine sieht bei dir so
aus:

1
            diff = 7 - divrest;
2
3
            if(diff != string[11]-'0')

Das funktioniert nicht, wenn divrest = 8 und damit diff = -1 wird.

: Bearbeitet durch Moderator
von NeinDanke (Gast)


Lesenswert?

Müller schrieb:
> - Wenn Ja, dann ist die Note Echt
> - Wenn Nein, handelt es sich um eine Fälschung

Ich hoffe der Banknotenfälscher denkt auch dran eine ungültige Nummer 
auf den Schein zu drucken.

von Müller (Gast)


Lesenswert?

Yalu danke für die ausführliche Hilfe. Ich habe auf der Suche nach einer 
Möhlichkeit diesen Code zu prüfen, erstmal nichts gefunden per Google, 
bin dann irgendwann mal auf einer Seite gelandet, wo das quasi so 
beschrieben wurde. Dass es dann doch so einfach geht, ist natürlich 
positiv, danke dir,

Ich werd das morgen mal testen.

Lieben Gruß

@NeinDanke
Wär ich nicht darauf gekommen, Mensch bist wohl ein Hecht wa? Cicalone

von asdfasd (Gast)


Lesenswert?

Yalus Lösung sieht sauber und bis auf einen Punkt korrekt aus.

Das Problem ist dieses Fragment:
1
>     char c = *str++;
2
>     if(n < 2 && isupper(c))

Die ctype-Funktionen brauchen als Argument einen unsigned char oder 
EOF, normalerweise also einen Wert zwischen -1 und 255.  Ein "char c" 
kann hier zu merkwürdigen Fehlern (inkl. Programmabstürzen!) führen. 
Desweiteren werden, je nach locale, mehr als die 26 Zeichen A-Z als 
Großbuchstaben akzeptiert (z.B. ÄÖÜ).
  Aus diesen Gründen benutze ich die ctype-Funktionen kaum noch - ich 
schreib dann lieber "if (n < 2 && c >= 'A' && c <= 'Z')".  Das hat diese 
Probleme nicht und EBCDIC ist eh tot ;-)

von Mikro 7. (mikro77)


Lesenswert?

Mal wieder so eine nette Sache mit dem char...

asdfasd schrieb:
> Die ctype-Funktionen brauchen als Argument einen unsigned char oder
> EOF, normalerweise also einen Wert zwischen -1 und 255.

... das steht so in der Linux man page.

Der ISO Standard sagt: "a character representable as an unsigned char 
or equal to the value of the macro EOF". Ein signed char ist doch wohl 
representable als unsigned char, oder?

Ich gucke auch häufig auf http://www.cplusplus.com. Die sagen: 
"Character to be checked, casted to an int, or EOF." Und haben auch ein 
Beispiel:
1
int i=0;
2
char str[]="Test String.\n";
3
char c;
4
while (str[i])
5
{
6
  c=str[i];
7
  if (isupper(c)) c=tolower(c);
8
  putchar (c);
9
  i++;
10
}

von Simpel (Gast)


Lesenswert?

> Müller schrieb:
>
> Ich hoffe der Banknotenfälscher denkt auch dran eine ungültige Nummer
> auf den Schein zu drucken.

Genau aus diesem Grund habe ich das mit dem 13-€-Schein geschrieben... 
:-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

asdfasd schrieb:
> Die ctype-Funktionen brauchen als Argument einen unsigned char oder
> EOF, normalerweise also einen Wert zwischen -1 und 255.  Ein "char c"
> kann hier zu merkwürdigen Fehlern (inkl. Programmabstürzen!) führen.

Stimmt, das habe ich nicht bedacht.

Die Programmabstürze bzw. Assertion-Abbrüche in einigen Implementationen
lassen sich dadurch vermeiden, dass man das Argument der is*-Funktionen
nach (unsigned char) castet.

Ich verstehe aber auch nicht ganz, warum für die is*-Funktionen EOF als
Argument zugelassen ist. Normalerweise prüft man doch die Bytes eines
Datenstroms auf EOF ab, bevor sie weiterverarbeitet werden. Dann
könnte das Argument einfach char sein, und der hässliche Cast wäre nicht
nötig.

> Desweiteren werden, je nach locale, mehr als die 26 Zeichen A-Z als
> Großbuchstaben akzeptiert (z.B. ÄÖÜ).

Ja, korrekterweise sollte man deswegen in der Funktion CheckCode das
Locale temporär auf "C" setzen.

Hier ist eine Version der Funktion, die diese Dinge berücksichgtigt:

1
#include <stdio.h>
2
#include <ctype.h>
3
#include <locale.h>
4
5
enum Err { E_OK, E_TOOSHORT, E_TOOLONG, E_BADCHAR, E_BADSUM };
6
7
enum Err CheckCode(const char *str) {
8
  int n, sum = 0;
9
  enum Err err = E_OK;
10
  char *loc = setlocale(LC_CTYPE, NULL);
11
12
  setlocale(LC_CTYPE, "C");
13
  for(n=0; n<12 && !err; n++) {
14
    char c = *str++;
15
    if(n < 2 && isupper((unsigned char)c))
16
      sum += c;
17
    else if(n >= 1 && isdigit((unsigned char)c))
18
      sum += c - '0';
19
    else
20
      err = c ? E_BADCHAR : E_TOOSHORT;
21
  }
22
  if(err == E_OK) {
23
    if(*str)
24
      err = E_TOOLONG;
25
    else if(sum % 9)
26
      err = E_BADSUM;
27
  }
28
  setlocale(LC_CTYPE, loc);
29
  return err;
30
}

> Aus diesen Gründen benutze ich die ctype-Funktionen kaum noch

Ich auch nicht, deswegen bin ich auch über das Problem gestolpert :)

> ich schreib dann lieber "if (n < 2 && c >= 'A' && c <= 'Z')".  Das hat
> diese Probleme nicht und EBCDIC ist eh tot ;-)

Oh, sag so etwas nicht, da sind nämlich die Herren von IBM ganz anderer
Meinung ;-)

Alles in allem gesehen ist die Methode des TE mit dem Lookup-String
vielleicht doch nicht die schlechteste. Immerhin könnte man damit mit
einer kleinen Modifikation auch leicht abprüfen, ob der entsprechende
Buchstabencode für das Land bzw. die Druckerei überhaupt vergeben ist.

von Müller (Gast)


Lesenswert?

Hallo zusammen,
wenigstens ist nicht alles schlecht, was ich da wieder fabriziert habe.

eine Überprüfung des Länder Codes hatte ich auch noch geplant. Ich meine 
irgendwo gelesen zu haben, dass einige Buchstaben sogar eine Fälschung 
angeben.

Zu den Druckerei verwendeten Buchstaben habe ich jedoch auf Anhieb keine 
Liste gefunden, ich werde aber mal genauer suchen.

Ich könnte ja bei der Eingabe, wie Yalu beschrieben hat, explizit auf 
EOF prüfen, und dann könnte man ja auch auf den Cast verzichten.

Ich werde mich mal nachher dransetzen. Vielen Dank

Lieben Gruß

von Müller (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe jetzt nochmal etwas geschrieben. Dein Beispiel habe ich 
größtenteils übernommen. Länderkennung und Druckerei Kennung Überprüfung 
ist da auch drinne, und sollte funktionieren.

Jedoch musste ich die Druckereikennungen auf Heap laden, eine normale 
Iniatilisation auf den Stack mittels const char **kennung = {"..", 
".."...
hat aus mir nicht näher bekannten Gründen nicht geklappt.

Ich konnte zwar das so hinschreiben ohne Fehlermeldung, kompiliert hat 
er das auch. Dann wollte ich testen, ob der mir alle 24 ausgibt per 
printf.
Er hat dann zwar die ersten 3 oder 4 ausgegeben, jedoch kam es direkt 
danach zu einem segfault.

Weiss der Geier warum das so war.

Könnt ja mal drüber schauen, bestimmt kann man das noch extrem 
vereinfachen.

Lieben Gruß

von asdfasd (Gast)


Lesenswert?

> Ich verstehe aber auch nicht ganz, warum für die is*-Funktionen EOF als
> Argument zugelassen ist. Normalerweise prüft man doch die Bytes eines
> Datenstroms auf EOF ab, bevor sie weiterverarbeitet werden.

Bequemlichkeit und Geschwindigkeit (als diese Funktionen entstanden hat 
man noch Taktzyklen gezählt).  Man konnte so seine Abfragen nach 
Häufigkeit sortieren und EOF kam dann (da es "in" jeder Datei ja nur 
einmal vorkommt) ganz nach hinten.  Außerdem war "Text" nur 7 bit so 
dass das signed/unsigned char Problem auf keinem Radar war (das 
ctype-array war entspr auch nur 129 Byte groß).

> korrekterweise sollte man deswegen in der Funktion CheckCode das
> Locale temporär auf "C" setzen.

Keine so gute Idee.  Zum einen ist setlocale ein Schwergewicht (lädt 
Dateien von Platte) und zum anderen, und viel wichtiger, setlocale ist 
global und ändert das Locale aller Threads des Prozesses.

Der ANSI-C locale Kram ist ziemlicher Bockmist.  Das war ein 
Schnellschuss um mit möglichst wenig Aufwand (eine Zeile in main - 
setlocale(LC_ALL, "");) Programme zu lokalisieren.  Funktioniert leider 
nur bei trivialen Programmen.
   Dummerweise ist die API so beschissen, dass es nur ein entweder-oder 
gibt, locales oder keine.  Locale-unabhängiger Kode hat nun das Problem, 
dass er locale-abhängige Funktionen vermeiden muss - problematisch 
insbesondere bei implementationsempfindlichen Sachen wie strtod.
   Bei mir gehen deshalb immer die Alarmglocken an, wenn ich in einem 
Programm ein setlocale sehe - zu viele Programmierer sind sich der 
Konsequenzen nicht bewusst.

Zurück zum Checker: warum willst du unbedingt die ctype-Funktionen 
verwenden?  Der Algorithmus funktioniert so eh nur mit ASCII und da sind 
isupper und isdigit trivial[1].

> > EBCDIC ist eh tot ;-)
>
> Oh, sag so etwas nicht, da sind nämlich die Herren von IBM ganz
> anderer Meinung ;-)

Für das Encoding sollen sie ewig bluten.  EBCDIC-Support wird bei mir 
absichtlich ignoriert - sollen sich die damit rumschlagen, die es 
verbrochen haben ;-)

> [...] leicht abprüfen, ob der entsprechende Buchstabencode für das
> Land bzw. die Druckerei überhaupt vergeben ist

Dann musst du aber auch noch ein Datum übergeben und eine Glaskugel für 
die Zukunft einbauen ;-)  Kommerzielle Softwarehäuser machen sowas um 
Wartungsverträge zu rechtfertigen.  Für sich selbst sollte man so einen 
Schmu nicht machen.  Diese Routine soll die Checksum und 
(notwendigerweise) den lexikalischen Aufbau überprüfen[2].  Semantische 
Checks (Länder-, Druckereikodes, Nummernbereiche, etc) gehören woanders 
hin.  "Do one thing and do it right" ;-)

[1] Die triviale Implementation ist heutzutage wohl sogar schneller.
[2] Btw, ein Test fehlt nocht: letzte Ziffer != '0'.

von asdfasd (Gast)


Lesenswert?

Müller schrieb:
> Länderkennung und Druckerei Kennung Überprüfung ist da auch drinne

Halte ich nicht viel von, s.o.

> Jedoch musste ich die Druckereikennungen auf Heap laden,

Wenn schon, dann doch ordentlich.  Mal dir mal auf, wie deine Daten 
jetzt im Speicher liegen und was du wirklich brauchst.  Auch scheint es 
mir etwas unnötig, die Daten bei jedem Check neu anzulegen.

> eine normale Iniatilisation auf den Stack [...] hat aus mir nicht
> näher bekannten Gründen nicht geklappt.

Auf den Stack packt man so etwas eh nicht.  Und wenn etwas nicht klappt 
(obwohl man weiß, dass es gehen sollte), tut man gut daran, 
herauszufinden, wo der Fehler ist.  Dadurch lernt man am meisten ;-)
(Tipp: bei der Definition/Initialisierung brauchst du keine Sternchen.)

> explizit auf EOF prüfen

EOF ist ein Rückgabewert von getchar & co.  In Strings wirst du das 
nicht finden.  Ein EOF-Test befreit dich aber eh nicht davon, die 
Argumente von isigit & co nach unsigned char casten zu müssen (signed 
char hat Werte von -128 bis 127, gültige Werte für isdigit & co sind -1 
bis 255).

von Yalu X. (yalu) (Moderator)


Lesenswert?

asdfasd schrieb:
>> korrekterweise sollte man deswegen in der Funktion CheckCode das
>> Locale temporär auf "C" setzen.
>
> Keine so gute Idee.  Zum einen ist setlocale ein Schwergewicht (lädt
> Dateien von Platte)

Kann man nicht davon ausgehen, dass wenigstens das C-Locale bereits
geladen ist? Das muss ja vor dem ersten setlocale-Aufruf auch schon
verfügbar gewesen sein.

Alternativ gäbe es ja noch die POSIX-Funktionen is*_l, denen man das
gewünschte Locale (das man beim Programmstart einmal anlegt) als
Argument übergibt. Leider sind diese lokalisierten ctype-Funktionen
(noch) nicht in den C-Statndard eingeflossen.

> und zum anderen, und viel wichtiger, setlocale ist global und ändert
> das Locale aller Threads des Prozesses.

Ja, das ist natürlich blöd. In C++ ist diese ganze Lokalisierei deutlich
besser gelöst. Dort muss man das globale Locale praktisch nie ändern.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Müller schrieb:
> Jedoch musste ich die Druckereikennungen auf Heap laden, eine normale
> Iniatilisation auf den Stack mittels const char **kennung = {"..",
> ".."...
> hat aus mir nicht näher bekannten Gründen nicht geklappt.

Mit ={...} kannst du ein Array oder eine Struktur intialisieren, nicht
aber einen Zeiger. Anders als bei String-Literalen wird hier nicht
automatisch Speicher reserviert. Folgendes geht aber:

1
static const char kennungen[][3] = {
2
  "EA", "EB", "NA", "PA", "SA", "SB", "SC", "SD", 
3
  "SE", "SF", "TA", "TB", "TC", "UA", "UB", "UC", 
4
  "UD", "UE", "UF", "VA", "VB", "XA", "YA", "ZB" 
5
};
6
7
static size_t elements = sizeof kennungen / sizeof kennungen[0]; // = 24

Die Variable kennungen ist also ein Array, desswen Elemente wiederum
Arrays mit jeweils 3 Chars sind.

Möglich wäre auch ein Array von Zeigern, die auf die einzelnen Strings
zeigen:

1
static const char *kennungen[] = { "EA", "EB", ... };

Hier wird aber zusätzlich Speicherplatz für die Zeiger benötigt, und der
Zugriff auf die Strings erfordert zusätzlich die Dereferenzierung dieser
Zeiger, so dass im vorliegenden Fall die erste Variante effizienter ist.

Ansonsten sollte aber auch deine Methode mit den mallocs funktionieren.
Du solltest aber in der Deklaration von kennungen das const weglassen,
da du ja in k_init Daten hineinkopierst. Der Compiler meckert das an,
wenn du die Warnungen aktivierst.

von Müller (Gast)


Lesenswert?

asdfasd schrieb:
> EOF ist ein Rückgabewert von getchar & co.  In Strings wirst du das
> nicht finden.  Ein EOF-Test befreit dich aber eh nicht davon, die
> Argumente von isigit & co nach unsigned char casten zu müssen (signed
> char hat Werte von -128 bis 127, gültige Werte für isdigit & co sind -1
> bis 255).

Der User soll später die Möglichkeit haben, den Code einzugeben in die 
Console. Der kann ja auf die Idee kommen und Ctrl+d eingeben.

Trotzdem hast du nicht unrecht, damit dass jedesmal neu Speicher geladen 
wird. Mit Yalus Tipps werde ich das nochmal überarbeiten.

Isdigit verwende ich nicht. Mein Ziel ist es noch, komplett auf die 
Ctype Funktionen zu verzichten

@Yalu
Danke für die Hilfe mit der Initialisierung, werde das entsprechend 
ändern. Dann kann ich die init und free Sachen wieder rausschmeißen, 
super. Macht den Code ja wieder übersichtlicher.

Schönen Abend noch!

von Müller (Gast)


Angehängte Dateien:

Lesenswert?

So kurzes Update, habe jetzt beschriebene Aktualisierung vorgenommen.
Ich weiß die Ländererkennung / Druckerei Erkennung mag für manche nicht 
so doll sein, aber die bleibt da ! ;)

Anregung sind weiterhin erwünscht.

Schönen Abend noch.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.