Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
#include <iostream> #include <fstream> class ini // Une class prend généralement une majuscule { public: ini(std::ifstream&) // On colle le "&" au type en C++ (contrairement au C). { } template <typename T> void Set(std::string const&, T&) // Methode sans majuscule, réservé aux classes { std::cout << "managed some natural" << std::endl; } void Set(std::string const&, bool&) { std::cout << "managed some boolean" << std::endl; } void Set(std::string const&, std::string&) { std::cout << "managed some string" << std::endl; } }; class InputParameter { public: int& getIntervalTime() { return m_tStart; } // Lève un warning si m_tStart est un double private: int m_tStart; }; std::ifstream& operator>>(std::ifstream& in, InputParameter& param) { ini init(in); init.Set("TSTART", param.getIntervalTime()); // Design dangereux, on utilise un "setIntervalTime" plutôt que d'affecter le résultat d'un get... return in; } int main() { try { InputParameter param; std::ifstream in("someFile.txt"); in >> param; } catch(std::exception& e) { std::cout << "error occured !" << e.what() << std::endl; } return 0; }
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question#ifndef INI_H
#define INI_H
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <iomanip>
//#include "afgen.h"
// ini class
// Reads variable names and set their values from input file
class ini
{
private:
std::ifstream &in_; // data file
std::ios_base::iostate oldstate_; // data file original settings
ini(ini const &);
ini &operator=(ini const &);
void Trim(std::string &str) const;
std::string const Lowercase(std::string const &str) const;
void Parse(std::string const &str, std::string &lhs,std::string &rhs, bool bString);
void FindValue(std::string const &variable, std::string &value);
public:
explicit ini(std::ifstream &file);
~ini();
template <typename T> void Set(std::string const &variable, T &value);
void Set(std::string const &variable, bool &value);
void Set(std::string const &variable, std::string &value);
//void Set(std::string const &variable, afgen &value);
};
// Constructs object and set the I/O flags
inline ini::ini(std::ifstream &file) : in_(file), oldstate_(file.exceptions())
{
in_.exceptions(std::ios_base::failbit | std::ios_base::badbit | std::ios_base::eofbit);
}
inline ini::~ini()
{
in_.exceptions(oldstate_); // restore the I/O flags
}
// Reads the variable name and sets its value from file
// For booleans: reads the variable name and sets its value from file
inline void ini::Set(std::string const &variable, bool &value)
{
std::string str;
FindValue(variable, str);
std::stringstream ss(Lowercase(str));
if (!(ss >> std::boolalpha >> value))
throw std::runtime_error("Bad value read");
}
// For strings: reads the variable name and sets its value from file
inline void ini::Set(std::string const &variable, std::string &value)
{
std::string str;
while (str.empty())
{
char buf[255];
in_ >> buf;
//in_.getline(buf, 255);
str = buf;
Trim(str);
}
std::string lhs, rhs;
Parse(str, lhs, rhs, true);
if (Lowercase(lhs) != Lowercase(variable))
throw std::runtime_error("Variable name not found");
while (rhs.empty())
{
char buf[255];
in_ >> buf;
//in_.getline(buf, 255);
rhs = buf;
Trim(rhs);
}
value = rhs;
}
template <typename T>
void ini::Set(std::string const &variable, T &value)
{
std::string str;
FindValue(variable, str);
std::stringstream ss(str);
if (!(ss >> value))
throw std::runtime_error("Bad value read");
}
// For afgen class: reads the file name and sets the afgen object
/*inline void ini::Set(std::string const &variable, afgen &value)
{
std::string fname; // filename for tabulated data
Set(variable, fname); // get the file name now
value.Filename(fname); // set the afgen object
value.MemoriseTable(); // read in all tabulated data
}*/
#endif // INI_H
#include <cstring>
#include <cstdlib>
#include <cctype>
#include "ini.h"
// INTERNAL USE: Removes whitespaces, quotes and equal sign from
// given string (str)
void ini::Trim(std::string &str) const
{
while (str[0] == ' ' || str[0] == '=' || str[0] == '\t'
|| str[0] == '"')
str.erase(0, 1);
int cLen = static_cast<int>(str.length());
while (cLen > 0 && (str[cLen-1] == ' ' || str[cLen-1] == '\t'
|| str[cLen-1] == '"'))
str.erase(--cLen, 1);
}
// INTERNAL USE: Converts and returns a string, all chars in lowercase
std::string const ini::Lowercase(std::string const &str) const
{
std::string locase(str);
for (std::string::iterator pos=locase.begin();
pos!=locase.end(); ++pos)
*pos = static_cast<char>(std::tolower(*pos));
return locase;
};
// INTERNAL USE: Splits a given string (str) into two: left- (lhs)
// and right hand side (rhs). Where to split the two is where
// the equal sign (=) is located in str.
// If bString is set to TRUE, the rhs string can contain spaces.
void ini::Parse(std::string const &str, std::string &lhs,
std::string &rhs, bool bString)
{
lhs.clear(); // ensure all empty
rhs.clear();
char buf[255];
std::strcpy(buf, str.c_str());
char *pToken = std::strtok(buf, " =\t");
int nCnt = 0;
while (pToken && nCnt<2)
{
if (++nCnt == 1)
lhs = pToken;
else
{
rhs = pToken;
Trim(rhs);
if (rhs.empty())
--nCnt;
}
if (!bString)
pToken = std::strtok(0, " =\t");
else
pToken = std::strtok(0, "\n");
}
}
// INTERNAL USE: Returns the variable's value as string
void ini::FindValue(std::string const &variable, std::string &value)
{
std::string str;
in_ >> str;
std::string lhs, rhs;
Parse(str, lhs, rhs, false);
if (Lowercase(lhs) != Lowercase(variable))
throw std::runtime_error("Variable name not found");
while (rhs.empty())
{
in_ >> lhs;
std::string unused;
Parse(lhs, rhs, unused, false);
}
value = rhs;
}
#ifndef INPUTPARAMETER_H
#define INPUTPARAMETER_H
#include<string>
#include<iostream>
#include"ini.h"
class InputParameter
{
public:
InputParameter();
virtual ~InputParameter();
int &getIntervalTime();
void setIntervalTime(int value);
private:
int m_intervalTime;
};
std::ifstream& operator>>(std::ifstream &in, InputParameter& param);
#endif // INPUTPARAMETER_H
#include "inputparameter.h"
// Default constructor
InputParameter::InputParameter(){}
// Destructor
InputParameter::~InputParameter(){}
int& InputParameter::getIntervalTime()
{
return m_intervalTime;
}
void InputParameter::setIntervalTime(int value)
{
m_intervalTime = value;
}
std::ifstream& operator>>(std::ifstream &in, InputParameter ¶m)
{
ini init(in);
init.Set("TSTART", param.getIntervalTime());
return in;
}
#include <iostream>
#include "inputparameter.h"
int main()
{
try
{
InputParameter param;
std::ifstream in("file.txt");
in >> param;
}
catch(std::exception &e)
{
std::cout << "error occured !" << e.what() << std::endl;
}
}
// Default constructor
InputParameter::InputParameter(){m_intervalTime = 0; m_tStart = 0;}
Il semble que je me sois emmêler les pinceaux dans les types de variables que j'essayais de stocker dans mon objet InputParameter. J'ai mis tout ça en ordre et cela fonctionne parfaitement.
Je devais être fatigué sans doute....
Toujours est il que "l'intellisense de Qt" ne me propose pas ma fonction template set() lorsque j'écris mon code c'est peut être ça qui m'a dérouté....
Au fait dans une de tes remarques tu parles de design dangereux. pourquoi cela ?
InputParameter::InputParameter(){m_intervalTime = 0; m_tStart = 0;}Si tu sais que ton interval et ton start seront fixés une bonne fois pour toutes (pas de modification), alors tu peux faire:
class InputParameter { public: InputParameter(int intervalTime, int tStart); int getIntervalTime() const { return m_intervalTime; } int gettStart() const { return m_tStart; } private: const int m_intervalTime; const int m_tStart; }; InputParameter::InputParameter(int intervalTime, int tStart) : m_intervalTimeintervalTime), tStart(m_tStart) { }
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Bon pour être honnête ma première version est avec une structure dès le départ. Mais je ne suis pas un inconditionnel de l'utilisation des struct dans un design OO.
Mais je ne vois pas comment faire pour utiliser un setter puisqu'il n'a pas de type de retour (void) et me dit du coup : invalide use of void expression si j'utilise un setter.
std::ifstream& operator>>(std::ifstream &in, InputParameter& param) { ini init(in); int tmp; init.Set("TSTART", tmp); param.setIntervalTime(tmp); return in; }
std::ifstream& InputParameter::operator>>(std::ifstream &in) { ini init(in); init.Set("TSTART", m_intervalTime); return in; }
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature