Problem mit Zugriff auf struct mittels Pointer

Schnelle objektorientierte, kompilierende Programmiersprache.
raysman
Beiträge: 2
Registriert: So Jan 07, 2018 10:37 pm

Problem mit Zugriff auf struct mittels Pointer

Beitrag von raysman » So Jan 07, 2018 10:42 pm

Ich würde gerne folgende Lösung auf einem anderen Weg programmieren.
Leider verstehe ich nicht, wie ich auf das struct zugreifen kann, damit Buchstabe a auch den Code ausgibt.

else { cout << morse_data[*(ptr + i)].morse_code << "#"; }

funktioniert leider nicht. Ich habe jedoch keine Idee warum. Wenn ich das i aus der Schleife einsetze werden alle Codes strikt der Reihenfolge nach ausgegeben.

Großbuchstaben habe ich bisher bewusst noch nicht berücksichtigt.

Lösung:

Code: Alles auswählen

#include <iostream>
#include <string>
using namespace std;

struct T_Morse_Data
{
	char letter;
	std::string morse_code;
};
const T_Morse_Data morse_data[] = {
{ 'a', ".-" },
{ 'b', "-..." },
{ 'c', "-.-." },
{ 'd', "-.." },
{ 'e', "." },
{ 'f', "..-." },
{ 'g', "--." },
{ 'h', "...." },
{ 'i', ".." },
{ 'j', ".---" },
{ 'k', "-.-" },
{ 'l', ".-.." },
{ 'm', "--" },
{ 'n', "-." },
{ 'o', "---" },
{ 'p', ".--." },
{ 'q', "--.-" },
{ 'r', ".-." },
{ 's', "..." },
{ 't', "-" },
{ 'u', "..-" },
{ 'v', "...-" },
{ 'w', ".--" },
{ 'x', "-..-" },
{ 'y', "-.--" },
{ 'z', "--.." },
{ '0', "-----" },
{ '1', ".----" },
{ '2', "..---" },
{ '3', "...--" },
{ '4', "....-" },
{ '5', "....." },
{ '6', "-...." },
{ '7', "--..." },
{ '8', "---.." },
{ '9', "----." },
// Leerzeichen zur Worttrennung werden im Morsecode
// durch einen Slash '/' umgeben von Leerzeichen
// dargestellt ...
// (Alternative: Trennung durch 3 Leerzeichen)
// Hier bei uns, um die Testläufe eindeutiger zu
// machen: Trennung mittels drei Slashes
{ ' ', "///" },
{ '.', ".-.-.-" },
{ ',', "--..--" },
{ ':', "---..." },
{ '?', "..--.." },
{ '-', "-....-" },
{ '/', "-..-." },
{ '@', ".--.-." },
{ '=', "-...-" }
};
const int morse_data_len = 47;

int main() {
	string eingabe = "";
	string ausgabe = "";
	string code = "";
	cout << "Bitte Text eingeben (ggfs. mit Leerzeichen): ? ";
	getline(cin, eingabe);

	for (int i = 0; i < eingabe.size(); i++) {
		if (eingabe.at(i) >= 'A' && eingabe.at(i) <= 'Z') {
			eingabe.at(i) += 32;
		}
		for (int j = 0; j < morse_data_len; j++) {
			if (eingabe.at(i) == morse_data[j].letter) {
				code = morse_data[j].morse_code;
				break;
			}
			else {
				continue;
			}
		}
		ausgabe += code;
		cout << ausgabe << "#";
		ausgabe = "";
	}
	cout << endl;
	system("PAUSE");
	return 0;
}
Meine Variante

Code: Alles auswählen

int main() {
	char *ptr = new char[morse_data_len];
	cin.getline(ptr, morse_data_len);

	char p = 0;
	for (int i = 0; i < morse_data_len; i++)
	{
		if (*(ptr + i) == '\0') { break; }
		else { cout << morse_data[*(ptr + i)].morse_code << "#"; }
	}

	system("PAUSE");
	return 0;
}

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von Xin » So Jan 07, 2018 11:06 pm

Moin und willkommen :-)
raysman hat geschrieben:Ich würde gerne folgende Lösung auf einem anderen Weg programmieren.
Leider verstehe ich nicht, wie ich auf das struct zugreifen kann, damit Buchstabe a auch den Code ausgibt.

else { cout << morse_data[*(ptr + i)].morse_code << "#"; }

funktioniert leider nicht. Ich habe jedoch keine Idee warum. Wenn ich das i aus der Schleife einsetze werden alle Codes strikt der Reihenfolge nach ausgegeben.
In die eckigen Klammern kommt bei einem Array ein Index. Deine Lösung packt aber den Buchstaben als Schlüssel rein.
In der Lösung liegt das 'a' auf Index 0. 'a' ist aber auch eine gültige Zahl, nämlich eben der ASCII-Code für 'a'. Der ist 97.
Du musst also erst rausfinden, auf welchem Index das Morsezeichen für den ASCII-Code 97 - dem 'a' liegt.

Alternativ könntest Du eine Hashmap nehmen (std::map), wo du einen Schlüssel (das ASCII-Zeichen) auf den String (das Morse-Zeichen) abbildest.
raysman hat geschrieben:Großbuchstaben habe ich bisher bewusst noch nicht berücksichtigt.
Morst man bei Großbuchstaben lauter? ;)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

raysman
Beiträge: 2
Registriert: So Jan 07, 2018 10:37 pm

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von raysman » So Jan 07, 2018 11:26 pm

Klingt so, als wäre ein Tausch von 'a' zu .- nur über den Index möglich? Wenn ich ich jetzt -97 ergänze funktioniert es :)
Jetzt hab ich gesehen, dass in der Lösung einfach das Array mit einer Schleife durchlaufen wird ..

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von Xin » Mo Jan 08, 2018 12:32 am

raysman hat geschrieben:Klingt so, als wäre ein Tausch von 'a' zu .- nur über den Index möglich? Wenn ich ich jetzt -97 ergänze funktioniert es :)
Für Buchstaben... nicht für Satzzeichen, da musst Du weitere Bedingungen einbauen. Allerdings kannst Du so auch einfach Großbuchstaben einbauen, wenn Du von 'A' 65 abziehst. Das geht auch mit (*(ptr+i))-'A' - unter der Vorraussetzung, dass ptr+i auf einen Großbuchstaben zeigt...
raysman hat geschrieben:Jetzt hab ich gesehen, dass in der Lösung einfach das Array mit einer Schleife durchlaufen wird ..
Wenn Du Dich nur mit dem berechneten Index durcharbeitest, brauchst Du auch den Schlüssel ('letter') nicht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von mfro » Mo Jan 08, 2018 8:26 am

was soll die Schreibweise

Code: Alles auswählen

*(ptr + i)
???

Gewöhn' dir das nicht an. Wenn man Arrays meint, sollte man n.m.M. auch Arrays hinschreiben, dafür wurden sie erfunden:

Code: Alles auswählen

ptr[i]
Wenn Du sicherstellen kannst, dass dein Übersetzungsarray immer so aufgebaut ist (und bleibt), dass es bei 'a' beginnt und (ohne Lücke) bis 'z' geht, kannst Du 1. das 'letter' member in der struct weglassen (weil das ja implizit schon dem Array-Index - 'a' entspricht) und 2. schreiben:

Code: Alles auswählen

cout << morse_data[i - 'a'].morse_code << ...
Wenn das Übersetzungsarray Lücken aufweisen (oder unsortiert sein) darf, brauchst Du Code, der dir zu einem gegebenen Zeichen den richtigen Array-Index raussucht. Also (im einfachsten Fall) so was:

Code: Alles auswählen

for (int index = 0; index < sizeof(morse_data) / sizeof(morse_data[0]); index++)
{
     if (morse_data[i].letter == eingabe[i])
     {
         morse_code = morse_data[i].morse_code;
         break;
     }
}
(hier musst Du noch den Fall abfangen, dass das Zeichen nicht gefunden wurde)
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von Xin » Di Jan 09, 2018 1:02 am

Ich habe mir mal spaßeshalber die Musterlösung angeguckt und möchte eine Alternative zeigen. Die Musterlösung ist eher altmodisch und entspricht nicht modernem C++. Die folgende Lösung ist erstens leichter zu lesen, leichter zu warten und sollte deutlich schneller in der Ausführung sein.

Code: Alles auswählen

#include <iostream>
#include <string>
#include <map>

using namespace std;

std::map< char, std::string > dict = {
{ 'a', ".-" },
{ 'b', "-..." },
{ 'c', "-.-." },
{ 'd', "-.." },
{ 'e', "." },
{ 'f', "..-." },
{ 'g', "--." },
{ 'h', "...." },
{ 'i', ".." },
{ 'j', ".---" },
{ 'k', "-.-" },
{ 'l', ".-.." },
{ 'm', "--" },
{ 'n', "-." },
{ 'o', "---" },
{ 'p', ".--." },
{ 'q', "--.-" },
{ 'r', ".-." },
{ 's', "..." },
{ 't', "-" },
{ 'u', "..-" },
{ 'v', "...-" },
{ 'w', ".--" },
{ 'x', "-..-" },
{ 'y', "-.--" },
{ 'z', "--.." },
{ '0', "-----" },
{ '1', ".----" },
{ '2', "..---" },
{ '3', "...--" },
{ '4', "....-" },
{ '5', "....." },
{ '6', "-...." },
{ '7', "--..." },
{ '8', "---.." },
{ '9', "----." },
// Leerzeichen zur Worttrennung werden im Morsecode
// durch einen Slash '/' umgeben von Leerzeichen
// dargestellt ...
// (Alternative: Trennung durch 3 Leerzeichen)
// Hier bei uns, um die Testläufe eindeutiger zu
// machen: Trennung mittels drei Slashes
{ ' ', "///" },
{ '.', ".-.-.-" },
{ ',', "--..--" },
{ ':', "---..." },
{ '?', "..--.." },
{ '-', "-....-" },
{ '/', "-..-." },
{ '@', ".--.-." },
{ '=', "-...-" }
};

int main() {
   string eingabe = "";
   cout << "Bitte Text eingeben (ggfs. mit Leerzeichen): ? ";
   getline(cin, eingabe);

   for( char c : eingabe )
   {
     auto it = dict.find( tolower( c ) );
     if( it != dict.end() )
       cout << it->second + "#";
   }
   cout << endl;

   return 0;
}
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von mfro » Di Jan 09, 2018 9:07 am

Das dürfte hier keine Rolle spielen, aber wenn man keinen sorted Iterator braucht, ist std::unordered_map fast immer die bessere Wahl gegenüber std::map (schneller).
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von Xin » Di Jan 09, 2018 10:19 am

mfro hat geschrieben:Das dürfte hier keine Rolle spielen, aber wenn man keinen sorted Iterator braucht, ist std::unordered_map fast immer die bessere Wahl gegenüber std::map (schneller).
Klugscheißer... ;)

Ich fand's so schön, das Programm auf wenige Zeilen zusammen zu streichen und dann sowas als Feedback. :D

Ansonsten müsste man das wirklich mal ausprobieren, denn eine sortiere Map könnte theoretisch ja über eine binäre Suche schneller fündig werden als eine unsortierte Map. Wäre also eine Frage der Implementierung!?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von mfro » Di Jan 09, 2018 1:10 pm

Xin hat geschrieben: Klugscheißer... ;)
aber immer wieder gern ;)
Xin hat geschrieben: Ich fand's so schön, das Programm auf wenige Zeilen zusammen zu streichen und dann sowas als Feedback. :D
... wenn wir schon beim Klugscheissen sind ( ;) ), Stichwort Zeilen sparen. Da geht noch was, die maps haben einen hübschen Array-Operator:

Code: Alles auswählen

for (char c : eingabe)
    cout << dict[tolower(c)] + "x";
Das hat allerdings den möglicherweise unerwünschten Seiteneffekt, dass für nicht erkannte Zeichen neue "leere" Map-Einträge erzeugt werden (was dann allerdings auch bedeutet, dass die gehasht werden und das Programm mit mehr solcher Einträge immer schneller werden müsste).
Xin hat geschrieben: Ansonsten müsste man das wirklich mal ausprobieren, denn eine sortiere Map könnte theoretisch ja über eine binäre Suche schneller fündig werden als eine unsortierte Map. Wäre also eine Frage der Implementierung!?
Das will ich nicht ausschließen, glaube aber nicht daran. Schließlich reden wir ja von Hash-Tabellen. std::map (und std::unordered_map) verwendet std::hash<char> und das bildet (solange Du nicht bei der Template-Instanzierung was eigenes übergibst) das eben *nicht* 1:1 aufeinander ab. Das wird also wahrscheinlich nix mit der binären Suche.
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit Zugriff auf struct mittels Pointer

Beitrag von Xin » Di Jan 09, 2018 3:00 pm

mfro hat geschrieben:
Xin hat geschrieben: Klugscheißer... ;)
aber immer wieder gern ;)
Ich bitte doch darum :)
mfro hat geschrieben:
Xin hat geschrieben: Ich fand's so schön, das Programm auf wenige Zeilen zusammen zu streichen und dann sowas als Feedback. :D
... wenn wir schon beim Klugscheissen sind ( ;) ), Stichwort Zeilen sparen. Da geht noch was, die maps haben einen hübschen Array-Operator:

Code: Alles auswählen

for (char c : eingabe)
    cout << dict[tolower(c)] + "x";
Das hat allerdings den möglicherweise unerwünschten Seiteneffekt, dass für nicht erkannte Zeichen neue "leere" Map-Einträge erzeugt werden (was dann allerdings auch bedeutet, dass die gehasht werden und das Programm mit mehr solcher Einträge immer schneller werden müsste).
Dass es schneller wird, halte ich für eine interessante Theorie, ich würde jetzt eher vermuten, je voller die map, desto langsamer.
Bei eine Map, die von char ausgeht, könnte eine Spezialisierung natürlich einen referenzierten Zugriff über ein Array ausmachen, was natürlich nicht zu toppen wäre. Aber das würde auch mit leeren Elementen gehen und dann wäre es schneller, wenn dafür keine leeren Strings angelegt werden müssen. ^^
mfro hat geschrieben:
Xin hat geschrieben: Ansonsten müsste man das wirklich mal ausprobieren, denn eine sortiere Map könnte theoretisch ja über eine binäre Suche schneller fündig werden als eine unsortierte Map. Wäre also eine Frage der Implementierung!?
Das will ich nicht ausschließen, glaube aber nicht daran. Schließlich reden wir ja von Hash-Tabellen. std::map (und std::unordered_map) verwendet std::hash<char> und das bildet (solange Du nicht bei der Template-Instanzierung was eigenes übergibst) das eben *nicht* 1:1 aufeinander ab. Das wird also wahrscheinlich nix mit der binären Suche.
Einen Hash kann man doch binär suchen?
Ich habe mir noch keine Implementierung von map angeguckt. Die Idee ist bei mir da recht einfach: Es ist Standard und hat damit per Definition halbwegs passabel zu sein. Bei einer Hashmap, wo ich wissen will, was da intern funktioniert, nehme ich eine eigene Implementation.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten