Hallo Leute!
Oft steht man vor der Aufgabe einen cpp-String in eine Zahl, sei es Integer oder Fließkomma zu konvertieren. Dabei gibt es zwei Wege bei der Fehlerbehandlung. Entweder, man hofft auf eine
korrekte Eingabe des Benutzers und präsentiert ihm dann die Fehlermeldung, oder man fängt
etwas die fehlerhaften Eingaben vorher ab.
zuerst aber wieder der header strtest.h:
#ifndef STRTEST_INC_
#define STRTEST_INC_ 1
#include <iostream>
#include <sstream> // _atod
#include <cstdlib> // EXIT_SUCCESS
#include <string.h> // strlen
//void StringToChar(std::string wort, char satz[]);
//double _atod(std::string zawo);
//int ist_erlaubt(std::string mot, std::string erlaubt);
int check_cppstring(std::string to_check, std::string allowed, int *not_allowed_chars);
int check_cppstring_b(std::string to_check, std::string allowed, int *not_allowed_chars, std::string *verboten);
int korr_cppstring(std::string *to_check, std::string todel);
int Kommatest(std::string *mot);
class strtest
{
public:
strtest(){};
~strtest(){};
void StringToChar(std::string wort, char satz[]);
double _atod(std::string zawo);
int ist_erlaubt(std::string mot, std::string erlaubt);
int check_cppstring(std::string to_check, std::string allowed, int *not_allowed_chars);
int check_cppstring_b(std::string to_check, std::string allowed, int *not_allowed_chars, std::string *verboten);
int korr_cppstring(std::string *to_check, std::string todel);
int Kommatest(std::string *mot);
};
#endif
nun die dazugehörige Datei strtest.cpp:
// file strtest.cpp
#include "strtest.h"
// converts a cpp string to char
void strtest::StringToChar(std::string wort, char satz[])
{
int slei, wolen;
wolen = wort.length();
for (slei = 0; slei < wolen; slei++)
{
satz[slei] = wort[slei];
satz[slei +1] = '\0';
}
}
// converts a number stored in a cpp string to a double value
double strtest::_atod(std::string zawo)
{
double rewer = 0;
std::istringstream b(zawo);
b >> rewer;
return rewer;
}
// check if char 'wort' exists in string 'soll'
// if yes return value = 1, otherwise 0
int strtest::ist_erlaubt(std::string mot, std::string erlaubt)
{
int i, zaehler = 0, lgeperm;
std::size_t found;
std::string str2 = "";
std::string charperm = "";
lgeperm = erlaubt.length();
for (i = 0; i < lgeperm; i++)
{
// cpp-string 'erlaubt' in Teile zerlegen
charperm = erlaubt.substr(i, 1);
found = charperm.find(mot);
if (found != std::string::npos) // Wenn teil gefunden wurde
{
zaehler++;
break;
}
}
//std::cout << "*mot=" << mot << " erlaubt["<< i << "]= "<< erlaubt[i] << " zaehler: " << zaehler << std::endl;
return zaehler;
}
// checks whether the individual characters of c string 'wort* are existing in c string 'allowed'
// return value = number of characters of argument 1 were stored in argument 2 (c string 'allowed')
// argument 1 = ASCII string to be checked
// argument 2 = List of characters where allowed, stored in ASCII string 'allowed'
// argument 3 = number of character where found in string 'to_check' ande are not stored in argument 2
int strtest::check_cppstring(std::string to_check, std::string allowed, int *not_allowed_chars)
{
int i, length_to_check, retval = 0, length_allowed, result = 0, banned = 0;
std::string buchstabe = "";
length_to_check = to_check.length(); // i
length_allowed = allowed.length();
if ((length_to_check == 0) || (length_allowed == 0)) return -1; // if length of to_check or allowed is Zero
for (i = 0; i < length_to_check; i++)
{
buchstabe = to_check.substr(i, 1);
result = ist_erlaubt(buchstabe, allowed);
if (result == 1) ++retval;
else banned++;
}
*not_allowed_chars = banned;
return retval;
}
// checks whether the individual characters of c string 'wort* are existing in c string 'allowed'
// return value = number of characters of argument 1 were stored in argument 2 (c string 'allowed')
// argument 1 = ASCII string to be checked
// argument 2 = List of characters where allowed, stored in ASCII string 'allowed'
// argument 3 = number of character where found in string 'to_check' ande are not stored in argument 2
// argument 4 = the characters wher forbidden are here stored
int strtest::check_cppstring_b(std::string to_check, std::string allowed, int *not_allowed_chars, std::string *verboten)
{
int i, length_to_check, retval = 0, length_allowed, result = 0, banned = 0;
std::string buchstabe = "";
length_to_check = to_check.length(); // i
length_allowed = allowed.length();
if ((length_to_check == 0) || (length_allowed == 0)) return -1; // if length of to_check or allowed is Zero
for (i = 0; i < length_to_check; i++)
{
buchstabe = to_check.substr(i, 1);
result = ist_erlaubt(buchstabe, allowed);
if (result == 1) ++retval;
else
{
*verboten += buchstabe;
//if(result == 0) to_check.erase(i, i); // eventuell ersten Stringteil loeschen
banned++;
}
}
//std::cout << "veraenderter String : " << *verboten << std::endl;
*not_allowed_chars = banned;
return retval;
}
// deletes characters where stored in argument 2(todel) and found in string 'to_check'
// return value is the number of deleted characters
int strtest::korr_cppstring(std::string *to_check, std::string todel)
{
int i, j, length_to_check, retval = 0, length_todel;
std::string buchstabe = "";
std::string delbuc = "";
std::size_t found;
length_to_check = to_check->length(); // Laenge des zu korrigierenden Strings
length_todel = todel.length(); // Laenge der Liste der zu loeschenden Zeichen
if ((length_to_check == 0) || (length_todel == 0)) return -1; // if length of to_check or allowed is Zero
for (i = 0; i < length_to_check; i++)
{
buchstabe = to_check->substr(i, 1); // zu korrigierenden String in einzelne Zeichen zerlegen
for (j = 0; j < length_todel; j++)
{
delbuc = todel.substr(j, 1); // String der Liste der zu loeschenden Zeichen in einzelne Zeichen zerlegen
found = to_check->find(delbuc); // Suche zu Loeschende Zeichen
if (found !=std::string::npos) // Wenn ei nzu loeschendes Zeichen gefunden
{
//std::cout << " found: " << found;
//std::cout << " #i: " << i << " result: " << result << " verboten nach del: " << *to_check << std::endl;
to_check->erase(found, 1); // an Position 'found' das gefundene Zeichen loeschen
length_to_check = to_check->length(); // erneut zu korrigierenden String Laenge ermitteln
//std::cout << " *i: " << i << " result: " << result << " verboten nach del: " << *to_check << std::endl;
retval++; // retval is the number of deleted characters
}
}
//std::cout << "i: " << i << " result: " << result << " verboten nach del: " << *to_check << std::endl;
}
return retval; // return value is the number of deleted characters
}
int strtest::Kommatest(std::string *mot)
{
int slei, zaehler = 0;
std::size_t found, xstart;
std::string str2;
std::string Zeichen[4] = {",", ";", ":"};
//lge = mot->length();
std::cout << "mot vorher..........: " << *mot << std::endl;
//Suche Zeichen und ersetzte erstes Vorkommen durch Punkt
for (slei = 0; slei < 3; slei++)
{
found = mot->find(Zeichen[slei]);
if (found != std::string::npos)
{
mot->replace(found,1, ".");
std::cout << "1 mot nachher.......: " << *mot << std::endl;
}
}
found = mot->find(".");
while(found!= std::string::npos )
{
xstart = found + 1;
found = mot->find(".", xstart);
//std::cout << "*xstart: " << xstart << " found: "<< found;
//std::cout << " *found=" << found << std::endl;
if (found != std::string::npos)
{
mot->erase(found, 1); //nachfolgende Punkte löschen
std::cout << "*mot nachher: " << *mot << std::endl;
//return zaehler;
}
}
std::cout << "mot nachher.........: " << *mot << std::endl;
return zaehler;
}
Nun die main.cpp selbst:
/** string_to_char wandelt als cpp-string gespeicherte Zahlen in ASCII-strings um
* und prueft cpp-strings auf unerlaubte Zeichen. Die Zahl der erlaubten Zeichen
* sowie der unerlaubten Zeichen werden saparat wiedergegeben.
* Die Funktion check_cppstring_b ueberprueft den string in argument 1 ob
* dieser Zeichen enthaelt, welche nicht in der Liste von argument 2 stehen
* Rueckgabewert dieser Funktion ist die Anzahl der gefundenen 'erlaubtern' Zeichen
* welche in argumenbt 2 definiert sind.
* Die Anzahl der Zeichen, welche gefunden wurde und nicht in argument 2 definiert sind
* werden in argument 4(cpp-string) gespeichert.
* Danach uebernimmt die Funktion korr_cppstring die Aufgabe, diese im zu pruefenden
* String zu loeschen. Der zu korrigierende String ist argument 1, die Zeichen welche
* eventuell aus diesem String zu loeschen sind, werden in argument 2 definiert.
*/
#include "strtest.h"
int main(int argc, char **argv)
{
strtest stst;
std::string wort = "123.4567";
std::string test = "123,4;+,·#-,a.b:5,6:7,a.bc";
char ascii_char[200] = {0};
std::string erlaubt = "0.123456789";
std::string verboten = "";
//char permitted[15] = {"0.123456789"}; // {"0.123456789"};
double dzahl = 0;
int s = 0, fehler = 0;
std::cout << "String..............: "<< wort << std::endl;
s = stst.check_cppstring(wort, erlaubt, &fehler);
stst.StringToChar(wort, ascii_char);
std::cout << "ASCII-char..........: " << ascii_char << std::endl;
dzahl = stst._atod(wort);
std::cout << "double value........: " << dzahl << std::endl << std::endl;
std::cout << "cpp string 'test'...: " << test << std::endl;
stst.Kommatest(&test); // erstes Komma durch Punkte ersetzen, weitere loeschen
s = stst.check_cppstring_b(test, erlaubt, &fehler, &verboten);
std::cout << "good chars..........: " << s << std::endl;
std::cout << "wrong chars.........: " << fehler << std::endl;
std::cout << "verboten............: " << verboten << std::endl;
std::cout << "test vor del........: " << test << std::endl;
s= stst.korr_cppstring(&test, verboten);
std::cout << "verboten nach del...: " << test << std::endl;
return EXIT_SUCCESS;
}
Die Ausgabe des Beispiels sieht dann so aus:
String..............: 123.4567
ASCII-char..........: 123.4567
double value........: 123.457
cpp string 'test'...: 123,4;+,·#-,a.b:5,6:7,a.bc
mot vorher..........: 123,4;+,·#-,a.b:5,6:7,a.bc
1 mot nachher.......: 123.4;+,·#-,a.b:5,6:7,a.bc
1 mot nachher.......: 123.4.+,·#-,a.b:5,6:7,a.bc
1 mot nachher.......: 123.4.+,·#-,a.b.5,6:7,a.bc
*mot nachher: 123.4+,·#-,a.b.5,6:7,a.bc
*mot nachher: 123.4+,·#-,ab.5,6:7,a.bc
*mot nachher: 123.4+,·#-,ab5,6:7,a.bc
*mot nachher: 123.4+,·#-,ab5,6:7,abc
mot nachher.........: 123.4+,·#-,ab5,6:7,abc
good chars..........: 8
wrong chars.........: 15
verboten............: +,·#-,ab,:,abc
test vor del........: 123.4+,·#-,ab5,6:7,abc
verboten nach del...: 123.4567
Getestet wird hier der String "123,4;+,·#-,a.b:5,6:7,a.bc";
Was für Zeichen erlaubt sind ist im String 'erlaubt festgehalten;
std::string erlaubt = "0.123456789";
Nach der Korrekturmaßnahme sieht das Ergebnis so aus:
123.4567
Manchmal kann es vorkommen, das das eine oder andere Zeichen
bei der Eingabe einer Zahl versehentlich mit rein rutscht.
Zugegeben ist der String 'test' ein extremes Beispiel.
Trotzdem kann man jetzt damit keine Programme schreiben, bei denen
man irgendwelche durchgedrehten Knallköpfe mit einer Glättkelle für
Maurer vor die Tastatur stellt, um diese für Jobs zur Datenerfassung umzuschulen.
Gott bewahre!
Auf die Idee bin ich gekommen, da meine beiden Hände durch Arbeitsunfälle ziemlich in
Mitleidenschaft gekommen sind. Spätere Operationen brachten keine nennenswerte
Verbesserung. Im Gegenteil, mit den Jahren wurde es immer schlimmer.
Aber zurück zum Thema.
Manchmal ist es bei Eingaben eben wie bei der Suche nach alten Münzen mit dem
Metalldetektor. Viel Dreck muss beiseite geschafft werden, um das gewünschte zu erhalten.
Für eventuelle Test mit oder ohne Glättkelle, ob jetzt betrunken oder nicht, ob zu Sylvester
oder sonst irgendwann, übernehme ich keinerlei Haftung!
Hoffe inspiriert zu haben
Guiseppe