begin process at 2012 05 27 19:01:33
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Chaîne de caractères

 > REMPLACER LE CIN.GETLINE( )

REMPLACER LE CIN.GETLINE( )


 Information sur la source

 Description

Après avoir eu des erreurs de bizarre de comportement avec cin.getline() voici un bout de code :

Source

  • ////////////////////////////////////////////////////////////
  • //
  • // LireLigne permet de lire une ligne complète sans poser
  • // problème comme le GetLine()
  • //
  • ////////////////////////////////////////////////////////////
  • string LireLigne()
  • {
  • string sLue;
  • char cLu;
  • // pour vider le buffer avant de procéder
  • // à la lecture
  • if (cin.peek() == LF)
  • while (cin.get() != LF);
  • // lecture de la ligne
  • cLu = cin.get();
  • while (cLu != LF)
  • {
  • sLue = sLue + cLu;
  • cLu = cin.get();
  • }
  • return sLue;
  • }
////////////////////////////////////////////////////////////
//
// LireLigne permet de lire une ligne complète sans poser
// problème comme le GetLine()
//
////////////////////////////////////////////////////////////
string LireLigne()
{
	string sLue;
	char cLu;

	// pour vider le buffer avant de procéder
	// à la lecture
	if (cin.peek() == LF)
		while (cin.get() != LF);

	// lecture de la ligne
	cLu = cin.get();
	while (cLu != LF)
	{
		sLue = sLue + cLu;
		cLu = cin.get();
	}
	return sLue;
}




 Sources du même auteur

Source avec Zip Source avec une capture Source .NET (Dotnet) WEBCAM C++.NET
RÉCUPÉRER D'UNE ERREUR DE LECTURE SUR UN FLUX
Source avec Zip JEU DE MÉMOIRE EN MODE CONSOLE, POUR LES INTERMÉDIAIRES EN P...

 Sources de la même categorie

CALCUL DE CLEF RIB par Renfield
Source avec Zip [C] WD_STRING V2.2 par cyberripper
Source avec Zip LES STRING EN C, AFFECTATION, CONCATÉNATION, SPLIT, ... par appranting
Source avec Zip [C] WD_STRING V1.9 par cyberripper
Source avec Zip LIBRAIRIE LANGUAGES par astro53

 Sources en rapport avec celle ci

RÉCUPÉRER D'UNE ERREUR DE LECTURE SUR UN FLUX par lacousine
Source avec Zip JEU DE COMBAT MODE TEXTE par gromito

Commentaires et avis

Commentaire de vecchio56 le 27/01/2006 18:01:17 administrateur CS

Tu oublies un petit détail: sLue = sLue + cLu; va provoque probablement beaucoup de réallocation
getLine n'a pas d'erreur de comportement puisque tu spécifie la taille maximum d'une ligne.
Comme ton autre code, je trouve que c'est un peu léger (tu aurais au moins pu les rassembler)

Commentaire de lacousine le 28/01/2006 21:12:42

vecchio56 : Après avoir programmé et avoir eu des problèmes avec getline() en rapport avec le flux de retour, le professeur nous a pondu ce petit bout de code. Tous comme l'autre d'ailleurs que j'ai affiché. Le but de ses 2 petites fonctions est pour ceux qui vont subir le même sort un jour au l'autre. Et sur le WebChat plusieurs m'ont demandé dans la même semaine de résoudre leur problème... et après avoir essayer les 2 fonctions fournis, ça réglé leur problème. Et j'étais tannée de toujours chercher pour trouver mon code et c'est le pourquoi je les ai affichiées ici, afin que ca soit une aide pour ceux qui en auront besoin.

ps. Je ne suis pas l'auteur des fonctions, donc inutile de me demander pourquoi j'ai fait ca de cette façon. :P

Commentaire de lacousine le 28/01/2006 21:15:23

En passant, je trouve ca facultatif de dire que : sLue = sLue + cLu; va surement poser beaucoup de réallocation, car je ne vois aucune place ou la fonction fait un new, puisqu'elle utilise l'opérateur +=.

Commentaire de vecchio56 le 28/01/2006 21:40:32 administrateur CS

et += ne fait pas réallocation peut être?

Commentaire de BruNews le 28/01/2006 23:19:21 administrateur CS

Il est certain qu'on ne "voit" rien quand on utilise des bidules comme 'string' ou autres trucs de ce genre. Pour autant il faut bien mettre les octets quelque part et c'est bien à coup de 'new' que la classe string obtiendra la place, ce qui est une calamité en performance et en fragmentation de l'espace mémoire du processus.

Commentaire de lacousine le 29/01/2006 16:46:08

Premièrement : http://support.microsoft.com/default.aspx?scid=kb;EN-US;q240015

Deuxièmement : je ne peux rien dire sur le fait que la réallocation de mémoire. Mais voici une explication détaillée : (qui n'est pas de moi) Et que j'aurais du utiliser peut-être...


-----------------------------------------------------------------------

Le langage C++ offre une variété d'outils d'entrée/ sortie sur des flux de données, et utilise les classes std::istream et std::ostream comme abstractions fondamentales pour représenter (respectivement) les flux en entrée et les flux en sortie. Appliquant héritage et polymorphisme, ceci permet de gérer sur un même pied les entrées/ sorties à la console (avec, en particulier, std::cin, une instance de std::istream liée à l'entrée standard—typiquement le clavier—et std::cout, une instance de std::ostream liée à la sortie standard—typiquement l'écran en mode console), sur un lien de communication, sur un fichier ou sur tout conteneur respectueux de certaines règles de base.

ex :
#include <string>
#include <fstream>
#include <iostream>
// lit chaque mot d'un fichier texte et les affiche
// à la sortie standard, séparés par des tabulations
int main ()
{
   std::string Mot;
   std::ifstream fichierEntree ("in.txt");
   while (fichierEntree >> Mot)
      std::cout << Mot << '\t';
}


Pour l'entrée de chaînes de caractères, on aura tendance à utiliser l'opérateur >> tel que défini sur un opérande de gauche de type std::istream& et sur un opérande de droite de type std::string&, profitant ainsi de la grande souplesse du type std::string, dont les instances ont une capacité d'entreposage capable de croître en fonction des besoins (ce qui élimine les problèmes de dépassement de capacité des zones tampons, aussi nommées Buffer Overflow Problems).

L'opérateur >> sur un flux en entrée et une std::string a pour comportement de lire sur le flux jusqu'à la rencontre du premier caractère d'espacement.

Si on désire lire une ligne à la fois, par exemple dans un cas où les espaces sont significatifs, alors ce n'est pas le meilleur outil.

Dans ces circonstances, on a habituellement recours à std::getline().

Il se trouve que std::getline() est une fonction très efficace qui prend en paramètre un std::istream& et un std::string& et qui lit des caractères du flux jusqu'à un délimiteur de fin de chaîne (on peut décider soi-même de lire jusqu'à un caractère particulier qui soit différent de '\n' en insérant le délimiteur désiré comme troisième paramètre de la fonction).

Il est très fréquent que des étudiants manipulant ces deux outils rencontrent des problèmes à l'usage de std::getline(). En effet, dans un programme comme celui-ci, la lecture de la chaîne s va être escamotée.

On peut comprendre ce qui se passe en allant tracer le code de std::getline(), qui est un template exposé dans le fichier d'en-tête <string>, mais voici en gros ce qui se passe :

- lorsqu'on lit le premier entier (Val), l'entier en soi est lu, mais std::cin garde dans son tampon interne le caractère de nouvelle ligne ('\n') ayant servi à compléter l'entrée de données, parce que ce caractère ne fait pas partie de l'entier lu et parce qu'il pourrait être utile lors de la prochaine lecture (std::cin ne sait pas que nous, le '\n', on n'en veut pas);

- par défaut (et c'est ce qu'on veut), std::getline() lit ce qui apparaît dans le tampon du flux en entrée reçu en paramètre (ici: std::cin) jusqu'à ce qu'apparaisse un premier '\n'. Dans notre cas, s'il traîne un tel caractère dans le tampon, c'est moche;

- le truc élégant est de vérifier au besoin s'il y a, au début du tampon du flux en entrée utilisé pour std::getline() (donc au début du tampon de std::cin), un changement de ligne ('\n') ou un retour de chariot ('\r') qui traîne dans le cas où on sait qu'il est possible qu'on ait laissé traîner un tel caractère, et de l'enlever du flux s'il y a lieu.

Je vous propose donc la version ci-dessous, qui (elle) fonctionne bien:

#include <string>
#include <iostream>
int main ()
{
   std::cout << "Entrez un entier...";
   int Val;
   std::cin >> Val;
   std::cout << "Entrez une ligne de texte...";
   std::string s;
   char c = std::cin.peek ();
   if (c == '\n' || c == '\r')
      std::cin.get (c);
    // lire une ligne avec std::cin, la mettre dans s
    std::getline (std::cin, s);
   std::cout << s << std::endl;
}


L'appel à std::cin.peek() retourne le premier caractère au début du flux en entrée. S'il s'agit d'une fin de ligne, alors on le retire du flux. Il est important de vérifier la présence ou non d'un tel caractère, d'ailleurs, car deux cas sont possibles:

- soit l'usager entre un entier, puis presse <return>, puis entre du texte. Dans ce cas, la lecture de l'entier se terminera au caractère de nouvelle ligne, et ce caractère sera encore au début dans le tampon du flux en entrée juste avant l'appel à std::getline(). Dans un tel cas, retirer le caractère de flux sera important;

- soit l'usager entre un entier puis peut-être un espace puis du texte, puis appuie sur <return>. Dans ce cas, le caractère retourné par l'appel à std::cin.peek() sera le premier caractère suivant l'entier dans le tampon du flux, et ce caractère ne sera manifestement pas un changement de ligne, et risque d'être significatif. Dans un tel cas, il faut laisser ce caractère dans le flux pour que std::getline() en prenne possesion.

Et pour les curieux, voici la fonction getline :

template<class _Elem,
class _Traits,
class _Alloc> inline
basic_istream<_Elem, _Traits>& __cdecl getline(
basic_istream<_Elem, _Traits>& _Istr,
basic_string<_Elem, _Traits, _Alloc>& _Str,
const _Elem _Delim)
{ // get characters into string, discard delimiter
typedef basic_istream<_Elem, _Traits> _Myis;
ios_base::iostate _State = ios_base::goodbit;
bool _Changed = false;
const typename _Myis::sentry _Ok(_Istr, true);

if (_Ok)
{ // state okay, extract characters
_TRY_IO_BEGIN
_Str.erase();
const typename _Traits::int_type _Metadelim =
_Traits::to_int_type(_Delim);
typename _Traits::int_type _Meta = _Istr.rdbuf()->sgetc();

for (; ; _Meta = _Istr.rdbuf()->snextc())
if (_Traits::eq_int_type(_Traits::eof(), _Meta))
{ // end of file, quit
_State |= ios_base::eofbit;
break;
}
else if (_Traits::eq_int_type(_Meta, _Metadelim))
{ // got a delimiter, discard it and quit
_Changed = true;
_Istr.rdbuf()->sbumpc();
break;
}
else if (_Str.max_size() <= _Str.size())
{ // string too large, quit
_State |= ios_base::failbit;
break;
}
else
{ // got a character, add it to string
_Str += _Traits::to_char_type(_Meta);
_Changed = true;
}
_CATCH_IO_(_Istr)
}

if (!_Changed)
_State |= ios_base::failbit;
_Istr.setstate(_State);
return (_Istr);
}

Commentaire de victorcoasne le 29/01/2006 21:18:52

Le string est la manière C d'être fénéant !

Ce qui est encore plus fénéant c'est de donner un code qui n'est pas de soi.

Perso, jamais eu de problème avec getline (sauf si je met un cin.getline puis un cin forcement mais tout se résouds en ajoutant un deuxième getline qui sert à rien sauf à éviter le plantage du cin suivant).

Bonne prog,
@++

Commentaire de vecchio56 le 29/01/2006 21:27:54 administrateur CS

Moi j'ai résolu tous ces problèmes en arrêtant de travailler dans la console

Commentaire de BruNews le 29/01/2006 21:36:01 administrateur CS

C'est concis et plein de bon sens, surtout que la console pour trouver des clients...

Commentaire de victorcoasne le 31/01/2006 22:32:48

Vecchio56 > J'ai la même solution que toi mais certains sont restés fidèle au NOIR ET BLANC (à croire que la couleur n'a pas été inventé). Mais on peut colorer le texte me direz-vous, donc je peux être plus clair et vous dire que si on fait maintenant des environnement 64bits c'est pas pour retourner sous (Console) DOS !

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

problème avec cin.getline(...,...,...) [ par bouba ] J'utilise cin.getline() pour stocker une chaîne de caractère entrée au clavier. Le problème est qu'il faut appuyer deux fois sur entrée pour valider l prob avec cin.getline(); [ par yafuka ] salut!j''essai de rentrer des chaines de caracteres de la misere a boucler le cin.getline.ma fonction ajouteevoid book::Ajouter(){ cout &lt;&lt; "Titr a propos de cin.getline [ par Xneo ] Je voudrais savoir quelle ligne de code mettre après les cin.getline pr vidé le buffer ou un truc kom sa parske si je met plusieurs cin.getline a la s cin.getline(str, 256) [ par ronandmcdonald ] Salut je voulais savoir comment cela se fess que je peux pas utiliser cin.getline dans une fonction que voila :bool RS232::Write_RS232(){DWORD dwWritt Question à la con sur un getline() [ par Killvador ] Salut tt le monde,G un petit problème:dans ce petit prog le début marche jusqu'a la getline() qu'on dirait que le prog l'a complétement zapé.(y passe Problème cin.getline [ par visualstar ] Bonsoir, J'ai un petit problème qui est grave chiant lolJe programme sous linux en C++ et à un moment donné, je dois faire ceci :fflush(stdin);cout &l J'ai un problème avec cin.getline!! [ par Chap71 ] Voici mon prgm:#pragma hdrstop#pragma argsused#include&lt;iostream&gt;#include&lt;fstream&gt;#include&lt;iomanip&gt;#include&lt;stdio.h&gt;using names Probleme, aide moi svp! [ par lanbook ] Bonjour, j'ai fait un petit programme en C++ qui permet de saisir et d'affichir des donne&#233;s. Le programme marche bien sauf au moment o&#249; l'on cin [ par snpier wolf ] bonjours à tous,voila j'ai cherché partout et pas moyen de trouver une solution a mon problèmme.je vous explique, j'ais fait un programme qui ouvre un cin.getline dans un Case : Marche pas !!! [ par Sixpion ] bonjour a tous !!on a un petit pb avec l'insertion de cin.getline dans des Case (voir code) il semblerai que le cin.getline fct bien dans le main mais


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,421 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales