web-dev-qa-db-fra.com

Comment écrire un script shell pour assigner des notes aux plages numériques?

Je veux créer un script qui vous invite à entrer un nombre compris entre 0 et 100, puis vous attribue une note basée sur ce nombre.

Je voudrais que dans bash.

PS3='Please enter your choice: '
(Something here)

do
case $
    "0-59")
        echo "F"
        ;;
    "60-69")
        echo "D"
        ;;
    "70-79")
        echo "C"
        ;;
    "Quit")
        break
        ;;
    *) echo invalid option;;
esac
done
19
Temple Pate

Concision vs lisibilité: un terrain d'entente

Comme vous l'avez vu, ce problème admet des solutions moyennement longues et quelque peu répétitives mais très lisibles ( terdon's et AB's bash réponses), ainsi que celles qui sont très courts mais non intuitifs et beaucoup moins auto-documentés (Tim's python et bash réponses et celles de Glenn Jackman réponse Perl ). Toutes ces approches sont précieuses.

Vous pouvez également résoudre ce problème avec du code au milieu du continuum entre compacité et lisibilité. Cette approche est presque aussi lisible que les solutions plus longues, avec une longueur plus proche des petites solutions ésotériques.

#!/usr/bin/env bash

read -erp 'Enter numeric grade (q to quit): '
case $REPLY in [qQ]) exit;; esac

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

for letter in F D C B A; do
    ((REPLY <= cutoffs[$letter])) && { echo $letter; exit; }
done
echo "Grade out of range."

Dans cette solution bash, j'ai inclus des lignes vides pour améliorer la lisibilité, mais vous pouvez les supprimer si vous le souhaitez encore plus court.

Les lignes vides incluses ne sont en réalité que légèrement plus courtes que ne variante compactée, encore assez lisible sur la solution bash de A.B. . Ses principaux avantages par rapport à cette méthode sont les suivants:

  • C'est plus intuitif.
  • Il est plus facile de changer les limites entre les notes (ou d'ajouter des notes supplémentaires).
  • Il accepte automatiquement les entrées avec les espaces de début et de fin (voir ci-dessous l'explication du fonctionnement de (())).

Ces trois avantages découlent du fait que cette méthode utilise les entrées de l'utilisateur sous forme de données numériques plutôt qu'en examinant manuellement les chiffres qui le composent.

Comment ça marche

  1. Lire l'entrée de l'utilisateur. Laissez-les utiliser les touches fléchées pour se déplacer dans le texte qu'ils ont saisi (-e) et n'interprétez pas \ comme un caractère d'échappement (-r).
    Ce script n'est pas une solution riche en fonctionnalités (voir ci-dessous pour un raffinement), mais ces fonctionnalités utiles ne font que l'allonger de deux caractères. Je recommande de toujours utiliser -r avec read, à moins que vous ne sachiez que vous devez laisser l'utilisateur fournir des échappements \.
  2. Si l'utilisateur a écrit q ou Q, quittez.
  3. Créez un associatiftablea ( declare -A ). Remplissez-le avec la note numérique la plus élevée associée à chaque note.
  4. Boucle la lettre, de la plus basse à la plus haute, en vérifiant si le nombre fourni par l'utilisateur est suffisamment bas pour se situer dans la plage numérique de chaque lettre.
    Avec l'évaluation arithmétique (()), il n'est pas nécessaire d'étendre les noms de variable avec $. (Dans la plupart des autres situations, si vous souhaitez utiliser la valeur d'une variable à la place de son nom, vous devez le faire .)
  5. S'il se situe dans la plage, imprimez la note et exit .
    Par souci de brièveté, j’utilise les opérateurs de court-circuit et (&&) plutôt que if-then.
  6. Si la boucle se termine et qu'aucune plage n'a été mise en correspondance, supposez que le nombre entré est trop élevé (plus de 100) et informez l'utilisateur qu'il était hors limites.

Comment cela se comporte, avec une entrée étrange

Comme les autres solutions courtes publiées, ce script ne vérifie pas l'entrée avant de supposer qu'il s'agit d'un nombre. L'évaluation arithmétique ((())) supprime automatiquement les espaces de début et de fin, donc c'est pas de problème, mais:

  • Les entrées qui ne ressemblent pas du tout à un nombre sont interprétées comme 0.
  • Avec une entrée qui ressemble à un nombre (c'est-à-dire si elle commence par un chiffre) mais qui contient des caractères non valides, le script génère des erreurs.
  • Une entrée à plusieurs chiffres commençant par 0 est interprétée comme étant dans octal . Par exemple, le script vous dira que 77 est un C, tandis que 077 est un D. Bien que certains utilisateurs le souhaitent, cela n’est probablement pas le cas et cela peut créer une confusion.
  • Du côté positif, quand une expression arithmétique est donnée, ce script la simplifie automatiquement et détermine la note associée. Par exemple, il vous dira que 320/4 est un B.

Une version complète et complète

Pour ces raisons, vous voudrez peut-être utiliser quelque chose comme ce script développé, qui vérifie que la saisie est bonne et comprend certaines autres améliorations.

#!/usr/bin/env bash
shopt -s extglob

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in  # allow leading/trailing spaces, but not octal (e.g. "03") 
        *( )@([1-9]*([0-9])|+(0))*( )) ;;
        *( )[qQ]?([uU][iI][tT])*( )) exit;;
        *) echo "I don't understand that number."; continue;;
    esac

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

C'est toujours une solution assez compacte.

Quelles sont les fonctionnalités ajoutées?

Les points clés de ce script développé sont:

  • Validation d'entrée. le script de terdon vérifie l'entrée avec if [[ ! $response =~ ^[0-9]*$ ]] ..., je montre donc une autre façon, qui sacrifie un peu de brièveté mais est plus robuste, permettant à l'utilisateur de saisir des espaces de début et de fin et refusant d'autoriser une expression pouvant être ou non destiné à être octal (sauf si c'est zéro).
  • J'ai utilisé case avec étendu globbing au lieu de [[ avec le =~ correspondance d'expression régulière opérateur (comme dans réponse de terdon ). J'ai fait cela pour montrer que (et comment) cela peut aussi être fait de cette façon. Les globes et les expressions rationnelles sont deux façons de spécifier des modèles qui correspondent au texte. L'une ou l'autre méthode convient parfaitement pour cette application.
  • Comme script bash de A.B. , j'ai tout enfermé dans une boucle externe (sauf la création initiale du tableau cutoffs). Il demande des chiffres et donne les notes correspondantes tant que le terminal est disponible et que l'utilisateur ne lui a pas demandé de quitter. À en juger par la variable do...done autour du code de votre question, il semble que vous le souhaitiez.
  • Pour faciliter la tâche, j'accepte toute variante de q ou quit qui respecte la casse.

Ce script utilise quelques constructions qui peuvent ne pas être familières aux novices; ils sont détaillés ci-dessous.

Explication: Utilisation de continue

Lorsque je veux ignorer le reste du corps de la boucle while extérieure, j'utilise la commande continue. Cela le ramène au sommet de la boucle, pour lire plus d'entrées et exécuter une autre itération.

La première fois que je fais cela, la seule boucle dans laquelle je me trouve est la boucle externe while. Je peux donc appeler continue sans argument. (Je suis dans une construction case, mais cela n’affecte pas le fonctionnement de break ou continue.)

        *) echo "I don't understand that number."; continue;;

La deuxième fois, cependant, je suis dans une boucle intérieure for qui est elle-même imbriquée dans la boucle extérieure while. Si j'utilisais continue sans argument, cela équivaudrait à continue 1 et continuerait la boucle for intérieure au lieu de la boucle while extérieure.

        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }

Donc, dans ce cas, j’utilise continue 2 pour que bash trouve et continue la deuxième boucle.

Explication: case étiquettes avec des taches

Je n'utilise pas case pour déterminer dans quelle lettre bin un nombre entre (comme dans réponse bash de A.B. ). Mais j’utilise case pour décider si l’opération de l’utilisateur doit être prise en compte:

  • un numéro valide, *( )@([1-9]*([0-9])|+(0))*( )
  • la commande quit, *( )[qQ]?([uU][iI][tT])*( )
  • toute autre chose (et donc une entrée invalide), *

Ce sont globes de shell .

  • Chacune est suivie d'un ) auquel aucun ( d'ouverture ne correspond, ce qui correspond à la syntaxe de case pour séparer un modèle des commandes qui s'exécutent lorsqu'il correspond.
  • ;; est la syntaxe de case pour indiquer la fin des commandes à exécuter pour une correspondance de cas particulier (et qu'aucun cas ultérieur ne doit être testé après les avoir exécutées).

L'environnement de shell ordinaire fournit * pour correspondre à zéro ou plusieurs caractères, ? pour correspondre exactement à un caractère et les classes/plages de caractères entre []. Mais j'utilise extended globbing , qui va au-delà de cela. La navigation étendue est activée par défaut lors de l'utilisation interactive de bash, mais elle est désactivée par défaut lors de l'exécution d'un script. La commande shopt -s extglob en haut du script l’active.

Explication: Globbing étendu

*( )@([1-9]*([0-9])|+(0))*( ), qui vérifie la saisie numérique , correspond à une séquence de:

  • Zéro ou plusieurs espaces (*( )). La construction *() correspond à zéro ou plus du motif dans les parenthèses, ce qui est juste un espace.
    Il existe en fait deux types d'espaces horizontaux, d'espaces et de tabulations, et il est souvent souhaitable de faire correspondre les tabulations également. Mais je ne m'inquiète pas de cela ici, car ce script est écrit pour une entrée manuelle et interactive, et l'indicateur -e sur read permet GNU readline. Cela permet à l'utilisateur de se déplacer d'avant en arrière dans son texte à l'aide des touches fléchées gauche et droite, mais cela a pour effet secondaire d'empêcher généralement la saisie littérale des tabulations.
  • Une occurrence (@()) de (|):
    • Un chiffre différent de zéro ([1-9]) suivi de zéro ou plus (*()) de tout chiffre ([0-9]).
    • Un ou plusieurs (+()) de 0.
  • Zéro ou plusieurs espaces (*( )), à nouveau.

*( )[qQ]?([uU][iI][tT])*( ), qui vérifie la commande de sortie , correspond à une séquence de:

  • Zéro ou plusieurs espaces (*( )).
  • q ou Q ([qQ]).
  • Facultativement - c’est-à-dire zéro ou une occurrence (?()) - sur:
    • u ou U ([uU]) suivi de i ou I ([iI]) suivi de t ou T ([tT]).
  • Zéro ou plusieurs espaces (*( )), à nouveau.

Variante: validation de l'entrée avec une expression régulière étendue

Si vous préférez tester l'entrée de l'utilisateur par rapport à une expression régulière plutôt qu'à un glob Shell, vous préférerez peut-être utiliser cette version, qui fonctionne de la même manière, mais utilise [[ et =~ (comme dans terdon's answer ) au lieu de case et étendu globbing.

#!/usr/bin/env bash
shopt -s nocasematch

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    # allow leading/trailing spaces, but not octal (e.g., "03")
    if [[ ! $REPLY =~ ^\ *([1-9][0-9]*|0+)\ *$ ]]; then
        [[ $REPLY =~ ^\ *q(uit)?\ *$ ]] && exit
        echo "I don't understand that number."; continue
    fi

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

Les avantages possibles de cette approche sont les suivants:

  • Dans ce cas particulier, la syntaxe est un peu plus simple, du moins dans le deuxième motif, où je vérifie la commande quit. En effet, j’ai pu définir l’option nocasematch Shell, puis toutes les variantes de cas de q et quit ont été automatiquement traitées.

    C'est ce que fait la commande shopt -s nocasematch. La commande shopt -s extglob est omise car la suppression n'est pas utilisée dans cette version.

  • Les habiletés d'expression régulières sont plus courantes que la maîtrise des extensions de bash.

Explication: Expressions régulières

En ce qui concerne les modèles spécifiés à droite de l'opérateur =~, voici comment fonctionnent ces expressions régulières.

^\ *([1-9][0-9]*|0+)\ *$, qui vérifie la saisie numérique , correspond à une séquence de:

  • Le début - c’est-à-dire bord gauche - de la ligne (^).
  • Zéro ou plus (*, postfixe appliqué). Normalement, un espace n'a pas besoin d'être échappé \- dans une expression régulière, mais ceci est nécessaire avec [[ pour éviter une erreur de syntaxe.
  • Une sous-chaîne (()) qui est l'un ou l'autre (|) parmi:
    • [1-9][0-9]*: un chiffre différent de zéro ([1-9]) suivi de zéro ou plus (*, postfixe appliqué) d'un chiffre quelconque ([0-9]).
    • 0+: un ou plusieurs (+, postfixe appliqué) de 0.
  • Zéro ou plusieurs espaces (\ *), comme avant.
  • L’extrémité - c’est-à-dire, bord droit - de la ligne ($).

Contrairement aux étiquettes case, qui correspondent à l'expression entière à tester, =~ renvoie true si une partie quelconque de son expression de gauche correspond au modèle donné en tant qu'expression de droite. C'est pourquoi les ancres ^ et $, spécifiant le début et la fin de la ligne, sont nécessaires ici et ne correspondent syntaxiquement à rien qui apparaisse dans la méthode avec case et extglob.

Les parenthèses sont nécessaires pour que ^ et $ soient liés à la disjonction de [1-9][0-9]* et 0+. Sinon, ce serait la disjonction de ^[1-9][0-9]* et 0+$, et correspondrait à toute entrée commençant par un chiffre différent de zéro ou se terminant par un 0 (ou les deux, pouvant toujours inclure des non-chiffres entre les deux). ).

^\ *q(uit)?\ *$, qui vérifie la commande de sortie , correspond à une séquence de:

  • Le début de la ligne (^).
  • Zéro ou plusieurs espaces (\ *, voir l'explication ci-dessus).
  • La lettre q. Ou Q, puisque shopt nocasematch est activé.
  • Facultativement - c'est-à-dire, zéro ou une occurrence (postfix ?) - de la sous-chaîne (()):
    • u, suivi de i, suivi de t. Ou, puisque shopt nocasematch est activé, u peut être U; indépendamment, i peut être I; et indépendamment, t peut être T. (C’est-à-dire que les possibilités sont non limitées à uit et UIT.)
  • Zéro ou plusieurs espaces à nouveau (\ *).
  • La fin de la ligne ($).
20
Eliah Kagan

Vous avez déjà l'idée de base. Si vous voulez coder ceci dans bash(ce qui est un choix raisonnable puisqu'il s'agit du shell par défaut sous Ubuntu et la plupart des autres systèmes Linux), vous ne pouvez pas utiliser casecar il ne comprend pas les plages. À la place, vous pouvez utiliser ifname __/elsename__:

#!/usr/bin/env bash

read -p "Please enter your choice: " response

## If the response given did not consist entirely of digits
if [[ ! $response =~ ^[0-9]*$ ]]
then
    ## If it was Quit or quit, exit
    [[ $response =~ [Qq]uit ]] && exit
    ## If it wasn't quit or Quit but wasn't a number either,
    ## print an error message and quit.
    echo "Please enter a number between 0 and 100 or \"quit\" to exit" && exit
fi
## Process the other choices
if [ $response -le 59 ]
then
    echo "F"
Elif [ $response -le 69 ]
then
    echo "D"
Elif  [ $response -le 79 ]
then
    echo "C"
Elif  [ $response -le 89 ]
then
    echo "B"
Elif [ $response -le 100 ]
then
    echo "A"
Elif [ $response -gt 100 ]
then
    echo "Please enter a number between 0 and 100"
     exit
fi
23
terdon
#!/bin/bash

while true
do
  read -p "Please enter your choice: " choice

  case "$choice"
   in
      [0-9]|[1-5][0-9])
          echo "F"
          ;;
      6[0-9])
          echo "D"
          ;;
      7[0-9])
          echo "C"
          ;;
      8[0-9])
          echo "B"
          ;;
      9[0-9]|100)
          echo "A"
          ;;
      [Qq])
          exit 0
          ;;
      *) echo "Only numbers between 0..100, q for quit"
          ;;
  esac
done

et une version plus compacte (Thx @ EliahKagan ):

#!/usr/bin/env bash

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in
        [0-9]|[1-5][0-9])   echo F ;;
        6[0-9])             echo D ;;
        7[0-9])             echo C ;;
        8[0-9])             echo B ;;
        9[0-9]|100)         echo A ;;

        [Qq])               exit ;;
        *)                  echo 'Only numbers between 0..100, q for quit' ;;
    esac
done
12
A.B.

Toutes les installations Ubuntu ont Python, donc voici un python scénario bon mot. Si vous avez besoin que ce soit en bash, j'ai aussi écrit l'équivalent sous forme de script shell .

print (chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1]))))

Pour l’exécuter, enregistrez-le dans un fichier (par exemple, grade.py), puis exécutez-le dans le terminal avec ceci:

python grade.py

Voici ce que vous verrez:

Enter the number: 65
E

Comment cela marche-t-il?

  1. Prendre une entrée - 65.
  2. Ajoutez un 0 au début - 065.
  3. Supprimez le dernier caractère - 06.
  4. 75 soustrayez ce nombre - 70.
  5. Convertir en lettre (A est 65, B est 66) - Ename__.
  6. Imprimez-le - Ename__.
9
Tim

Voici ma solution semi - ésotérique bash, qui remplit un tableau avec 101 entrées, puis compare les entrées utilisateur à celles-ci. Même pour une utilisation dans le monde réel, c'est raisonnable - si vous avez besoin d'excellentes performances, vous n'utiliserez pas bash, et une centaine (ou plus) de tâches restent rapides. Mais cela cesserait d'être raisonnable s'il était étendu à une gamme beaucoup plus grande (comme un million).

#!/usr/bin/env bash
p(){ for i in `seq $2 $3`; do g[$i]=$1; done; }
p A 90 100; p B 80 89; p C 70 79; p D 60 69; p F 0 59
while read -r n && [[ ! $n =~ ^[qQ] ]]; do echo ${g[$n]}; done

Avantages:

  • Ce n'est pas vraiment si ésotérique. Bien que ce soit plus long que les solutions les plus courtes, et pas tout à fait aussi auto-documenté que les solutions plus longues ... c'est raisonnablement auto-documentant , tout en restant résolument du tout petit.
  • Il permet une modification facile pour modifier les plages de notes ou ajouter/supprimer des notes.
  • Il fonctionne dans une boucle et se ferme le qname__, quitname__, ou tout ce qui commence par qname __/Qname__.
  • Répertorie en premier les grades les plus élevés, pour vous aider à penser positivement. :)
  • Hmm, cela fait le travail, continue à avoir un sens même après l'avoir regardé, et a les fonctionnalités essentielles. Vous pouvez réellement utiliser ceci!

Désavantages:

  • Cela vous donne un F lorsque vous saisissez des entrées non numériques ... mais ce n'est pas si grave, n'est-ce pas? Si vous donnez un numéro où un nombre est nécessaire, vous méritez peut-être un F!
  • Les entrées ambiguës, éventuellement octales, sont traitées comme telles (puisque gest un tableau indexé à une dimension ). Comme le dit le vieil adage, "Ce n'est pas un bug, c'est une fonctionnalité!" Peut-être.
  • Une entrée en dehors de la plage ou non numérotée entraîne l'impression d'une ligne vide. Cependant, il n’ya rien de mal à cela: cela vous indique quelle note correspond à votre entrée, et pour une entrée erronée, il n’en existe pas.
  • Mettez un nombre négatif et ... eh bien, appelez-le un oeuf de Pâques .
  • Encore beaucoup plus long que solution de Tim python . Oui, je ne peux pas vraiment faire tourner ça pour avoir l'air d'un avantage.

Un peu cool, hein? (Eh bien, je pense que oui.)

Comment ça marche

  1. La fonction p p opose un tableau indexé numériquement gof g rades, aux index allant du premier argument au deuxième, avec la valeur (lettre) donnée dans le troisième argument.
  2. pest appelé pour chaque note, afin de définir sa plage numérique.
  3. Continuez à lire les entrées utilisateur tant qu'elles sont disponibles et qu'elles ne commencent pas par q(ou Qname__), vérifiez le tableau gpour lequel la note correspond au nombre saisi et imprimez cette lettre.
6
Eliah Kagan

Après le rendant dans Python 2 , j'ai décidé de le faire en bash.

#! /bin/bash

read -p "Enter the number: " i
i=0$i
x=$((10#${i::-1}))
printf "\x$(printf %x $((11-($x>5?$x:5)+64)))\n"

Pour l’exécuter, enregistrez-le dans un fichier (par exemple, grade.sh), rendez-le exécutable avec chmod +x grade.sh, puis exécutez-le avec ./grade.sh.

Voici ce que vous verrez:

Enter the number: 65
E

Comment cela marche-t-il?

  1. Prendre une entrée - 65.
  2. Ajoutez un 0 au début - 065 (et le 10# le conserve en base 10).
  3. Supprimez le dernier caractère - 06.
  4. 75 soustrayez ce nombre - 70.
  5. Convertir en lettre (A est 65, B est 66) - Ename__.
  6. Imprimez-le - Ename__.
6
Tim

Et voici ma version awk:

awk '{
  if($_ <= 100 && $_ >= 0) {
      sub(/^([0-9]|[1-5][0-9])$/, "F", $_);
      sub(/^(6[0-9])$/, "D", $_);
      sub(/^(7[0-9])$/, "C", $_);
      sub(/^(8[0-9])$/, "B", $_);
      sub(/^(9[0-9]|100)$/, "A", $_);
      print
    }
    else {
      print "Only numbers between 0..100"
    }
}' -

ou comme one-liner:

awk '{if($_ <= 100 && $_ >= 0) { sub(/^([0-9]|[1-5][0-9])$/, "F", $_); sub(/^(6[0-9])$/, "D", $_); sub(/^(7[0-9])$/, "C", $_); sub(/^(8[0-9])$/, "B", $_);sub(/^(9[0-9]|100)$/, "A", $_);   print} else { print "Only numbers between 0..100"}}' -
5
A.B.

Voici une autre réponse "ésotérique"

Perl -E '
    print "number: "; 
    $n = <>; 
    say qw/A A B C D E F F F F F/[11-($n+1)/10]
       if $n=~/^\s*\d/ and 0<=$n and $n<=100
'

Explication

  • Perl -E: le -E, comme -e, permet de transmettre un script en tant qu'argument de ligne de commande. C'est une façon de faire fonctionner les one-liners Perl. Contrairement à -e, -E active également toutes les fonctions facultatives (telles que say, qui est fondamentalement un print avec une nouvelle ligne de fin.).
  • print "number: ";: invite l'utilisateur à entrer un nombre.
  • $n = <>;: enregistrez ce nombre sous le nom $n.

La partie suivante doit être un peu décomposée. qw/string/ évalue une liste en cassant string à l'espace. Donc, qw/A A B C D E F F F F F/ est en fait cette liste:

0 : A
1 : A
2 : B
3 : C
4 : D
5 : E
6 : F
7 : F
8 : F
9 : F
10 : F

Donc, say qw/A A B C D E F F F F F/[11-($n+1)/10] est équivalent à

my @F=("A","A","B","C","D","E","F","F","F","F","F");
print "$F[11-($n+1)/10]\n"

Maintenant, Perl permet d'utiliser des indices négatifs pour récupérer des éléments comptant à partir de la fin du tableau. Par exemple, $arrray[-1] affichera le dernier élément du tableau. De plus, les indices de tableau à virgule flottante (par exemple 10.7) sont automatiquement tronqués au nombre entier immédiatement inférieur (10.7, ou 10.3 ou peu importe ce qui devient 10).

Le résultat de tout cela est que l'index 11-($n+1)/10 correspond toujours à l'élément approprié (grade) du tableau.

4
glenn jackman

Bien que vous ayez demandé une solution bash, je pense qu'en python, cela peut être fait de manière élégante et rapide. Couvrant à la fois les erreurs de manipulation en cas de saisie incorrecte et la "conversion" d'un nombre compris entre 0 et 100 en lettres de A à F (ou tout autre):

#!/usr/bin/env python3
try:
    n = int(input("number: ")); n = n if n>0 else ""
    print("FEDCBA"[[n>=f for f in [50,60,70,80,90,101]].count(True)])
except:
    print("invalid input")

Explication

  1. Nous devons d’abord obtenir le numéro de l’utilisateur:

    n = int(input("number: "))
    
  2. Nous testons la validité de ce numéro pour un certain nombre de conditions:

    n>=50, n>=60, n>=70, n>=80, n>=90
    

    Pour chacun de ces tests, le résultat sera soit False, soit True. Donc (compresser un peu le code):

    [n>=f for f in [50,60,70,80,90]].count(True)]
    

    produira un chiffre de 0 à 5

  3. Par la suite, nous pouvons utiliser cette figure comme index pour une chaîne, afin de produire un caractère en sortie, par ex.

    "ABCDEF"[3] 
    

    affichera "D" (puisque le premier caractère = "A")

  4. Le 101 additionnel à la liste doit générer une erreur (index) au cas où le nombre dépasserait 100, puisque "ABCDEF"[6] n'existe pas. Il en va de même pour n = n if n>=0 else "", ce qui créera une erreur (valeur) si un nombre inférieur à 0 est entré
    Dans ces cas, ainsi que si l'entrée n'est pas un chiffre, le résultat sera:

    invalid input
    

Les tests:

number: 10
F

number: 50
E

number: 60
D

number: 70
C

number: 80
B

number: 90
A

number: 110
invalid input

number: -10
invalid input

number: Monkey
invalid input
1
Jacob Vlijm