Validation de input char + int en même temps [Résolu/Fermé]

Signaler
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016
-
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016
-
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

Messages postés
11727
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
4 août 2020
671
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.
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016

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
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016

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");
   }

}

}
Messages postés
11727
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
4 août 2020
671
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.
Messages postés
11727
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
4 août 2020
671
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.
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016

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;
}
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016

Alright après des heures intenses d'essais et d'erreurs je crois avoir un code fonctionnel,

je vais poster le code et si vous trouvez quelque chose auquel je n'ai pas pensé faites moi signe svp :)




#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 cLettreUtilisateur;
	int iChiffreUtilisateur;
	std::string sTentativeDeLUtilisateur;
	bool bSuccess = false;


	do
	{
		// J'ai rajouté ces 2 choses car je crois qu'elles seront nécessaires dans le vrai prog
		//system("cls");
		//AfficherPartie();
		std::cout << "Veuillez entrer une lettre et un chiffre : ";
		std::getline(std::cin, sTentativeDeLUtilisateur);

		
		if ((ConvertirEnMajuscule(sTentativeDeLUtilisateur[0]) == 'Q') && (sTentativeDeLUtilisateur.length() == 1))
		{
			std::cout << "\nBRAVO ça rentre dans la fonction Q ! \n";
			break;
		}
		else if ((ConvertirEnMajuscule(sTentativeDeLUtilisateur[0]) == 'S') && (sTentativeDeLUtilisateur.length() == 1))
		{
			std::cout << "\nSUPERBE ça rentre dans la fonction S ! \n";
			break;
		}
		else if ((sTentativeDeLUtilisateur.length() > 1) && (ConvertirEnMajuscule(sTentativeDeLUtilisateur[0]) >= 'A') && (ConvertirEnMajuscule(sTentativeDeLUtilisateur[0]) <= 'J'))
		{
			cLettreUtilisateur = ConvertirEnMajuscule(sTentativeDeLUtilisateur[0]);
		}
		else
		{
			std::cout << "\nChoix non valide\n";
			system("pause");
			continue;
		}



		if ((sTentativeDeLUtilisateur.length() == 2) && (sTentativeDeLUtilisateur[1] >= '0') && (sTentativeDeLUtilisateur[1] <= '9'))
		{
			iChiffreUtilisateur = sTentativeDeLUtilisateur[1];
			bSuccess = true;
		}
		else if ((sTentativeDeLUtilisateur.length() == 3) && (sTentativeDeLUtilisateur[1] == ' ') && (sTentativeDeLUtilisateur[2] >= '0' && sTentativeDeLUtilisateur[2] <= '9'))
		{
			iChiffreUtilisateur = sTentativeDeLUtilisateur[2];
			bSuccess = true;
		}
		else if ((sTentativeDeLUtilisateur.length() == 3) && (sTentativeDeLUtilisateur[1] != ' '))
		{
			std::cout << "\nChoix non valide\n";
			system("pause");
			continue;
		}
		else
		{
			std::cout << "\nChoix non valide\n";
			system("pause");
		}

	} while (bSuccess == false);
	

	system("pause");
	return 0;
}
Messages postés
11727
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
4 août 2020
671
Cela me semble très bien, d'ainsi lire tous des caractères (via sTentativeDeLUtilisateur), de les tester ((sTentativeDeLUtilisateur[1] >= '0') && (sTentativeDeLUtilisateur[1] <= '9')), et, si ce sont des chiffres, de les transformer en nombre (iChiffreUtilisateur = sTentativeDeLUtilisateur[1]).
Petite suggestion : quand "Choix non valide", afficher aussi ce que le programme a reçu, par exemple "Choix (3 Q) non valide".
Bonne continuation, c'est souvent par essais et erreurs qu'on progresse le mieux.
Messages postés
12
Date d'inscription
samedi 10 septembre 2016
Statut
Membre
Dernière intervention
5 décembre 2016

Un gros merci pour votre temps, vos conseils m'ont permis de mieux comprendre ce qui ne fonctionnait pas initialement.

bon, c'est le temps d'aller profiter d'un sommeil bien mérité

merci encore et bonne nuit :)