Zahl aus Datei ab Zeichen einlesen

Moin deepthroat
,
Für mich heißt elegant meist kurz, aber nicht kryptisch. Man sollte ruhig dem Compiler einiges an Optimierungen zutrauen.
Dem Compiler schon, aber oft dem Editierenden nicht :rolleyes:

Ich würde den Code von DevDevil schon als elegant bezeichnen. Er ist kurz und knapp, verwendet Standardmethoden und man sieht auf den ersten Blick was dort gemacht wird.
Sicher, aber nicht jeder kurze Code wird auch von Programmier-Anfängern verstanden ...

find_first_of ist eine Standardmethode der string Klasse in der STL. In der Regel sollte man davon ausgehen können, dass ein C++ Compiler dies unterstützt.
Jau, hast Recht, habe jetzt auch in der Hilfe was gefunden - allerdings scheint diese hier nicht korrekt/vollständig installiert zu sein ..... muss mich darum mal kümmern :(

Wenn man natürlich so einen altertümlichen Compiler nutzt, der noch nie ein (halbwegs konformer) C++ Compiler war, braucht man sich auch nicht wundern.
Auch da gebe ich Dir Recht, nur - sag' das meinem Chef .... :suspekt:
Ich bekomme hier leider weder die Zeit noch die Mittel um das Ding mal upzudaten ......... (!)

Gruß
Klaus
 
Hallo zusammen,

ich habe nun mal den Code mit den hier getätigten Anmerkungen und Hilfestellungen neu überarbeitet:

Code:
	struct data_t {
		void* value;
		enum { FLOAT, INT, U_INT} type;
	};
	
	//declare variables for GA parameters
	int popsize;
	int ngen;
	float pmut;  
	float pcross;
	int scorefreq;
	int flushfreq;
	int precision;
	int nbest;
	float pconv;
	int nconv;
	unsigned int seed;

	std::map<std::string, data_t> params;
	params["popsize"].value = &popsize;
	params["popsize"].type = data_t::INT;
	params["ngen"].value = &ngen;
	params["ngen"].type = data_t::INT;
	params["pmut"].value = &pmut;
	params["pmut"].type = data_t::FLOAT;
	params["pcross"].value = &pcross;
	params["pcross"].type = data_t::FLOAT;
	params["scorefreq"].value = &scorefreq;
	params["scorefreq"].type = data_t::INT;
	params["flushfreq"].value = &flushfreq;
	params["flushfreq"].type = data_t::INT;
	params["precision"].value = &precision;
	params["precision"].type = data_t::INT;
	params["nbest"].value = &nbest;
	params["nbest"].type = data_t::INT;
	params["pconv"].value = &pconv;
	params["pconv"].type = data_t::FLOAT;
	params["nconv"].value = &nconv;
	params["nconv"].type = data_t::INT;
	params["seed"].value = &seed;
	params["seed"].type = data_t::U_INT;


	//read variables from input file
	std::ifstream inputfile("GA_input.txt", std::ios::in);
	if(!inputfile.is_open()) return 0;
	std::string line;
	while(getline(inputfile, line)) {
		if (line.empty()) continue;

		const std::string::size_type var_begin(line.find("(") + 1);
		const std::string::size_type var_end(line.find(")", var_begin + 1));
		const std::string::size_type value_begin(line.find(":", var_end + 1) + 1);
		std::string varname = line.substr(var_begin, var_end - var_begin);
		std::stringstream ss(line.substr(value_begin));

		switch (params[varname].type) {
		case data_t::INT:
			ss >> *static_cast<int*>(params[varname].value); 
			break;
		case data_t::FLOAT:
			ss >> *static_cast<float*>(params[varname].value); 
			break;
		case data_t::U_INT:
			ss >> *static_cast<unsigned int*>(params[varname].value); 
			break;
		}

	}
	inputfile.close();

Gefällt mir auch sehr gut und finde ich auch leserlich. Vielen Dank an alle, die mir hier geholfen haben ;-) Gibt es hier evtl. noch andere Verbesserungsvorschläge? Sonst würde ich dieses Thema als erledigt kennzeichnen.

Gruß,
Stevie
 
Hi.

Du könntest der data_t Struktur noch einen Konstruktor verpassen, dann vereinfacht sich die Initialisierung der Struktur, und man könnte auch ein Makro verwenden was Tippfehler minimiert (obwohl man Makros vorsichtig einsetzen sollte):
C++:
struct data_t {
  void* value;
  enum type_t {  FLOAT, INT, U_INT} type;

  data_t() : value(0), type(static_cast<type_t>(-1)) {}
  data_t(void* pv, type_t t) : value(pv), type(t) {}
};
...

#define MAP_VAR(var, type)  (params[#var] = data_t(&var, type))

MAP_VAR(popsize, data_t::INT);
MAP_VAR(ngen, data_t::INT);
MAP_VAR(pmut, data_t::FLOAT);
...
#undef MAP_VAR
Gruß
 
Hallo deepthroat,

jetzt habe ich aber schon meine Schwierigkeiten das zu verstehen.

Was machen diese beiden Zeilen?
Code:
data_t() : value(0), type(static_cast<type_t>(-1)) {}
data_t(void* pv, type_t t) : value(pv), type(t) {}

Danke!

Gruß,
Stevie
 
Hallo deepthroat,

jetzt habe ich aber schon meine Schwierigkeiten das zu verstehen.

Was machen diese beiden Zeilen?
Code:
data_t() : value(0), type(static_cast<type_t>(-1)) {}
data_t(void* pv, type_t t) : value(pv), type(t) {}
Wie man leicht sieht ;) sind das zwei Konstruktoren. Der erste ist ein Standardkonstruktor und wird verwendet wenn man eine Variable vom Typ data_t anlegt ohne sie explizit zu initialisieren. Mit dem zweiten Konstruktor kann man eine Variable initialisieren. Also mit Hilfe des zweiten Konstruktors ist es möglich folgendes zu schreiben:
C++:
data_t  meine_variable(&other, data_t::INT);

// oder

data_t meine_variable = data_t(&other, data_t::INT);
Das ist ohne den Konstruktor nicht möglich.

Alle selbstdefinierten Typen die man in einen Container der STL (wie. eine std::map oder std::vector) hineinpacken will, benötigen einen Standardkonstruktor. Deshalb muss man den auch definieren.

Gruß
 
Zurück