Validation de input char + int en même temps

Résolu/Fermé
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016 - Modifié par Demonaz84 le 4/12/2016 à 04:34
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016 - 5 déc. 2016 à 07:44
Bonjour,

Je travail sur un programme c++ dans lequel je dois utiliser uniquement la base ( donc pas de #include qui rendrait mon problème une farce à règler, je n'ai que le droit de me servir de la base absolue.

Le programme avance très bien, cependant je n'arrive pas à trouver de solution pour valider un char + un integer en même temps ( le programme demande à l'utilisateur d'entrer une lettre + un chiffre en même temps, afin de vérifier si ce chiffre est caché derrière la lettre (jeu plate je sais mais bon il faut commencer à quelque part)

si je fais seulement std::cin cLettre; et std::cin iChiffre; , et que l'utilisateur entre bel et bien une lettre et un chiffre, il n'y a aucun problème le jeu marche très bien.

mais s'il entre n'importe quoi d'autre qu'une lettre + un chiffre (dans cet ordre, quoiqu'il peut y avoir un espace vide entre la lettre et le chiffre) et bien all hell breaks loose, résultant soit en une boucle infinie ou simplement le programme stuck.

si je n'avais qu'une validation pour une lettre ou un chiffre à faire, je n'aurais aucun problème, mais puisque ça doit lire un char + un int en même temps, je n'arrive pas dutout à le faire comme il le faut, j'ai essayé de faire un getline et de le mettre dans un inputstringstream mais je dois mal le faire car ça a empiré ma situation et là ça fait 3 jours que je n'arrive pas à faire quelque chose d'autant banal que de verifier la validité d'un char et d'une lettre en même temps ...


PS, la lettre doit être entre A et J (j'ai déjà une fonction qui transforme les minuscules en majuscules donc pas besoin de se casser la tête avec minuscule/majuscule) , le chiffre entre 0 et 9 , et si lutilisateur entre seulement s et rien d'autre, ça doit aller dans ma fonction savegame, et si il fait q seulement, ça doit quitter la partie ( donc si il fait q4 par exemple, ça ne demandera pas de quitter puisqu'il y a un chiffre, ca devra indiquer que c'est un input invalide

et seulement si la lettre est entre A et J , et que le chiffre est entre 0 et 9 , la valeur de l'input aura passé la barriere et pourra continuer vers le reste du programme afin d'être utilisée ( sans ce filtre de validation un mauvais input peut crasher la partie ) PS : plus loin dans mon programme je doit justement utiliser cLettreUtilisateur et iChiffreUtilisateur dans mes boucles, c'est pour ça seulement les inputs qui respectent parfaitement mes conditions doivent être en mémoire dans ces 2 variables.



Désolé du mur de texte, mais sans dire tout en détails j'ai peur de faire perdre votre temps puisque vous ne pourriez pas savoir exactement le genre de validation que j'ai de besoin (et comme je disait, je n'ai pas le droit de me servir de fonctions avancées du c++, seulement de la base (pas de commande qui ferait la job en 1 ligne de code , juste des for/while/do for et plein de if...)


si quelqu'un a prit le temps de lire tout ça et qu'il sait, en utilisant la base seulement, comment vérifier un char et un int en même temps, en respectant les conditions que j'ai nommées plus haut , ça serait très apprécié parce que je ne trouve RIEN sur youtube ni google, comme si j'étais le premier humain à devoir faire ça ( tout le monde dit comment valider un char ou un int, mais jamais les 2 en meme temps ( ca ne peut pas être 1 après lautre pusique dans le jeu, lutilisateur doit entrer les 2 en meme temps sous ce format : f3 ou f 3 ))

merci

2 réponses

yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 507
4 déc. 2016 à 12:11
Rassure-toi : tu n'es sans doute pas le premier humain à confondre lettre et caractère, ni à confondre chiffre et nombre.
Ta demande serait plus claire si tu postais ton code.
L'utilisateur entre des caractères, et le programme reçoit des caractères.
Pour le programme, le caractère 1 et le caractère A sont des caractères et le nombre 1 est un nombre. Chaque variable a un type, qui détermine comment le programme interprète chaque variable.
Pour un humain, un caractère peut être une lettre, un chiffre, une ponctuation, ou autre chose. Remarque que ce ne sont pas des types de variables.
Le programme peut examiner chaque caractère pour déterminer s'il s'agit d'une lettre ou d'un chiffre.
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016
4 déc. 2016 à 14:29
pour résumer ce que j'ai dit:

l'utilisateur doit faire une tentative dans le jeu, ce qui lui demande d'écrire une lettre et un chiffre en même temps ( donc un char et un int ) sous le format suivant : par exemple, F3 ou F 3).

la difficulté vient que ces 2 types de variables différents sont entrés en même temps.Cela occasionne une multitude de problèmes. Plein d'autres conditions viennent en considération et compliquer les choses, tout est nommé dans mon post initial ci dessus.

Vous sembler penser que je ne sais pas la différence entre un char et un int, j'ai donc dû très mal expliquer mon problème afin que l'on s'écarte à ce point de la nature de mon impasse héhéhé


mon code est trop énorme et divisé en plusieurs .cpp et headers et fonctions afin d'être vraiment postable ici, mais je crois avoir assez bien d'écrit mon problème pour ne pas que ça soit nécessaire de voir mon code.


désolé si mon explication n'était pas assez claire, en espérant que l'essence du problèeme soit maintenant plus évidente
0
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016
Modifié par Demonaz84 le 4/12/2016 à 15:00
voici un segment du code qui devrait aider à illustrer la situation, le probleme survient dans le do while, où je fais std::cin cLettreUtilisateur; et std::cin iChiffreUtilisateur;

puisque les 2 sont entrés en même temps, l'utilisateur ne peut même pas , par exemple, faire Q pour quitter la partie, puisque le programme s'attends à avoir 2 cin , et non juste 1, donc il reste sur Q et attends un deuxième input.

je dois donc utiliser une fonction ( que j'ai mit en commentaire puisque ça ne fonctionne pas du tout, en fait ça empire dramatiquement mes problèmes ) pour valider l'input de l'utilisateur

idéalement, je dois faire un getline et mettre tout l'input de l'utilisateur dans un string , mais je ne le fais pas comme il faut, ça créer des nouveaux problèmes étranges, genre que en chargeant une nouvelle partie, ça affiche avant même que j'aie fait quoi que ce soit '' bonne valeur'' ou mauvaise valeur ... donc clairement je ne maitrise pas la validation multiconditionnelles de la string devant contenir une lettre + un chiffre seulement ( et les exceptions que j'ai nommé en exemple à plusieurs reprises

donc voici le bout de code en question dans lequel à la place du cin cLettre et cin iChiffre je dois faire une fonction pour valider tout ça =




void NouvellePartie()
{

system("cls");


std::string sStringDeCaracteres;
 int iNombreDErreurs = 0;
 bool bPartieTerminee = true;


int iTableauDesNombresDecomposes[18];
 GenererVariables(iTableauDesNombresDecomposes);


int iNombreAssigneAUneLettre[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };


char cLettre[10] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };


BrassageAleatoire(iNombreAssigneAUneLettre, 10);


for (int iCompteur10 = 0; iCompteur10 < 18; iCompteur10++)
 {
 std::ostringstream ossString;
 ossString << iTableauDesNombresDecomposes[iCompteur10];
 sStringDeCaracteres += ossString.str();
 }
 std::cout << "TEST 3 : AFFICHAGE DE LA STRING CONTENANT TOUTES LES 18 VARIABLES DU TEST 2 :\n";
 std::cout << sStringDeCaracteres << "\n"; // test
 system("pause");


// assigne les chiffres random qui sont maintenant dans un string a des lettres random
 for (int iCompteur3 = 0; iCompteur3 < sStringDeCaracteres.length(); iCompteur3++)
 {
  for (int iCompteur4 = 0; iCompteur4 < 10; iCompteur4++)
  {

if (sStringDeCaracteres[iCompteur3] == ('0' + iNombreAssigneAUneLettre[iCompteur4]))
   {
    sStringDeCaracteres[iCompteur3] = cLettre[iCompteur4];
   }
  }
 }
 std::cout << "TEST 4 : AFFICHAGE DE LA STRING QUI CONTIENT MAINTENANT TOUTES LES LETTRES :\n";
 std::cout << sStringDeCaracteres << "\n"; // test
 system("pause");


char cLettreUtilisateur;
 int iChiffreUtilisateur;
 std::string sTentativeUtilisateur; // jai declarer celle la temporairement? pour tester de quoi apres la tentativeutilisateur

do
 {

AfficherPartie(sStringDeCaracteres);

std::cout << "\n\n\nNombre d'erreurs: " << iNombreDErreurs;



// Boucle pour regarder si tout les chiffres sont trouvés
 bPartieTerminee = true;
 for (int iCompteur11 = 0; iCompteur11 < 18; iCompteur11++)
 {
  if (sStringDeCaracteres[iCompteur11] >= 'A' && sStringDeCaracteres[iCompteur11] <= 'J')
  {
   bPartieTerminee = false;
   break;
  }
 }

if (bPartieTerminee == false)
 {
  std::cout << "\n\n\nTentative: ";
  //TentativeDeLUtilisateur(cLettreUtilisateur, iChiffreUtilisateur, sTentativeUtilisateur);

std::cin >> cLettreUtilisateur;
   std::cin >> iChiffreUtilisateur;



if (iNombreAssigneAUneLettre[ConvertirEnMajuscule(cLettreUtilisateur) - 'A'] == iChiffreUtilisateur)
  {
   std::cout << "Bonne valeur\n\n";
   for (int iCompteur5 = 0; iCompteur5 < sStringDeCaracteres.length(); iCompteur5++)
   {
    if (ConvertirEnMajuscule(cLettreUtilisateur) == sStringDeCaracteres[iCompteur5])
    {
     sStringDeCaracteres[iCompteur5] = ('0' + iChiffreUtilisateur);
    }
   }
  }
  else { ++iNombreDErreurs; std::cout << "Cette valeur est incorrecte\n\n"; }
  system("pause");
 }



} while (bPartieTerminee == false); // Fin du 'do'


if (bPartieTerminee == true)
  {
   if (iNombreDErreurs > 1)
   {
    std::cout << "\n\nJeu résolu avec " << iNombreDErreurs << " erreurs\n\n";
    system("pause");
   }
   else
   {
    std::cout << "\n\nJeu résolu avec " << iNombreDErreurs << " erreur\n\n";
    system("pause");
   }

}

}
0
yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 507
Modifié par yg_be le 4/12/2016 à 15:53
Qu'est-ce qui t’empêche, après
std::cin >> cLettreUtilisateur;
, de tester immédiatement si cLettreUtilisateur est un "Q"?
Quand l'utilisateur n'entre pas de bonnes valeurs, le programme affiche malgré tout "Bonne valeur"? Ne serait-ce pas utile d'afficher cLettreUtilisateur et iChiffreUtilisateur ? Cela t'aiderait peut-être à comprendre ce qui se passe.
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016
4 déc. 2016 à 16:38
aller, j'ai fait un petit programme comme tu l'as demandé, et ça fait la même chose, apres la première étape d'entrer et de vérifier les char, le stringstream entre des valeurs invisibles sans que je fasse quoique ce soit et ca affiche mauvaise valeur

copie colle mon programme et entre par exemple 'km', ca va valider k et m comme etant de bonnes lettres, puisi ensuite ca va meme pas te laisser le temps dentrer des chiffres ca va deja dire mauvaise valeur




#include <iostream>
#include <string>
#include <sstream>


char ConvertirEnMajuscule(char cCaractere)
{

	if (cCaractere >= 'a' && cCaractere <= 'z')
	{
		cCaractere = 'A' + cCaractere - 'a';
	}
	return cCaractere;
}



int main()
{
	setlocale(LC_ALL, "");

	char cChar1;
	char cChar2;
	int iInt1;
	int iInt2;
	std::string sTentative;
	bool bSuccessChar = false;
	bool bSuccessInt = false;


	do
	{
		std::cout << "Veuillez entrer 2 lettres : ";
		std::cin >> cChar1 >> cChar2;

		if ((ConvertirEnMajuscule(cChar1) >= 'A' && ConvertirEnMajuscule(cChar1) <= 'Z') && (ConvertirEnMajuscule(cChar2) >= 'A' && ConvertirEnMajuscule(cChar2) <= 'Z'))
		{
			bSuccessChar = true;
			std::cout << "\ncChar1 : " << cChar1 << "  cChar2 :  " << cChar2 << "\n\n";
		}
		else
		{
			std::cout << "\nInput invalide, doit être une lettre entre a et z\n\n";
			system("pause");
			bSuccessChar = false;
		}

	} while (bSuccessChar == false);



	do
	{
		std::cout << "\nVeuillez entrer 2 chiffres : ";
		std::getline(std::cin, sTentative);
		std::istringstream issTentative;
		issTentative.str(sTentative);
		issTentative >> iInt1 >> iInt2;

		if ((iInt1 >= 0 && iInt1 <= 9) && (iInt2 >= 0 && iInt2 <= 9))
		{
			bSuccessInt = true;
			std::cout << "\niInt1 : " << iInt1 << "  iInt2 :  " << iInt2 << "\n\n";
		}
		else
		{
			std::cout << "\nInput invalide, doit être un chiffre entre 0 et 9\n\n";
			system("pause");
			bSuccessInt = false;
		}

	} while (bSuccessInt == false);



	system("pause");
	return 0;
}
0
yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 507
4 déc. 2016 à 17:51
Peux-tu être plus factuel, et décrire ce que le programme affiche à chaque étape quand tu testes? Je te suggère d'afficher à chaque fois ce que le programme reçoit après chaque cin.
0
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016
4 déc. 2016 à 19:31
ok , je viens de rajouter des cout un peu partout pour tester à chaque étape, et voici ce que ça donne ( screenshot )

https://s3.postimg.org/rhql49083/test.jpg

il y a quelque chose qui ne fonctionne pas dans ma façon d'utiliser le stringstream, pour une raison que je cherche à comprendre, ça affiche le message de input invalide avant même que je n'aie pu entrer quoi que ce soit ,

également, la valeur de iInt1 et iInt2 ne sont pas transférées proprement, puisque le cout affiche une case de mémoire vide ( chiffre genre 650023981287 )

sauriez-vous comment régler tout ça ?
0
yg_be Messages postés 23020 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 24 juillet 2024 1 507
4 déc. 2016 à 22:29
Eh bien, je vois que le getline lit la suite de la ligne entrée précedement.
Je te suggère de mettre -1 dans int1 et int2 avant
issTentative >> iInt1 >> iInt2;
, cela te permettra de te rendre compte que
issTentative >> iInt1 >> iInt2;
n'a pas réussi à trouver des nombres.
0
Demonaz84 Messages postés 12 Date d'inscription samedi 10 septembre 2016 Statut Membre Dernière intervention 5 décembre 2016
5 déc. 2016 à 00:48
ok, j'ai changé les int en char puisque venu le temps de lire 2 chiffres en même temps sans espace ça lisait juste 1 chiffre

j'ai fait roulé le déboggage en mode pas à pas et je me rend compte que ça passe une fois au complet mon 2ième do while avant de recommencer du début et là enfin il attend que je rentre le int1 et int2 et le mettre dans la string


pourquoi ça fait ça ? pourquoi comme vous dites le getline lit la ligne précédente et pourquoi ça lit le 2ième do while au complet une fois avant de retomber dedans et là enfin d'attendre que j'entre quelque chose ?

comment/où devrais-je mettre le getline pour éviter ce fiasco ?


voici le code modifié légèrement =

#include <iostream>
#include <string>
#include <sstream>


char ConvertirEnMajuscule(char cCaractere)
{

	if (cCaractere >= 'a' && cCaractere <= 'z')
	{
		cCaractere = 'A' + cCaractere - 'a';
	}
	return cCaractere;
}



int main()
{
	setlocale(LC_ALL, "");

	char cChar1;
	char cChar2;
	char cInt1 = -1 + '0';
	char cInt2 = -1 + '0';
	std::string sTentative;
	bool bSuccessChar = false;
	bool bSuccessInt = false;


	do
	{
		std::cout << "Veuillez entrer 2 lettres : ";
		std::cin >> cChar1 >> cChar2;
		std::cout << "\nTEST : " << cChar1 << " " << cChar2 << "\n";

		if ((ConvertirEnMajuscule(cChar1) >= 'A' && ConvertirEnMajuscule(cChar1) <= 'Z') && (ConvertirEnMajuscule(cChar2) >= 'A' && ConvertirEnMajuscule(cChar2) <= 'Z'))
		{
			bSuccessChar = true;
			std::cout << "\ncChar1 : " << cChar1 << "  cChar2 :  " << cChar2 << "\n\n";
		}
		else
		{
			std::cout << "\nTEST : " << cChar1 << " " << cChar2 << "\n";
			std::cout << "\nInput invalide, doit être une lettre entre a et z\n\n";
			system("pause");
			bSuccessChar = false;
		}

	} while (bSuccessChar == false);

	std::cout << "\nTEST between both do whiles : " << cChar1 << " " << cChar2 << "\n";


	do
	{
		std::cout << "\nVeuillez entrer 2 chiffres : ";
		std::cout << "\nTest 2 AVANT GETLINE " << cInt1 << " " << cInt2 << "\n";
		std::getline(std::cin, sTentative);
		std::cout << "\nTest 2 APRES GETLINE " << cInt1 << " " << cInt2 << "\n";
		std::istringstream issTentative;
		issTentative.str(sTentative);
		issTentative >> cInt1 >> cInt2;
		std::cout << "\nTest 2 APRES >> cInt1 >> cInt2 " << cInt1 << " " << cInt2 << "\n";

		if (issTentative)
		{
		if ((cInt1 >= 0 && cInt1 <= 9) && (cInt2 >= 0 && cInt2 <= 9))
		{
			bSuccessInt = true;
			std::cout << "\ncInt1 : " << cInt1 << "  cInt2 :  " << cInt2 << "\n\n";
		}
		else
		{
			std::cout << "\nTest 2 " << cInt1 << " " << cInt2 << "\n";
			std::cout << "\nInput invalide, doit être un chiffre entre 0 et 9\n\n";
			system("pause");
			bSuccessInt = false;
		}
		}

	} while (bSuccessInt == false);

	std::cout << "\nTest 2 après les 2 do whiles : " << cInt1 << " " << cInt2 << "\n";


	system("pause");
	return 0;
}
0