0/5 (7 avis)
Vue 5 119 fois - Téléchargée 385 fois
#include "../../src/TURS.hh" #include <cstdlib> #include <vector> #include <fstream> void error(unsigned int line, const std::string& message) { std::cerr << "Ligne " << line << " : " << message << std::endl; } //Dans cet exemple, on lit l'entrée standard ou un fichier passé en paramètre //afin d'exécuter des commandes pour manipuler le TURS. int main(int argc, char** argv) { typedef std::vector<std::string>::const_iterator iter; typedef TURS<std::string> TURS_str; //Création d'un TURS de string. TURS_str turs; std::string line; std::vector<std::string> args; unsigned int i = 1; //On sélectionne le fichier passé en paramètre ou l'entrée standard. std::ifstream file; if(argc > 1) { file.open(argv[1]); if(!file) { std::cerr << "Le fichier n'existe pas : " << argv[1] << std::endl; return 1; } } std::istream& in = (argc > 1) ? file : std::cin; while(std::getline(in, line)) { //On récupère la commande. std::istringstream iss(line); std::string cmd; iss >> cmd; //On récupère les arguments. while(iss) { std::string arg; iss >> arg; args.push_back(arg); } //On exécute la commande. if(cmd == "action") { if(args.size() > 0) { turs.addAction(args[0]); } else { error(i, "Argument manquant pour la commande 'action'"); } } else if(cmd == "undo") { turs.undo(); } else if(cmd == "redo") { if(args.size() > 0) { turs.redo(atoi(args[0].c_str())); } else { turs.redo(); } } else if(cmd == "print") { if(args.size() > 0) { for(iter it = args.begin(); it != args.end(); ++it) { if(*it == "$tree") { std::cout << turs << " "; } else if(*it == "$currentVal") { std::cout << turs.currentVal() << " "; } else if(*it == "$nl") { std::cout << std::endl; } else { std::cout << *it << " "; } } std::cout << std::endl; } } else if(cmd == "clear") { turs.clear(); } else if(cmd == "mode") { if(args.size() > 0) { if(args[0] == "tree") { turs.setMode(TURS_str::TREE_MODE); } else if(args[0] == "normal") { turs.setMode(TURS_str::NORMAL_MODE); } else { error(i, "Argument invalide pour la commande 'mode'"); } } else { error(i, "Argument manquant pour la commande 'mode'"); } } else if(cmd == "quit") { break; } args.clear(); i++; } return 0; }
23 juin 2011 à 18:30
(Pas de using namespace, pas de mélange C et C++, utilisation de la STL, des templates, documentation, etc... Ça fait plaisir !).
C'est sympa aussi d'avoir une documentation. C'est encore plus sympa de l'avoir fait en Doxygen !
Au sujet du comportement du programme, il n'y a rien à redire, c'est pratique et aisément utilisable en tant que bibliothèque.
Y a des petits trucs qui me gênent un peu, mais ce n'est pas très grave:
- Inclusion de .cpp dans un .hpp. Pour séparer un code de sa définition, je conseille généralement le couple: .cc/.hh/.hxx ou .cpp/.hh/.hpp
- std::string TURSNode<T>::toString => Plutôt qu'un "std::string ret;" j'utiliserais un std::ostringstream (concaténation plus rapide qu'avec un std::string) avec un "return ret.str()".
- Dans les constructeurs, j'utiliserais la liste d'initialisation plutôt que d'affecter les valeurs dans le corps du constructeurs. Ça te permettrait d'avoir des attributs constants.
- Au lieu de addAction(T val), je mettrais plutôt: addAction(const T& val), sinon bonjour les copies en cas de gros objet ! C'est valable pour les autres aussi.
- J'éviterais les NULL au profit de 0, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp
Au niveau du binaire de démonstration:
- Le makefile est un faux makefile :p. Il ne tient pas compte de ce qui est déjà compilé.
- Tu compiles les *.cpp alors qu'ils sont inclus par les .hpp. Donc théoriquement, ta ligne de compil devrait être: "g++ main.cpp -o CLI"
- Tu ne mets pas de flags de sécurité: "g++ -W -Wall -Wabi -g main.cpp", tu verrais pas mal de warnings ! (Tu compares souvent des entiers signés avec des entiers non signés).
- En release un -o3 serait pas mal non plus :)
- D'après valgrind, tu as des fuites mémoires dans TURS.cpp, ligne 20 et ligne 43. Je t'invite à repasser du valgrind sur ton code.
- Au lieu de faire "char line[]", tu peux mettre un "std::string line", et faire un "while (std::getline(std::cin, line)"
- Ton binaire devrait facultativement prendre en argument un fichier. Pratique pour débugger des fuites mémoires, par exemple :p
J'ai sûrement oublié des choses. Je les ajouterais peut être plus tard.
23 juin 2011 à 18:49
En effet par exemple pour la makefile j'avais bien remarqué que ça compilait même sans avoir modifié les fichiers, mais je ne savais pas d'où venait le problème.
Je vais essayer modifier ça rapidement.
Encore merci :)
23 juin 2011 à 19:00
23 juin 2011 à 20:12
- Gérer les sources suivant le modèle .cpp/.hh/.hpp (je n'ai pas bien compris comment faire et sur internet il n'y a pas beaucoup d'exemples clairs)
- Modifier le makefile de l'exemple pour qu'il ne compile pas à chaque fois (idem, j'ai regardé ton makefile (pour le compilateur Pascal) mais comme c'est pour un gros projet, il est un peu complexe, il faudra que j'y regarde de plus près)
- Vérifier les fuites mémoires (je verrai ça plus tard)
23 juin 2011 à 23:32
C'est pas dur:
- Dans le .hh tu mets la définition de la classe.
- Dans le .cpp le code
- Dans le .hpp (qui est inclus à la fin du .hh) tu mets le code inliné ou templaté.
En fait, c'est juste un souci de nomination que tu as, pas de principe.
> Modifier le makefile de l'exemple pour qu'il ne compile pas à chaque fois (idem, j'ai regardé ton makefile (pour le compilateur Pascal) mais comme c'est pour un gros projet, il est un peu complexe, il faudra que j'y regarde de plus près)
Attention, par convention, "Makefile" prend une majuscule.
Soit tu mets -O3 (avec une majuscule à O) qui veut dire optim maximale, soit tu mets -g (qui veut dire, pas d'optim, ajouter des informations de debug). Les deux ne sont pas compatibles (et sont carrément à l'opposé).
Un Makefile tout mini, adapté à ton projet:
# Liste des fichier cpp, ne jamais mettre *.cpp
SRC=main.cpp
# Liste des headers, ils devraient être en .hpp et .hxx
HEADER= ../../../TURS/src/TURS.cpp \
../../../TURS/src/TURS.hpp \
../../../TURS/src/TURSNode.cpp \
../../../TURS/src/TURSNode.hpp
BINDIR=.
ifdef SystemRoot
BINNAME=CLI.exe
else
BINNAME=CLI
endif
TARGET=$(BINDIR)/$(BINNAME)
OBJ=$(SRC:.cpp=.o)
CPP=g++
CXXFLAGS=-W -Wall -Wabi -O3
all: $(TARGET)
$(TARGET): $(OBJ) $(HEADER)
$(CPP) $(CXXFLAGS) $(OBJ) -o $(TARGET)
%.o: %.cpp
$(CPP) -o $@ -c $< $(CFLAGS)
clean:
rm -rf *.o
distclean: clean
rm -rf $(TARGET)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.