[QUIZ#1] engelmarkus (C++)

engelmarkus

Erfahrenes Mitglied
Hier habe ich eine Lösung in C++ geschrieben.
Wie in der VB.Net-Lösung sind auch hier zwei Dateien im Projekt, in einer die einfache Lösung, in der anderen die Lösung mit Erweiterung.
 

Anhänge

  • quiz1CPP.zip
    10 KB · Aufrufe: 24
Hallo,

könntest du in Zukunft den Quelltext direkt in den Beitrag schreiben? Danke.

Meine Anmerkungen:
  • Wenn du C++ verwendest, warum verzichtest du dann auf den Einsatz von std::string?
  • Zum Durchlaufen der Vektoren wäre es vielleicht besser, einen Iterator zu verwenden.
  • Zu jedem new gehört ein delete! Solange das Programm nach der Erledigung seiner Aufgabe sofort terminiert, ist das kein allzu großes Problem, allerdings sollte man sich trotzdem eine korrekte Speicherverwaltung angewöhnen.
  • Gibt es einen speziellen Grund, warum Daten und Ergebnisliste Zeiger sind?

Grüße,
Matthias
 
Danke erstmal für die Verbesserungsvorschläge. Ich muss ganz ehrlich gestehen, dass ich den Code nicht in einer "geistigen Umnachtung" geschrieben hab, sondern einfach C++ nicht sonderlich gut kann :) .
Deswegen kann ich dir deine Fragen auch nicht beantworten, ich habs jetzt einfach mal entsprechend umgebaut:

Code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

// Hier werden die Zeilen aus der Datei abgelegt
std::vector<std::string> Daten;

int main()
{
	std::cout << "Bitte Suchbegriff eingeben: ";
	
	std::string suchbegriff;
	std::getline(std::cin, suchbegriff);

	// Jetzt müssen wir die Daten noch in den vector laden...
	std::ifstream daten("c:\\presidents.txt", std::ios::in);

	while (daten.good())
	{
		std::string zeile;
		std::getline(daten, zeile);
		
		Daten.push_back(zeile);
	}

	daten.close();


	// Jetzt können wir jede Zeile durchsuchen, ob sie draufpasst
	// ---------------------------------------------------------------------

	// erstmal brauchen wir einen Zeiger auf den ersten Buchstaben des Suchbegriffes
	char* suchZeiger;

	// dann noch ein Zeiger auf den nächsten Buchstaben aus der zu durchsuchenden Zeile
	char* nächsterBuchstabe;

	std::cout << std::endl << std::endl << "Suchergebnisse:" << std::endl;

	//  Jetzt laufen wir alle eingelesenen Zeilen durch
	for (std::vector<std::string>::iterator i = Daten.begin(); i != Daten.end(); i++)
	{
		suchZeiger = &suchbegriff[0];
		nächsterBuchstabe = &(*i)[0];

		std::ostringstream ausgabe;
		bool offen = false;   // Speichert, ob gerade ein <Bereich> offen ist, oder alle geöffneten spitzen Klammern auch schon eine geschlossene haben

		// Für jedes Zeichen aus der zu durchsuchenden Zeile; eines der zwei breaks unten muss drankommen
		while(true)
		{
			// Wenn wir beim Suchbegriff ganz hinten angekommen sind, dann sind alle Zeichen in der richtigen Reihenfolge enthalten
			if (*suchZeiger == '\0')
			{
				if (offen)
					ausgabe << ">";   // Ggf. Noch die Klammer schließen

				while (!*nächsterBuchstabe == '\0')   // und restliche Zeichen schreiben
				{
					ausgabe << *nächsterBuchstabe;
					nächsterBuchstabe++;
				}

				std::cout << ausgabe.str().c_str() << std::endl;
				break;
			}

			// Ist dagegen die Zeile zu Ende, gehen wir zur nächsten und fangen von vorne an
			if (*nächsterBuchstabe == '\0')
				break;

			// Wenn eine Übereinstimmung gefunden wurde, setzen wir den suchZeiger auf das nächste Zeichen
			if (*suchZeiger == *nächsterBuchstabe)
			{
				suchZeiger++;
				
				if (!offen)   // Bei Übereinstimmungen muss eine Klammer geöffnet werden, falls noch nicht geschehen
				{
					ausgabe << "<";
					offen = true;
				}

				ausgabe << *nächsterBuchstabe;
			}
			else
			{
				if (offen)   // Wenn grade keine Übereinstimmung da ist, dann die Klammer schließen, falls noch nicht geschehen
				{
					ausgabe << ">";
					offen = false;
				}

				ausgabe << *nächsterBuchstabe;
			}

			// Der Zeiger in der aktuell zu durchsuchenden Zeile wird auf alle Fälle weitergesetzt
			nächsterBuchstabe++;
		}
	}

	std::cin.seekg(0,std::ios::end);
	std::cin.clear();
	std::cin.ignore();
	return 0;
}

Die Endlosschleife ist so hoffentlich erlaubt? :)
Bei der Zeile hier frage ich mich, ob man die nicht einfacher schreiben kann?
Code:
nächsterBuchstabe = &(*i)[0];

Hoffentlich hab ichs nicht verschlimmbessert...
 
Hallo Markus,

so gefällt es mir doch gleich viel besser :) Trotzdem noch ein paar Kleinigkeiten:

Code:
// Hier werden die Zeilen aus der Datei abgelegt
std::vector<std::string> Daten;
[...]
	// Jetzt müssen wir die Daten noch in den vector laden...
	std::ifstream daten("c:\\presidents.txt", std::ios::in);
Zwei Variablennamen, die sich nur anhand der Groß-/Kleinschreibung unterscheiden, können sehr schnell für Verwirrung sorgen, daher am besten vermeiden!

Code:
	// erstmal brauchen wir einen Zeiger auf den ersten Buchstaben des Suchbegriffes
	char* suchZeiger;

	// dann noch ein Zeiger auf den nächsten Buchstaben aus der zu durchsuchenden Zeile
	char* nächsterBuchstabe;
Auch hier würde ich eher auf Iteratoren zurückgreifen (gibt es auch für Strings). Erstens ist nicht sichergestellt, dass char überhaupt der Basistyp eines std::string ist. Und zweitens kann es zu Problemen führen, wenn du mit der internen Repräsentation eines Datentyps arbeitest, ohne gesicherte Annahmen über selbige machen zu können (siehe weiter unten).

Code:
			// Wenn wir beim Suchbegriff ganz hinten angekommen sind, dann sind alle Zeichen in der richtigen Reihenfolge enthalten
			if (*suchZeiger == '\0')
Hier kann es womöglich krachen, da nicht garantiert ist, dass std::strings intern als nullterminierte C-Strings gespeichert werden. Die meisten STLs handhaben es zwar so, aber es kann eben auch mal anders kommen.

Code:
		std::cout << ausgabe.str().c_str() << std::endl;
Hier reicht auch ausgabe.str().

Bei der Zeile hier frage ich mich, ob man die nicht einfacher schreiben kann?
Code:
nächsterBuchstabe = &(*i)[0];
Code:
nächsterBuchstabe = i->c_str();
Allerdings müsste dann nächsterBuchstabe als const char* deklariert werden. Da die Verwendung von char* in Verbindung mit std::string aber sowieso problematisch ist (s.o.), erübrigt sich die Frage ;)

Grüße,
Matthias
 
Also noch eine Version :) :

Code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

// Hier werden die Zeilen aus der Datei abgelegt
std::vector<std::string> Daten;

int main()
{
	std::cout << "Bitte Suchbegriff eingeben: ";
	
	std::string suchbegriff;
	std::getline(std::cin, suchbegriff);

	// Jetzt müssen wir die Daten noch in den vector laden...
	std::ifstream datei("c:\\presidents.txt", std::ios::in);

	while (datei.good())
	{
		std::string zeile;
		std::getline(datei, zeile);
		
		Daten.push_back(zeile);
	}

	datei.close();


	// Jetzt können wir jede Zeile durchsuchen, ob sie draufpasst
	// ---------------------------------------------------------------------

	// erstmal brauchen wir einen Zeiger auf den ersten Buchstaben des Suchbegriffes
	std::string::iterator suchZeiger;

	// dann noch ein Zeiger auf den nächsten Buchstaben aus der zu durchsuchenden Zeile
	std::string::iterator nächsterBuchstabe;

	std::cout << std::endl << std::endl << "Suchergebnisse:" << std::endl;

	//  Jetzt laufen wir alle eingelesenen Zeilen durch
	for (std::vector<std::string>::iterator i = Daten.begin(); i != Daten.end(); i++)
	{
		suchZeiger = suchbegriff.begin();
		nächsterBuchstabe = (*i).begin();

		std::ostringstream ausgabe;
		bool offen = false;   // Speichert, ob gerade ein <Bereich> offen ist, oder alle geöffneten spitzen Klammern auch schon eine geschlossene haben

		// Für jedes Zeichen aus der zu durchsuchenden Zeile; eines der zwei breaks unten muss drankommen
		while(true)
		{
			// Wenn wir beim Suchbegriff ganz hinten angekommen sind, dann sind alle Zeichen in der richtigen Reihenfolge enthalten
			if (suchZeiger == suchbegriff.end())
			{
				if (offen)
					ausgabe << ">";   // Ggf. Noch die Klammer schließen

				while (nächsterBuchstabe != (*i).end())   // und restliche Zeichen schreiben
				{
					ausgabe << *nächsterBuchstabe;
					nächsterBuchstabe++;
				}

				std::cout << ausgabe.str() << std::endl;
				break;
			}

			// Ist dagegen die Zeile zu Ende, gehen wir zur nächsten und fangen von vorne an
			if (nächsterBuchstabe == (*i).end())
				break;

			// Wenn eine Übereinstimmung gefunden wurde, setzen wir den suchZeiger auf das nächste Zeichen
			if (*suchZeiger == *nächsterBuchstabe)
			{
				suchZeiger++;
				
				if (!offen)   // Bei Übereinstimmungen muss eine Klammer geöffnet werden, falls noch nicht geschehen
				{
					ausgabe << "<";
					offen = true;
				}

				ausgabe << *nächsterBuchstabe;
			}
			else
			{
				if (offen)   // Wenn grade keine Übereinstimmung da ist, dann die Klammer schließen, falls noch nicht geschehen
				{
					ausgabe << ">";
					offen = false;
				}

				ausgabe << *nächsterBuchstabe;
			}

			// Der Zeiger in der aktuell zu durchsuchenden Zeile wird auf alle Fälle weitergesetzt
			nächsterBuchstabe++;
		}
	}

	std::cin.seekg(0,std::ios::end);
	std::cin.clear();
	std::cin.ignore();
	return 0;
}
 
Zurück