C++ String und Integer "verknüpfen"

iJerkface

Lieutenant
Registriert
März 2012
Beiträge
665
Hallo ,

seit langer Zeit wollte ich mich mal wieder ein bischen an C++ ausprobieren und mir ein kleines Programm zur Errechnung des Notendurchschnitts schreiben.

Problem hierbei :

Fächer (und somit die Fächernamen) , als auch die Anzahl der Fächer variieren.

Es stellt sich folgendes Problem:

Zuerst einmal möchte ich alle vorhandenen Fächer abrufen , d.h. der Nutzer gibt seine bis zu 15 Fächer und ihre Namen in stringform ein.



Code:
string Fach1;

cin >> Fach1

Später sollen dann die Noten / geschätzten Noten der einzelnen Fächer abgefragt werden.

Code:
string Fach1;
int Note1;

cout << " Bitte gib die Note von << Fach1 << "ein" << endl;
cin >> Note1;

Wenn ich später jedoch die einzelnen Noten der Fächer abrufen will , dann weiß das Programm ja nicht , dass in diesem Fall der Fachname string1 zu der Note Note1 gehört.

Wie also "verknüpfe " ich diese beiden Werte , sodass ich dann ausgegeben bekomme
Code:
cout << " Welche Note möchtest du wissen?" << endl;
cin >> Fach1 ;
cout << " Du hast in " << Fach 1 <<  "eine" << Note1 << endl;

Ich weiss , für die meisten von euch wird das Pipifax sein , aber ich hab durch Google Nichts nützliches gefunden und bin somit hier auf die Hilfe angewiesen :D

MfG iJerkface
 
Erzeug dir ein Objekt. Objekt Fach enthält dann verschiedene Parameter wie Note, Stunde, Dauer, Lehrer, Thema, etc...
Dann kannst du über Funktionen wie z.b Mathe->getNote(); die Note ausgeben lassen.
 
String Stream aus der STL:

Code:
#include <sstream>

...

stringstream ss;
ss << "Hallo test" << 42;
cout << ss.str();

Statt der 42 und "Hallo test" kannst du natürlich auch Variablen nehmen.

Edit:

Sorry, ich glaube ich habe erst jetzt verstanden, was du möchtest. Am besten du machst eine eigene Klasse (wie schon vorgeschlagen). Alternativ kannst du auch die Klasse "Pair" und "List" aus der STL verwenden. In einem Pair kannst du einen Key und einen Value abspeichern (also Fach und die dazugehörige Note). Diese Pairs kannst du dann in einer Liste speichern.
 
Zuletzt bearbeitet:
So wie ich das verstanden habe, willst du z.B von 1 auf "Eins" kommen.

--> Entweder mit std::Map<int,std::string>

oder einfach ein String array definieren. Die String stehen für die Noten.

std::string Noten []= {"null","eins","zwei",..};

cout<<Noten[1];
 
Zuletzt bearbeitet:
Objektorientiert würde das so ausshen dass du eine Klasse Zeugnis Machst diese entählt einen Vektor oder eine Map mit den Objekten Fach und Schüler.
In den Objekten kannst du dann die "Noten" abspeichern und daraus dann generieren was immer du willst - du kannst die fächer kategorisieren und dann schauen welchen notenschnitt der Schüler A in den Fächern "Naturwissenschaft" hat.

Das ist ein recht einfaches programm und gut zum einlernen von c++ und vor allem der Objektorientiertheit.
 
Eigentlich möchte ich nur , dass bei Eingabe des benötigten Faches die dazugehörige Note ausgegeben wird

Ich weiss aber nicht wie ich dem Compiler klarmache , dass die Note1 zu Fach1 gehört.
Ergänzung ()

Ich werde dann mal versuchen mich in die maps einzuarbeiten , hab davon bis dato nichts gehört.

Danke für die Hilfe!
 
Eine elegante Variante wäre wenn du schon bei der Eingabe Fächername und Note zugleich abfragst, anstatt erstmal alle Fächernamen und dann die Noten einzutragen. Setzt vorraus, das beide Abfragen natürlich gemeinsam erfolgen können. Dann kannst du die Werte in einem Array abspeichern, deren Elemente vom Typ einer Struktur oder einer Klasse sind. Alternativ kannst du auch ohne Struktur oder Klasse auskommen, wenn es "schneller" gehen soll in dem du 2 Arrays (eines aus string und eines aus int) gleicher Größe verwendest und über den selben Index referenzierst. so verknüpfst du die beiden Werte Fach und Note miteinander. Gibt sicher noch mehr Möglichkeiten. Aber das sind die simpelsten die mir einfallen.


Später kannst du dann bei der Abfrage nach einem Fach danach suchen (bei 15 Werten reicht eine lineare suche vollkommen aus) und kannst dann die zugehörige Note ausgeben.

Wenn die Eingabe von Fachname und Note nicht gleichzeitig erfolgt , müsstest du nur bei der Note ebenfalls einmal nach dem Fachnamen suchen und den offenen Wert für die Note abspeichern.

Beispiel für die Eingabe (Die kommentare entsprechend ausfüllen)

Code:
#define MAX_NUM_FAECHER    15

string faecher[15];
int noten[15];

for(int i = 0; i < MAX_NUM_FAECHER; i++)
{
      //Eingabe von Fachname z.B.  cin >> faecher[i];
      //Eingabe von zugehöriger Note z.B.  cin >> noten[i];
}

für die Abfrage entsprechend

Code:
string fach;

//abfrage nach gewünschtem fach z.B. cin >> fach

int found_index = -1;
for(int i = 0; i < MAX_NUM_FAECHER && found_index == -1; i++)
{
      if(faecher[i] == fach) found_index = i;
}

if(found_index >= 0)
{
     //Ausgabe der informationen mit faecher[found_index] und noten[found_index]
}
else
{
     //Ausgabe das ein entsprechendes Fach mit dem Fachnamen nicht gefunden wurde
}
 
Zuletzt bearbeitet:
DonnyDepp schrieb:

Idiomatisches C++ ist das jedenfalls nicht. printf() ist eine alte C-Funktion, die du freilich auch in C++ benutzen darfst, ohne davon Herpes zu bekommen. Du schmeißt damit allerdings jegliche Typsicherheit aus dem Fenster, und dafür solltest du dann eigentlich einen verdammt guten Grund haben (z.B. iostream-Implementierung deines Compilers ist eine Performance-Flaschenhals .... solltest du dann aber vorher per Profiler bestätigt haben).
 
antred schrieb:
Idiomatisches C++ ist das jedenfalls nicht. printf() ist eine alte C-Funktion, die du freilich auch in C++ benutzen darfst, ohne davon Herpes zu bekommen. Du schmeißt damit allerdings jegliche Typsicherheit aus dem Fenster, und dafür solltest du dann eigentlich einen verdammt guten Grund haben (z.B. iostream-Implementierung deines Compilers ist eine Performance-Flaschenhals .... solltest du dann aber vorher per Profiler bestätigt haben).

Und selbst dann lebt man einfach mit dem Flaschenhals oder wechselt den Compiler, anstatt sich in die Abgruende von printf zu begeben ;)
 
Ich möchte nochmal ein Plädoyer für iostreams hinterlassen, da die Begründung für iostreams mir bisher zu dünn war (das Beispiel ließe sich leicht auf die ursprüngliche Frage anpassen, aber das Beispiel ist für Anfänger ungeeignet):
Code:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>

class Point
{
public:
	Point(int px, int py) : x(px), y(py) {}
	int x,y;
};

//Funktion zum Ausgeben von Point
template<typename charT, typename traits>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& stream, const Point& pt)
{
	stream << "(" << pt.x << ", " << pt.y << ")";
	return stream;
}

//Funktion zum Einlesen von Point
template<typename charT, typename traits>
inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& stream, Point& pt)
{
	std::cout << "x: ";
	stream >> pt.x;
	std::cout << "y: ";
	stream >> pt.y;
	std::cout << std::endl;
	return stream;
}

int main(int argc, char** argv)
{
	Point one(1,2);
	Point two(5,9);
	
	//jetzt lassen sich Point Objekte direkt per cout ausgeben. Besonders gut in Teams, 
	//da man nicht auf irgendwelche Funktionsnamen wie print_point(Point* pt) oder so einigen muss, die das dann per printf ausgeben. std::cout << beliebigesObjekt kann jeder. Konvention per ISO Standard...
	std::cout << one << std::endl;
	std::cout << two << std::endl;
	
	//man kann es aber auch anderen Streams uebergeben, bspw. einem Stringstream. Koennte aber z.B. auch eine Netzwerkschnittstelle, Textdatei,.. sein.
	//Wichtige Erkenntnis: Die eine Ausgabefunktion funktioniert eben fuer verschiedene Streams, ohne Anpassung
	std::stringstream stream;
	stream << two << ", " << one;
	
	//Den String haette man jetzt z.B. auch fuer eine grafische Oberflaeche benutzen. Wenn man direkt printf verwendet, haette man jetzt schon
	//einiges doppelt und dreifach neuschreiben muessen
	std::string test_str = stream.str();
	//nochmal zum Beweis ausgeben
	std::cout << "der teststring: " << test_str << std::endl;
	
	std::vector<Point> storage;
	//zwei Punkte von der Konsole einlesen
	for(int i = 0; i < 2; ++i)
	{
		Point test_pt(0,0);
		//Point weiss selber am besten wie es sich von der Konsole einlesen laesst, deswegen der Funktion oben uberlassen
		std::cin >> test_pt;
		//Punkt dem Vektor hinzufuegen
		storage.push_back(test_pt);
	}

	//eingegebene Punkte ausgeben
	std::copy(storage.begin(), storage.end(), std::ostream_iterator<Point>(std::cout, "\n"));
	
	std::cout << "Punkte mit Koordinate X ausgeben: ";
	int x_input;
	std::cin >> x_input;
	//Achtung, die nachfolgende Zeile benoetigt C++11! Sie gibt jedenfalls alle Punkte bei denen die x Koordinate mit der eingegebenen uebereinstimmt
	std::copy_if(storage.begin(), storage.end(), std::ostream_iterator<Point>(std::cout, "\n"), [=](const Point& pt){return pt.x == x_input;});

	return 0;
}
Insbesondere die copy_if Zeile zeigt eindeutig, warum man sich mit der STL allgemein gut auskennen sollte. Alle Punkte eines Bereiches in einem beliebigen Datencontainer raussuchen, deren Bedingung prüfen und auf der Konsole ausgeben in nur einer Zeile. Meiner Meinung nach: Awesome!
 
Zuletzt bearbeitet:
Zurück
Oben