Problème chaîne de caractère.

Résolu
Bonjour à tous, voilà dans un programme j'aimerai demander un chiffre à l'utilisateur petit problème: Il faut enfaîte que dans ce qu'il ai rentré je regarde si il y a un + ou un - et si il y en a un, j'aimerai que le + ou le - sois obligatoirement au début, et j'aimerai qu'il puisse n'en rentré que un des deux, et qu'il puisse n'en rentré que un.
En gros voila ce que j'aimerai:
input("Nombre à rentré:")
si l'utilisateur rentre -12156- et bien ça marque réessayer, si il tape 1-2 sa marque réessaye également, si il tape -32 et bien la boucle le "laisse passer".
Voilà en gros ce que j'aimerai. Je suppose qu'il faudra des méthodes, et bien j'aimerai juste que vous me l'ai donniez; sans me faire le code m'voyez? Juste pour que je fasse un peu tout seul :P Voilà merci à celui qui pourra m'aider :D

12 réponses

Résumé de la discussion

Plusieurs échanges portent sur la validation d'une saisie utilisateur pour un chiffre, avec l'exigence que seul un signe '+' ou '-' puisse apparaître au tout début et jamais ailleurs. Des propositions évoquent aussi d'obliger ce signe à être unique et d'utiliser des contrôles supplémentaires pour rejeter les entrées mixtes, tout en préférant des solutions sans reformatage complexe. Les échanges abordent ensuite des détails pratiques comme l'utilisation de structures conditionnelles et l'éventuelle différence entre Python 2 et Python 3, ainsi que des conseils pour tester les entrées et déboguer. En parallèle, des explications ciblent l'emploi de fonctions comme all() et les compréhensions de liste pour vérifier que tous les caractères de la saisie appartiennent à l'ensemble autorisé.

Bobot (l’IA à votre service)
  1. SVP C'est pour un devoir :/
    0
    1. SVP c'est pour demain
      0
      1. Bonsoir

        Python c'est facile

        Premièrement, utilises-tu Python 2 ou 3 ?
        Deuxièement, sais-tu écrire l'instruction pour obtenir l'entrée de données , càd la saisie par le programme de ce que l'utilisateur va entrer ?

        Les deux questions sont liées: l'instruction diffère un peu entre Python 2 et Python 3
        0
        1. J'utilise Python 3, et oui Python c'est facile dés que on en connait plus que moi ^^ Et pour ce qui est de votre dernière question j'ai pas compris ^^ Mais si c'est ce que j'ai compris oui je sais le faire c'est :
          nom_variable=input("Chaîne de caractère")
          Voilà merci. :)
          0
          1. Voilà c'est ça. Bon maintenant mets cette instruction dans une boucle avec un print pour afficher chaque entrée
            0
            1. Non mais enfaîte c'est fait tout ça j'aurai juste besoin de comment faire pour détecter si le + ou le - n'est répéter qu'une fois et il faut qu'il soit obligatoirement au début.
              Voilà merci :)
              0
              1. Donne ce que tu as comme code., stp.

                Il y a une métode de chaîne qui compte combien de fois un chaîne se trouve dans une autre. La connais-tu ?
                0
              2. Oui c'est count.
                Mon code :
                "def saisie_decimal():

                saisie_correcte=True

                while saisie_correcte:

                saisie=input("entrer un nombre décimal:")
                saisie_correcte=False

                for c in saisie:
                if c not in "0123456789.-+":
                saisie_correcte=True

                return float(saisie)

                nombre=saisie_decimal()
                print(nombre)
                0
              3. Il y a un while, c'est bon

                Par contre to identifiant saisie_correcte n'est pas nécessaire. Tu écris

                while True:

                et quand ce sera bon, un break fera sortir de cette boucle while

                Il va falloir voir les conditions dans la boucle
                0
              4. def saisie_decimal():
                while True:
                saisie=input("entrer un nombre décimal:")
                cond = all( c in "0123456789.-+" for c in saisie)
                if cond:
                return float(saisie)nombre=saisie_decimal()print(nombre)

                Comme ça
                C'est un début, il faut vérifier d'autres conditions
                0
              5. Pardon, comme ça ce sera mieux:

                def saisie_decimal():
                while True:
                saisie=input("entrer un nombre décimal:")
                cond = all( c in "0123456789.-+" for c in saisie)
                if cond:
                return float(saisie)

                nombre=saisie_decimal()
                print(nombre)
                0
            2. Désoler mais je n'ai absolument pas compris à quoi sa faisait référence ^^ Ça répond a ce que j'ai demander ou c'est toute autre chose que tu es entrain de me montré ?
              0
              1. Exécute le code pour voir ce qu'il fait
                0
              2. Excuse moi, on peut enlever la ligne
                # -*- coding: cp1252 -*- 
                Elle ne sert q'en Python 2 quand il y a des accents dans le code
                Mais les scripts en Python 3 étant codés en UTF-8, ils acceptent automatiquement les caractères accentués sans avoir besoin de cette ligne
                Scuse, j'utilise Python 2. 7 de façon habituelle
                0
              3. Bon, alors ?

                Dans l'état actuel du code, quand on entre une saisie qui contient un autre caractère que l'un de ceux de la chaîne "0123456789.-+" ,
                l'objet
                diagnostic
                , qui a la valeur
                 True 
                avant de commencer la boucle de tests
                for c in "0123456789.-+"
                ,
                prend la valeur
                False
                .
                Et donc le
                return 
                n'est pas exécuté et ça repart pour un tour de la boucle while

                Mais il n'y a pas que cette boucle de tests à faire, il faut vérifier d'autres conditions.
                Et donc maintenat il faut ajouter ces conditions

                Bon, alors ?
                0
            3. Mais si j'ai bien compris ça reviens à faire exactement la même chose que mon programme de base ^^ Non ?
              0
              1. Non pas exactement la même chose puisque mon code marche tandis que le tien ne marche pas.
                Ca t'arrive de faire tourner un code pour voir ce qu'il fait ?

                Il est vrai que je cherche à obtenir un code qui réalise l'objectif que tu veux atteindre. Donc il y a des similitudes. Mais le tien ne marche pas
                J'obtiens ceci par exemple en entrant une mauvaise valeur:

                entrer un nombre décimal:12A4
                Traceback (most recent call last):
                File "C:\Python32\a effacer.py", line 12, in <module>
                nombre=saisie_decimal()
                File "C:\Python32\a effacer.py", line 9, in saisie_decimal
                return float(saisie)
                ValueError: could not convert string to float: '12A4'
                0
              2. La différence entre mon code et le tien, c'est que dans ton code tu écris
                saisie_correcte=False 

                avant la boucle
                 for c in saisie: 

                et tu changes avec
                saisie_correcte=True 
                quand l'un des caractères n'est pas bon

                tandis que dans mon code
                diagnostic = True

                avant la boucle
                et change avec
                diagnostic = False
                si l'un des caractères n'est pas bon

                Faut regarder les choses de près, pas de 3 mètres de haut
                0
            4. Bon, ça se traine et je dois partir.
              Voilà l'algorithme, il te reste à trouver comment écrire en Python les conditions qui sont en français:

              def saisie_decimal():
              while True:
              saisie=input("entrer un nombre décimal:")
              diagnostic = True
              for c in saisie:
              if c not in "0123456789.-+":
              diagnostic = False
              if premier caractère de saisie not in ('-','+'):
              diagnostic = False
              if (nombre de '-' est supérieur à 1) or \
              (nombre de '+' est supérieur à 1):
              diagnostic = False

              if diagnostic:
              return float(saisie)

              nombre=saisie_decimal()
              print(nombre)

              bonsoir
              0
              1. Bizarre parce que avec le miens lorsque je marque n'importe quoi (Des lettres + des chiffres, etc) et bien sa ne me fais pas l'erreur que tu rencontre je peux même te le prouver en te faisant un screen ! Donc avant de commencer à m'accabler de réflexions on ce calme!
                0
                1. Scuse, je vois ce qu'il y a eu.
                  Comme un con je me suis gourré d'indentation
                  pour l'instruction
                  return float(saisie) 

                  Au lieu de la mettre en dehors de la boucle
                  while
                  , je l'ai mise dedans , comme dans mon code.

                  C'est parce que lorsque je copie le code que tu as donné plus haut, et que je le colle dans un script, j'ai toutes les instructions qui s'écrivent les unes à la suite des autres sur la même ligne, et j'ai été obligé de faire des retours à la ligne pour remettre ton code en bonne ordre.
                  Sauf que je me suis gourré pour l'instruction return

                  En plus comme j'ai Python 2 et Python 3 installés tous les deux mais que j'utilise Python 2 habituellement, il faut que je fasse un micmac pour bien ouvrir les codes en Python 3 et pas Python 2.

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

                  Donc effectivement dans ces conditions, ton code marche.
                  Mais il est aberrant de faire prendre à l'objet
                  saisie_correcte
                  la valeur
                  True
                  quand justement la saisie n'est pas correcte. Ca a ajouté à ma confusion.

                  En faisant comme je fais dans mon code il n'y a pas besoin d'initialiser un objet à
                  True
                  ou
                  False
                  avant la boucle
                  while
                  , le programme rentre directement dans la boucle while et en ressort dès que l'instruction
                  return float(saisie)
                  est exécutée, ce qui se produit si diagnostic reste
                  True
                  tout le long des tests.
                  La logique de mon code, c'est de commencer les tests avec la valeur
                  True
                  pour
                  diagnostic
                  et il faut que cette valeur tienne le coup au travers de tous les tests pour pouvoir passer à l'instruction
                  return
                  .

                  Tu peux garder ton algorithme si tui préfères mais il n'est pas très logique, il y a plus de mal à le comprendre que le mien, je trouve. Mais tu fais comme tu veux.
                  Par contre tu pourras demander à ton prof de comparer et de te dire celui qu'il estime préférable, je ne me fais pas trop de souci.
                  0
              2. Et bien merci beaucoup désoler de m'être emballé...
                Merci beaucoup.
                0
                1. J'ai continué de penser au problème.

                  - Dans mon dernier post, j'ai écrit que ton code n'était pas très logique.
                  Ben si , il est logique, puisqu'il fonctionne bien. Point barre.

                  - J'ai écrit aussi qu'il y a plus de mal à le comprendre.
                  Ben non. J'aurais dû écrire: J'AI plus de mal à le comprendre. Tout simplement parce que j'étais habitué à envisager la solution sous l'angle de l'algorithme qui se trouve dans mon code. Mais ce n'est pas parce que je vois les choses avec ma subjectivité que c'est automatiquement la meilleure façon de faire.

                  - J'ai écrit aussi que tu devrais soumettre les deux codes pour comparaison à ton prof.
                  Mais c'est ce que j'ai fait moi même, pour voir s'il y avait vraiment des raisons déterminantes pour dire que c'est mon algorithme qui est le meilleur.
                  Ben y en a pas de déterminante.
                  Tu utilises un identifiant
                  saisie_correcte
                  qui est aberrant étant donné sa fonction. Mais ce n'est pas un point déterminant, on peut facilement changer cet identifiant pour un autre, par exemple c'est plus clair si on écrit ton code ainsi:

                  def saisie_decimal():
                  SAISIR=True
                  while SAISIR:
                  saisie=input("entrer un nombre décimal:")
                  SAISIR=False
                  for c in saisie:
                  if c not in "0123456789.-+":
                  SAISIR=True
                  return float(saisie)

                  Donc ce point n'étant pas déterminant, quels sont les autres ?

                  - Dans ton code, tu initialises
                  SAISIR
                  à False avant de faire les tests, moi j'initialise
                  diagnostic
                  à True. C'est pareil, ça fait une initialisation.
                  - Ensuite tu donnes la valeur booléenne inverse à
                  SAISIR
                  si les tests ne détectent pas une saisie correcte, je fais pareil pour
                  diagnostic
                  .
                  - Ensuite comment sort-on de la boucle while ?
                  Dans ton code c'est l'instruction
                  while
                  qui effectue un test sur
                  SAISIR
                  . Dans mon code je suis obligé de faire un test
                  if diagnostic
                  .
                  Dans les deux cas, il y a un if quelque part.
                  - Il y a juste que dans ton code tu es obligé d'initialiser la valeur de
                  SAISIR
                  avant la boucle while, moi pas. Mais ce n'est pas un point majeur.

                  Résultat: objectivement les deux code se valent.

                  Mais cet succession d'initialisation de valeur à True ou False, et de réaffectation de valeur False ou True ne me plaisait toujours pas.
                  Je me suis dit que ce qu'il faut faire, c'est que puisque l'instruction while implique un
                  if
                  caché, il faut mettre les tests dans ce
                  while
                  .
                  Donc j'ai trouvé le code suivant meilleur:

                  def saisir(x) :
                  for c in x:
                  if c not in "0123456789.-+":
                  return True
                  if x[0] not in '-+' \
                  or x.count('-')>1 \
                  or x.count('+')>1 :
                  return True

                  n = 'go'
                  while saisir(n):
                  n = input("entrer un nombre décimal:")


                  Mais en réfléchissant encore un peu, je me suis dit: si on vérifie en tout premier lieu que le premier caractère soit un
                  '-'
                  ou un
                  '+'
                  , alors le fait qu'il n'y ait pas d'autre '-' ou '+' dans la saisie nécessite qu'il n'y en ait pas dans les caractères au delà du premier. Il suffit de tester cette dernière condition pour éviter d'utiliser
                  count()
                  pour vérifier les nombres de '-' et de '+'.

                  def saisir(x) :
                  if x[0] not in '-+':
                  return True
                  for c in x[1:]:
                  if c not in "0123456789.":
                  return True

                  n = 'go'
                  while saisir(n):
                  n = input("entrer un nombre décimal:")

                  Mais si on appuie sur ENTER sans rien entrer on va avoir une erreur.
                  Donc il faut mettre
                   if x
                  comme premier test (c'est équivalent à
                  if x!=''
                  ).
                  Si en plus on utilise la fonction
                  any()
                  [c'est le contraire de la fonction
                  all() 
                  : elle renvoie False dès qu'elle trouve un élément équivalent à False dans la séquence qu'on lui passe en argument] alors on obtient:

                  def saisir(x) :
                  if not x \
                  or (x[0] not in '-+') \
                  or any(c not in "0123456789." for c in x[1:]):
                  return True

                  n = 'go'
                  while saisir(n):
                  n = input("entrer un nombre décimal:")

                  Enfin, comme j'estime inutile de tartiner les codes avec des fonctions qui ne se justifient pas, on peut tout aussi bien écrire tout simplement:

                  n = 'go'
                  while not n \
                  or (n[0] not in '-+') \
                  or any(c not in "0123456789." for c in n[1:]):
                  n = input("entrer un nombre décimal:")

                  print ('n==',n)

                  Simple Python, non ?

                  ===========================

                  Tout ceci étant dit, la vraie façon de vérifier qu'une saisie est une nombre décimal, c'est de laisser l'interpréteur Python vérifier lui-même s'il parvient à interpréter une chaîne saisie comme un nombre décimal, et pour le cas où il n'y arrive pas, on met l'essai dans une clause
                  try...except
                  qui gère ça toute seule:

                  while True:
                  n = input('Entrez : ')
                  try:
                  n = float(n)
                  break
                  except:
                  pass

                  print('n==',n)

                  Note qu'avec cet algorithme, il n'est pas nécessaire de spécifier le signe + pour les nombres positifs entrés.
                  0