Herezh_dev/Util/CharUtil.cc
2023-05-03 17:23:49 +02:00

408 lines
14 KiB
C++

// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.
#include "CharUtil.h"
#include <sstream> // for istringstream
using namespace std;
#include <limits>
// transformation d'un string ou d'une chaine de character en entier
int ChangeEntier(string st)
{ using namespace std;
char * chh = (char*)st.c_str();
#ifndef ENLINUX_STREAM
istringstream flux (chh);
#else
istrstream flux (chh);
#endif
int i;
flux >> i;
return i;
};
int ChangeEntier(char * st)
{using namespace std;
#ifndef ENLINUX_STREAM
istringstream flux (st);
#else
istrstream flux (st);
#endif
int i;
flux >> i;
return i;
};
// test d'un nombre numérique: ref: http://rosettacode.org/wiki/Determine_if_a_string_is_numeric
bool isNumeric( const char* pszInput, int nNumberBase )
{
istringstream iss( pszInput );
if ( nNumberBase == 10 )
{
double dTestSink;
iss >> dTestSink;
}
else if ( nNumberBase == 8 || nNumberBase == 16 )
{
int nTestSink;
iss >> ( ( nNumberBase == 8 ) ? oct : hex ) >> nTestSink;
}
else
return false;
// was any input successfully consumed/converted?
if ( ! iss )
return false;
// was all the input successfully consumed/converted?
return ( iss.rdbuf()->in_avail() == 0 );
};
// transformation d'un string ou d'une chaine de character en relle
double ChangeReel(string st)
{ using namespace std;
#ifndef ENLINUX_STREAM
istringstream flux ((char*) st.c_str());
#else
istrstream flux ((char*) st.c_str());
#endif
double i;
flux >> i;
return i;
};
double ChangeReel(char * st)
{ using namespace std;
#ifndef ENLINUX_STREAM
istringstream flux (st);
#else
istrstream flux (st);
#endif
double i;
flux >> i;
return i;
};
// recherche "nom" dans le tableau "tabMot", si nom existe ramene true, sinon false
bool ExisteString (Tableau<string>& tabMot,string nom)
{ for (int i=1;i<= tabMot.Taille();i++)
if (tabMot(i) == nom)
return true;
return false;
};
// transformation d'un entier en chaine de caractere correspondant
string ChangeEntierSTring(int a)
{ int b = a ;
string sor = "";
do
{ // on recherche la derniere decimale
int reste = b % 10 ;
// on ajoute a la chaine
sor = ChangeEntierChar(reste) + sor;
// on calcul le chiffre des dizaines
b = b/10;
} while (b != 0) ;
return sor;
} ;
// transformation d'un réel en chaine de caractère correspondant
string ChangeReelSTring(double a)
{using namespace std;
char tab[50]; // 50 caractères pour écrire le réel !!
char* st = tab;
#ifndef ENLINUX_STREAM
ostringstream flux (st,50);
#else
ostrstream flux (st,50);
#endif
flux << a << ends;
return st;
};
// transformation d'un entier de 0 a 10 en 1 caractere correspondant
// il existe une fonction _itoa qui fait le meme travail qui se trouve dans extras.h
char ChangeEntierChar(int a)
{ char result= ' ';
switch (a)
{case 0 :
result='0';break;
case 1 :
result='1';break;
case 2 :
result='2';break;
case 3 :
result='3';break;
case 4 :
result='4';break;
case 5 :
result='5';break;
case 6 :
result='6';break;
case 7 :
result='7';break;
case 8 :
result='8';break;
case 9 :
result='9';break;
default :
cout << "\nErreur : l'entier n'est pas compris entre 0 et 9 !\n";
cout << "ChangeEntierChar(int a) \n";
Sortie(1);
};
return result;
};
// transformation d'un string en minuscules
string Minuscules(const string& st)
{ using namespace std;
unsigned long int lon= st.length ();
string reponse;
for (unsigned long int i=0;i<lon;i++)
reponse += (char) tolower(st[i]);
return reponse;
};
// -------- utilitaire pour lire une chaine de caractères:
// si retour chariot, retourne la valeur par défaut passée en paramètre
// sinon retourne le string lue au clavier
// gestion d'erreur si lecture non correcte
// si avec_ecriture = true: on écrit "--> valeur par defaut : n " val_defaut
string lect_return_defaut(bool avec_ecriture,string val_defaut)
{ string rep;
bool entree_non_valide = true;
while (entree_non_valide)
{ // on s'intéresse d'abord au retour chariot
int c = std::cin.peek(); // peek character (sans changer le flux !!)
if (( c == EOF )||(c=='\n'))
{rep = val_defaut;
if (avec_ecriture)
cout << "--> valeur par defaut : "<< val_defaut << flush ;
c = getchar(); // on lit quand même le caractère
entree_non_valide = false;
}
else // sinon on peut lire
{std::getline (std::cin,rep);};
// gestion d'erreur éventuelle
if ( std::cin.fail() || std::cin.eof())
{std::cout << "\n Saisie incorrecte, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon c'est ok
{entree_non_valide = false;};
};
// retour de l'info
return rep;
};
// lecture d'une chaine de caractère via getline: pas de validation
// tant qu'il n'y a rien de lue
// gestion d'erreur si lecture non correcte
string lect_chaine()
{ string rep;
bool entree_non_valide = true;
while (entree_non_valide)
{ // on s'intéresse d'abord au retour chariot
int c = std::cin.peek(); // peek character (sans changer le flux !!)
if (( c == EOF )||(c=='\n'))
{std::cout << "\n Saisie incorrecte, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
entree_non_valide = false;
}
else // sinon on peut lire
{std::getline (std::cin,rep);};
// gestion d'erreur éventuelle
if ( std::cin.fail() || std::cin.eof())
{std::cout << "\n Saisie incorrecte, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon c'est ok
{entree_non_valide = false;};
};
// retour de l'info
return rep;
};
// lecture d'un scalaire réel avec getline
// gestion d'erreur si lecture non correcte
double lect_double()
{ string rep;
bool entree_non_valide = true;
while (entree_non_valide)
{ // on s'intéresse d'abord au retour chariot
int c = std::cin.peek(); // peek character (sans changer le flux !!)
if (( c == EOF )||(c=='\n'))
{std::cout << "\n Saisie incorrecte, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
entree_non_valide = false;
}
else // sinon on peut lire
{std::getline (std::cin,rep);};
// gestion d'erreur éventuelle
if ( std::cin.fail() || std::cin.eof())
{std::cout << "\n Saisie incorrecte, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon c'est ok
{entree_non_valide = false;};
};
// on traduit en réel
double result = ChangeReel(rep);
// retour de l'info
return result;
};
//
//rep = lect_return_defaut(false,"f");
//rep = lect_return_defaut(false,"o");
//rep = lect_return_defaut(true,"o");
//= lect_chaine();
//rep = lect_chaine();
//(int) lect_double();
//#include "CharUtil.h"
// cas d'une valeur o/n , sinon pas acceptable
// si avec_ecriture = true: on écrit "--> valeur lue : " valeur lue
string lect_o_n(bool avec_ecriture)
{ string rep;
bool entree_non_valide = true;
while (entree_non_valide)
{ // on s'intéresse d'abord au retour chariot
int c = std::cin.peek(); // peek character (sans changer le flux !!)
if (( c == EOF )||(c=='\n'))
{// ce n'est pas acceptable
std::cout << "\n Saisie incorrecte1, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
entree_non_valide = false;
}
else // sinon on peut lire
{std::getline (std::cin,rep);};
// gestion d'erreur éventuelle
if ( std::cin.fail() || std::cin.eof())
{std::cout << "\n Saisie incorrecte2, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon c'est ok
{ rep = Minuscules(rep);
if (!((rep == "o") || (rep == "n")))
{std::cout << "\n Saisie incorrecte3, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
}
else // sinon ouf, c'est ok
{entree_non_valide = false;
if (avec_ecriture)
cout << "--> valeur lue : "<< rep << flush ;
};
};
};
// retour de l'info
return rep;
};
// cas d'une valeur 1/0 , sinon pas acceptable
// si avec_ecriture = true: on écrit "--> valeur lue : " valeur lue
string lect_1_0(bool avec_ecriture)
{ string rep;
bool entree_non_valide = true;
while (entree_non_valide)
{ // on s'intéresse d'abord au retour chariot
int c = std::cin.peek(); // peek character (sans changer le flux !!)
if (( c == EOF )||(c=='\n'))
{// ce n'est pas acceptable
std::cout << "\n Saisie incorrecte1, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon on peut lire
{std::getline (std::cin,rep);};
// gestion d'erreur éventuelle
if ( std::cin.fail() || std::cin.eof())
{std::cout << "\n Saisie incorrecte2, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
}
else // sinon c'est ok
{ rep = Minuscules(rep);
if (!((rep == "1") || (rep == "0")))
{std::cout << "\n Saisie incorrecte3, recommencez : ";
std::cin.clear(); // effacer les bits d'erreurs
}
else // sinon ouf, c'est ok
{entree_non_valide = false;
if (avec_ecriture)
cout << "--> valeur lue : "<< rep << flush ;
};
};
};
// retour de l'info
return rep;
};
// lecture du prochain caractère non espace et non vide dans le flot sans modifier le flot
// en remplacement de la méthode peek qui ne marche pas avec code warrior
// si pb ou aucun caractère, retour du caractère "espacement"
char Picococar(ifstream& entr)
{ char car; // = flot.peek();
entr >> car;
// si pb cela signifie qu'en fait la ligne est terminée donc on s'arrête
if (entr.rdstate() != 0) {return ' ';}
// sinon on lit jusqu'à un caratère non nul
while ( (car==' ') && (entr.rdstate() == 0 ))
// cas où le prochain caractère est un espace
{ entr >> car;
}
// si c'est une sortie car pb on retourne car c'est la fin de ligne
if (entr.rdstate() != 0) return ' ';
// sinon on remet le caractère dans le flot
entr.putback(car);
return car;
};
char Picococar(istrstream& entr)
{ char car; // = flot.peek();
entr >> car;
// si pb cela signifie qu'en fait la ligne est terminée donc on s'arrête
if (entr.rdstate() != 0) {return ' ';}
// sinon on lit jusqu'à un caratère non nul
while ( (car==' ') && (entr.rdstate() == 0 ))
// cas où le prochain caractère est un espace
{ entr >> car;
}
// si c'est une sortie car pb on retourne car c'est la fin de ligne
if (entr.rdstate() != 0) return ' ';
// sinon on remet le caractère dans le flot
entr.putback(car);
return car;
};