Fragen zur Machbarkeit in C/C++

Hallo Duda

Das funktioniert so aber nicht, wenn du hast:
std::string hex = "3 2 2 6 3 A";

Dann ist:
hex[0] = 51
hex[1] = 50
hex[2] = 50
hex[3] = 54
hex[4] = 51
hex[5] = 65

Du müsstest also bevor du das in deiner Summe berechnest jedes Zeichen zuerst noch umwandeln, das kannst du eigentlich auch automatisieren:
C++:
void parseNumbers(const std::string& input, std::vector<unsigned char>& values) {
    std::stringstream stream;
    stream << input;
    unsigned int curValue = 0;
    while(stream >> std::hex >> curValue) {
        values.push_back(static_cast<unsigned char>(curValue));
    }
}

void theFunction() {
    std::string hex = "3 2 2 6 3 7 4 2 2 7 4 8 C 0 8 7 0 0 8 4 3 A";
    std::vector<unsigned char> numbers;
    parseNumbers(hex, numbers);
    unsigned int sum1 = 0;
    unsigned int sum2 = 0;
    for(int i = 0; i < numbers.size(); i += 2) {
        sum1 += numbers[i];
        sum2 += 2 * numbers[i + 1];
    }

    unsigned int sum3 = sum1 + sum2;
    unsigned int sum4 = sum3 % 34;
}

Viele Grüsse
Cromon
 
Hallo Cromon,
ich freue mich besonderst über Dein Feedback, es ist so, als wenn man einen alten Freund wieder begegnet.
Ja ich muß zugeben, das meine Darstellung nicht C/C++ gerecht ausgedrückt ist und deshalb sicherlich einige
Leser etwas irritiert hat. Aber so etwas gehört natürlich auch zur Alltäglichkeit und man muß sich da als Leser
auch Gedanken machen können, was will mir der Schreiber eigentlich sagen.
Ich bin ein nicht vorgebildeter, an das Programmieren Interessierter. Ich denke noch nicht wie ein Programmierer, deshalb kann ich mir nur die Vorgänge und den Programmablauf gedanklich vorstellen. Was ich auch zu schildern
versucht habe. Aber es ist nicht für jedermann einleuchtend gewesen. Aber Dir scheint meine Schilderung auszu-
reichen um erkennen zu können was ich meine. Ganz toll finde ich es von Dir, daß Du auf die Mängel hinweist,
welche nicht so ohne weiteres umzusetzen sind(ich habe auch daran gedacht, aber in meiner Euphorie, wie ich der
Berechnung zu Leibe rücken kann, natürlich die vorherige Umwandelung in Dezimalzahlen übersprungen.
Das diese Umwandelung ein wichtiger Faktor ist, das weiss ich selbstverständlich, aber trotzdem danke für
Deinem Hinweis diesbezüglich.
Sehr hilfreich und dankenswert ist natürlich die Mühe, welche Du Dir gemacht hast, um mir auf die Sprünge zu
helfen. Also danke für Deinen Code, ich werde ihn morgen handschriftlich abschreiben und mir mehrmals zu
Gemüte führen. Ich bin begeistert, von dem was Du aus meinen Angaben gemacht hast.
Ich denke, daß Du mich weiter motivieren willst, was Dir hiermit voll und ganz gelungen ist.

Viele Grüsse

Duda
 
Hallo Duda

Freut mich zu hören! Vielleicht noch kurz zur Erklärung der eigentlich wichtigsten Zeile:
C++:
while(stream >> std::hex>> curValue){

stringstreams eignen sich super für Konvertierungen von Typen. Grundsätzlich kannst du dir nen stringstream vorstellen wie std::cout und std::cin kombiniert. Mit << schreibst du rein (wie bei cout) und mit >> liest du aus (wie bei cin). Das lässt sich dann auch kombinieren:
C++:
std::stringstream stream;
std::string value;
stream << "AValue" >> value;

value würde dann den Text "AValue" beinhalten.

std::hex ist ein Modifizierer, welcher dem stringstream sagt, dass der nächste Wert als Hexadezimalzahl interpretiert werden soll. "Der nächste Wert" heisst bei einer Zahl (eine Ziffer ist eine Zahl) standardmässig bis zum nächsten Whitespace (Leerschlag, Newline, Tabulator, usw) oder zu einem in der gewählten Basis nicht lesbaren Zeichen (bei std::hex also alles ausser 0-9, A-F, a-f).

Du solltest also vielleicht nach parseNumbers überprüfen ob der Inhalt gültig war indem du schaust ob genügend Zahlen drin sind. Zuerst solltest du prüfen, ob dein Ziffernstring ungerader Länge ist, anschliessend ob die Anzahl ausgelesener Zahlen (str.length() + 1) / 2 entspricht.

Viele Grüsse
Cromon
 
Hallo Cromon,
zunächst möchte ich mich für Deine Ergänzungen in Bezug auf die wichtigste Zeile in Deinem Code und für die weiteren Hinweise bedanken. Habe wie angekündigt gestern alles vom Bildschirm abgeschrieben. Danach habe
ich die Zeilen auf mich wirken lassen das heißt:"Ich habe den Code wieder und immer wieder gelesen, ungefähr
so, als wenn man an einem köstlichem Getränk nippt und immer wieder nippt, weil man es geniessen möchte,
ohne daß das Glas zu schnell leer wird. Ich wollte nicht Wein oder so schreiben, sonnst denkst Du noch ich bin
Weinhändler und benutzt dieses schöne Internet-Portal zur Werbung. :) :) :) Doch zurück zum Code-Inhalt.
Habe mir zu den vielen Worte in englischer Sprache meine Gedanken gemacht. Es ist so, ich beherrsche das Englische nicht so, daß ich mich damit verständigen könnte. Also Sprechen und Schreiben, da ist tote Hose, um
es mal im Volksmund auszudrücken. Beim Lesen bin ich nicht ganz so rückständig und wenn ich mal auf ein mir
unbekanntes Wort stoße, dann habe ich ein Elektronische-Wörter-Buch. Beim Lesen von Text ergeben sich auch oft die Bedeutung von Wörtern aus dem Satzzusammenhang. Naja, langes Schreiben, kurzer Sinn, ich versuche
die Bedeutung Deiner Worte im Code auf den Grund zu gehen.
Den ersten Aufhänger habe ich mit dem Wort "void", ich hoffe es ist nicht die Anrede für mich. Weil mir fällt auf die Schnelle für so ein Kürzel nur "vollidiot" ein. Das wollte ich natürlich ungern sein, selbst wenn ich es wäre,
dann würde ich es nicht zugeben. Also zur Sicherheit schnell mal mein EWB aufgeklappt, da steht zur Auswahl:
"leer", "nichtig" und "sinnlos", also ohne Sinne, also doch sowas wie nichts in der Birne, wie es oft auch genannt
wird. Ich bin immernoch ganz verstört und denke: "Alos doch sowas wie "without brain".
Aber hier geht es um C++, deshalb habe ich auch mal schnell in das Stichwortverzeichnis des C++-Lehrbuches
nachgeschaut und siehe da steht:"Das Schlüsselwort "void" kann man überall dort verwenden, wo der Compiler eine Typenangabe erwartet, man aber keinen Typ angeben kann oder möchte.
Da viel mir ein Stein vom Herzen, denn nun weiss. daß Du mich nicht beleidigen wolltest. ;-)
Mir "parse" war es dann schon wesentlich einfacher, denn da fand ich sofort "zerlegen", auch" zergliedern" oder
"annalysieren etc.. geht da. Weil dann gleich "Numbers" mit so eine Art Anweisungsformel dahinter steht, deshalb bezieht sich das Ganze wohl auf die einzugebende Zeichenkette, welche hier "string" genannt wird. Naja, innerhalb der gebogenen klammern stehen so Einiges auch Abgekürztes, wie: "const, std::string& input, std::vector<unsigned char>& values. Mit dem Ersten ist "constant" gemeint, das folgende "std" entspricht Deiner
Art zuschreiben, weil Du dabei auch an ältere Compiler denkst, welche das "namespace std" nicht kennen. So mit beugst Du vor und schreibst es jedesmal in der abgekürzten Form. Zu dem 4 Punkten, was sicherlich zwei Doppel-
punkte sind, da weiß ich nichts zu sagen, habe darüber irgendwas gelesen, aber mein Kopf ist ein Sieb und jetzt
schreibe ich und kann an nichts Anderes denken. Dazu muß ich mich erneut schlau machen, aber nicht jetzt, denn jetzt will ich Dir zeigen, daß ich mir Gedanken mache und auch nicht zu faul an der Tastatur bin, um mir ein Programm zu schreiben. Ich weiß ebend noch nicht genug über C++ um selbst zu programmieren.
Doch weiter in Deinen Klammern. String& input, std und vector kenne ich, wobei ich nicht so genau weiss was der vector hier macht, ich nehme an, daß er die Funktion eines Zeigers hat und über ihn aufdie vorzeichenlosen Character und ihre Werte hingewiesen wird. Ja in der nächsten Zeile da ist wieder "std", was ich schon zu erklären versucht habe. Ansonsten strömt(was auch fließt sein kann) da ein Zeichenkettestrom. Dann wird was eingegeben, denn "input" das ist mir ein Begriff. Der nun folgende vorzeichenlose Datentype, das ist auch klar für mich. Doch jetzt kommt wieder was unbekanntes, nähmlich "cur", damit kann ich nichts anfangen,
also mein EWB, da steht "Köter" oder"gemeiner Kerl". Nein das kann nicht sein, was ist ein "Hund wert"oder
wie "bewertet man eine Kerl". Da muß ich wohl selbst meinen Denkapparat einschalten und mir Gedanken machen. Siehe da, es ist vielleicht auch nur eine Abkürzung und es heißt "current" und verbunden mit Value,
dann kann es nur in unserer Sprache, der im Umlauf befindliche oder aktuelle Wert sein. Ja in der Mathematik
üblich gibt es "sind" oder "gleich", also =, doch hier ist es eine Zuweisunf, womit eine 0 zugewiesen wird.
Nun möchte ich auch noch auf das Semikolon eingehen, wovon ich schon zwei übersprungen habe.
Ja, mit dem ; werden grundsätzlich Anweisungen abgeschlossen, damit wäre auch dies geklärt.
Jetzt kommen wir zu der wichtigsten Zeile, darauf reimt sich Weile. Dazu fällt mir ein: "Warte, warte, eine Weile,
dann kommt Hamann auch zu Dir, mit dem Hackebeilchen macht er Hackefleisch aus Dir,........Naja, wer da noch wartet, der kann lange warten, denn der Hamann wurde hingerichtet.
Doch mit while wird auch irgendwie gewartet, bis es geströmt hat und die hex ihre aktuellen Werte haben.
Diese Werte bleiben nur eine Weile bestehen, denn mit values.push_back werden diese Werte in den Hintergrung gestoßen oder verschoben und gleichzeitig werden daraus andere, konstante, vorzeichenlose Zeichen mit aktuelleren Werten
gebildet. Das Meiste von diesem Vorgang findet innerhalb der gebogenen Klammern statt.
 
Fortsetzung meines nicht ganz zu Ende gebrachten Textes.

Hallo Cromon,

ich bin nicht besonderst schnell mit der Tipperei, wollte eigentlich Schluß machen, aber da war wohl auch meine Zeit zum Schreiben bzw, zum Bearbeiten schon abgelaufen. Deswegen nun dieser kleine Nachtrag.

Ich bin zwar jetzt etwas aus dem Konzept, aber nur noch soviel, ich hoffe das Lesen hat Dir Spaß gemacht.

Viele Grüsse

Dude
 
das folgende "std" entspricht Deiner
Art zuschreiben, weil Du dabei auch an ältere Compiler denkst, welche das "namespace std" nicht kennen. So mit beugst Du vor und schreibst es jedesmal in der abgekürzten Form.
Das ist falsch. Woher hast du die Information, dass ältere Compiler dies nicht unterstützen?

Ironischerweise hätte dazu eine perfekte Referenz, allerdings auf Englisch.
Zusammenfassend lässt sich sagen, dass man using namespace std nicht nutzen sollte, denn dies importiert alle "Dinge" aus dem Namespace in den aktuellen Namespace (=Namensraum; Ansammlung von Namen von Funktionen/Variablen/Klassen/etc.). Wenn du nun eine gleichnamige Funktion in deinem Namespace oder aus einem anderen importierten Namespace hast, wirst du früher oder später Probleme bekommen. Ein Hauptproblem ist, dass du eine Funktion X() aus dem Namenraum N aufrufen willst, aber tatsächlich X() aus dem Namensraum N2 aufrufst. So entstehen Bugs (=Fehler).

Das sind zwei Doppelpunkte, richtig. Beispielsweise heißt "N::B", dass du auf den Bezeichner "B" aus dem Namensraum "N" zugreifst.

Doch weiter in Deinen Klammern. String& input, std und vector kenne ich, wobei ich nicht so genau weiss was der vector hier macht
Vector ist ein Container (=Behälter). Er kann Variablen eines Types speichern. Hier ist der Typ "unsigned char". Er speichert jedes Objekt, dass du per push_back() hinten anfügst, mit einer Zahl. Der Zähler beginnt bei 0. Mit dem Zähler kannst du auch auf einzelne Objekte zugreifen.

Ansonsten strömt(was auch fließt sein kann) da ein Zeichenkettestrom.
Im obigen Zusammenhang mit Streams bedeuten die Operatoren << und >> oft Datenfluss. In anderen Zusammenhängen bedeuten die allerdings etwas ganz Anders: Bit Shifting. Letzteres kannst du bei Wikipedia (auch auf Deutsch) nachlesen.

"cur" steht für current (=aktuell), richtig. Dies ist eine oft genutzte Abkürzung.
Anweisungen sind oft mit Semikoli abzuschließen, richtig.

Das einfache Gleichheitszeichen (=) wird in vielen Programmiersprachen für Zuweisungen genutzt. Zwei aufeinanderfolgende Gleichheitszeichen (==) für einen Vergleich. a == b ergibt 'true' (richtig), wenn a b entspricht (grob gesagt).

While ist ein Schleifentyp. Siehe auch bei der Wikipedia

Übrigens nennt man gebogene Klammern auch runde Klammern (bzw. habe ich gebogene Klammern noch nie gehört) ;)


PS: Du scheinst ja sehr viele Assoziationen zu allen möglichen Bereichen des Codes zu haben! Das ist schon einmal eine sehr gute Voraussetzung fürs Programmieren :) Nur müssen diese jetzt ein wenig mehr auf den eigentlichen Inhalt bezogen werden, wenn auch manch Köter-Gedanken lustig sind :D
 
Hallo ComFreek,
auch Dir sei Dank gesagt, ja ich meine es wirklich.
Denn ich freue mich natürlich auch sehr über Dein Feedback,
mit den für mich wissenswerten Anmerkungen.
Mein Text sollte auch nur zur Aufmunterung sein,
denn nur dumme Fragen möchte ich auch nicht nur stellen.
Deshalb mal so eine kleine Geschichte mit etwas Humor auch ein paar Dinge einflechten,
welche zum Schmunzeln anregen sollten. So war es auch mit den Klammern gemeint,
welche bevor sie rund sind, doch irgendwie gebogen worden sind. :) :) :-
Nimm es nicht so ernst, daß auch Du Humor hast, das sieht man ja in Deinem letzten Satz.

Doch noch kurz zu Deiner Frage in Bezug auf Namespace,
ich hoffte es ist das Gleiche wie Namensbereiche, denn da habe ich gelesen:
"Wenn Sie mit einem älteren Compiler arbeiten, der keine Namensbereiche unterstützt",
dann löschen Sie die Anweisung "using namespace std:" .
Hiermit zitiere ich einen Autor aus einem meiner beiden Bücher.
Ich fühlte mich deshalb mit meiner Aussage ziemlich sicher.
Wenn dem nicht so ist, dann habe ich durch Dich wieder was dazugelernt.
So nun möchte ich es erstmal gut sein lassen.
Mit einigen Fragen werde ich mich dann in den nächsten Tage melden.
Denn ich habe noch einiges zu lernen, bis ich anfange Code zu schreiben.

Viele Grüsse

Duda
 
Salut Duda

Ein C++-Compiler muss Namespaces unterstützen, genau so muss er auch unsing namespace und alle möglichen Kombinationen davon unterstützen. Tut er irgendwas davon nicht ist es kein C++-Compiler. Damit möchte ich allerdings jetzt nicht sagen, dass Du immer using namespace verwenden sollst, im Gegenteil, verwende es eigentlich nur ein absoluten Ausnahmesituationen. Den Grund hat dir ComFreek genannt. Bester Header um das zu veranschaulichen ist algorithm. Include algorithm und Du hast Funktionen wie std::count, std::sort, usw eingebunden. Hast Du nun using namespace std heissen die Funktionen nun alle count, sort, usw. Verwechslungsgefahr riesig! Von daher wenn dann nur wenn Du wirklich weisst, was Du alles einbindest das verwenden (Beispiel: Innerhalb einer Zeichenfunktion ist ein 'using namespace Gdiplus' keine Todsünde).

Hier noch mein Code so gut wie möglich in Deutsch:
C++:
void zahlenExtrahieren(const std::string& eingabeZeile, std::vector<unsigned char>& zahlenSpeicher) {
    std::stringstream konvertierungsStrom;
    konvertierungsStrom << eingabeZeile;
    unsigned int aktuelleZahl = 0;
    while (konvertierungsStrom >> std::hex >> aktuelleZahl) {
        zahlenSpeicher.push_back(static_cast<unsigned char>(aktuelleZahl));
    }
}

void theFunction() {
    std::string hex = "3 2 2 6 3 7 4 2 2 7 4 8 C 0 8 7 0 0 8 4 3 A";
    std::vector<unsigned char> zahlen;
    zahlenExtrahieren(hex, zahlen);
    unsigned int sum1 = 0;
    unsigned int sum2 = 0;
    for (int i = 0; i < zahlen.size(); i += 2) {
        sum1 += zahlen[i];
        sum2 += 2 * zahlen[i + 1];
    }

    unsigned int sum3 = sum1 + sum2;
    unsigned int sum4 = sum3 % 34;
}

Zu deine Fragen:
while(konvertierungsStrom >> std::hex >> aktuelleZahl

Wie ich sagte ist das >> und << zu verstehen wie bei std::cout/std::cin, mit << wird etwas 'ausgegeben', mit >> etwas eingelesen. Bei std::cout ist die Ausgabe und Einlese auf der Konsole, bei std::stringstream in eine/aus einer Zeichenkette, die vom std::stringstream selber verwaltet wird. Das heisst wenn Du << machst wird die Zeichenkette erweitert, wenn Du >> machst wird aus der Zeichenkette verarbeitet. Diese Operatoren (>> und <<) geben für die Ströme (std::cout und std::cin sind auch nur Ströme und erben von std::istream (Eingabestrom) für std::cin und std:ostream (Ausgabestrom) für std::cout und deshalb unterstützten sie die Operatoren << und >>) jeweils zurück ob die Aktion erfolgreich war oder nicht. Dies ist allerdings etwas einfacher gesagt als verstanden. std:ostream und std::istream haben eine spezielle Überladung für den Operator !, das heisst, wenn man ! auf einen std:ostream anwendet, nachdem bei einer Aktion etwas schiefgelaufen ist (zum Beispiel >> mit einer Zahl und in der Eingabe war keine Zahl) wird da 'true' zurückgegeben. Zudem haben std:ostream und std::istream einen speziellen Operator der es ermöglicht ein Objekt davon in einen boolean umzuwandeln. Aus diesem Grund geht auch das:
C++:
bool allesOk = (bool) std::cin; // das (bool) ist nötig, weil der Operator eine explizite Konvertierung von std::istream nach bool ermöglicht, aber nicht eine implizite

Das heisst diese Zeile:
while(konvertierungsStrom >> std::hex >> aktuelleZahl) wird zu 'false' ausgewertet, wenn bei der Auslese einer Zahl (hexadezimal wegen std::hex) etwas nicht funktioniert hat.

Wenn Du noch mehr Fragen hast einfach stellen!

Viele Grüsse
Cromon
 
Hallo Cromon,
sei auch Du mit einem Salute gegrüßt, was mich etwas an Italien erinnert.
Du bringst mich echt in Verlegenheit, denn ich muß wohl als erstes ein Programm machen,
welche für Dich in einer Tour das Wort "Danke " ausgibt.
Du und auch ComFreek geben sich echt Mühe mit mir, also danke dafür.
Natürlich auch danke an die Mitleser, welche sich Mühe geben beim Entziffern meines Kauderwelsch
was englisch soviel wie "hotch potch" heißt.
Mit etwas Geschick kann man erkennen, daß es im Grunde keine "unverständliche Ausdrucksweise" ist.
(in englisch: "double dutch", hat aber nichts mit einem "Dutchman" zu tun, was ja ein Holländer wäre)
Ich meine wer sich sowas reinzieht(wie es die heutige Jugend ausdrücken würde),
der muß schon die benötigte Portion Humor mitbringen.
Es gibt viele Sprüche wie: "Wer lacht, der ist gesund oder wer zuletzt lacht, der lacht länger! usw...."
Besondertst gut finde ich: "Ein Tag ohne Lachen, ist ein verlorener Tag".
In dem Sinn macht es gut.
Heute habe ich In den Nachmittagsstunden wenig zu lachen,
nach den letzten feuchten Tagen ist das Gras so gewachsen,
daß ich Mühe haben werde da durchzukommen mit dem Rasenmäher. :-(
Aber ich muß das gute Wetter ausnutzen, vielleicht fallen mir beim Grasschneiden ein paar schlecht zu
formulierende Fragen ein. Also bis später, ich hoffe, daß ich dann auch schon wieder lachen kann. :-)

Viele Grüsse

Duda
 
Hallo Cromon, hallo ComFreek und alle Leser !

Wie schon angedeutet, habe zu meinem Vorhaben noch weitere Fragen, denn ich weiss nicht, ob man aus einem
Wert auch Variablen/Konstante machen kann. Das geht vielleicht nur, wenn man die Zahl in einen String umwandelt und aus dem String irgendwie den Namen für eine Variable bildet.
Der Wert ist ja eine Zahl, welche auch als String eine Zahl bleibt, nur kann man damit nicht rechnen,
was ich auch nicht vorhabe. Sondern ich möchte aus dieser Zahl einen Namen für eine Variable machen.
Was natürlich auch nicht geht, weil es eine Zahl ist.
Ein Name darf wohl Zahlen enthalten, aber nicht an der ersten Stelle, so ist es allgemein üblich.
Mir schwebt vor, daß man dieser Zahl einen Buchstaben voranstellen könnte und damit wäre es ein möglicher
Name. Damit wäre vielleicht das Namen-Problem schonmal gelöst(natürlich erstmal nur in meinem Kopf),
also nur eine Idee von mir.
Aber Namen von Variablen mit den Namen P0 bis P35, welche als Wert dann o bis 9 und A bis Z zurückgeben,
das muß doch irgendwie möglich sein.
Ich weiß auch noch nicht was besser ist, entweder die Definition mit im Code oder eine eigene Header-Datei, worauf im Programmverlauf zugegriffen werden kann.

Hier zum Beispiel der Buchstabe "P" wird der Zahl "16" vorangestellt und es wäre "P16".
Das wäre ein gültiger Name. Das "P" wird im Programm verankert, die jeweilige Zahl bekommen wir vom Typ "int". Es ist das jeweilige Ergebnis der vorangegangenen Berechnung, aber nur 0 bis 35 ist möglich.


unsigned int sum4 = ................. (nur zur Info, sum4 enthält z. B. als Wert die Zahl 16)

Ja ich weiss, ich wende mich eventuell mit nicht ganz alltäglichen Frage an Euch.
Aber ich kann mich nicht selbst fragen, was ist machbar mit C/C++

Wenn es nicht geht, dann habe ich einen anderen Lösungsansatz, den ich eigentlich nicht wollte,
der aber nach meinem Dafürhalten machbar ist. Denn irgendwie muß es ja weitergehen und wird
es auch, da bin ich mit ganz sicher. Zur Not machen wir ganz was Anderes.

Viele Grüsse

Duda
 
Zurück