<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<question type="category">
  <category>
    <text>$course$/QCM de NSI/Première/Fichiers CSV</text>
  </category>
  <info format="html">
    <text><![CDATA[<p>Format CSV (Comma Separated Values), séparateurs (virgule,<br/>
point-virgule, tabulation), lecture et écriture avec le<br/>
module <code>csv</code>, en-tête, encodage UTF-8, conversion des<br/>
types, manipulations courantes.</p>]]></text>
  </info>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q01 : Que signifie CSV ?</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que signifie l'acronyme <strong>CSV</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le CSV est un standard très répandu pour les échanges<br/>
de données entre tableurs, bases de données et<br/>
programmes. Sa simplicité (texte brut, ligne par<br/>
ligne) en fait un format universel.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Comma Separated Values</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est un format texte simple<br/>
dans lequel chaque ligne est un enregistrement<br/>
et les champs sont séparés par un délimiteur<br/>
(souvent une virgule, parfois un point-virgule<br/>
ou une tabulation).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Computer System Variables</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport. C'est un format de<br/>
fichier de données tabulaires.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Compressed Storage Vector</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CSV n'est pas un format compressé.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Centered Spreadsheet View</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une vue de tableur, c'est<br/>
un format texte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q02 : Structure d'un CSV</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la structure de base d'un fichier CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Exemple typique : la première ligne <code>nom,age,ville</code><br/>
définit les colonnes ; les lignes suivantes<br/>
contiennent les valeurs correspondantes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un fichier XML structuré par balises</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CSV n'a pas de balises, juste des<br/>
séparateurs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un format de type JSON aux structures imbriquées</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec JSON. CSV est plat.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un fichier texte, un enregistrement par ligne, champs délimités</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la première ligne contient<br/>
souvent les noms des colonnes (en-tête), puis<br/>
chaque ligne suivante représente une entrée du<br/>
jeu de données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un fichier binaire avec en-tête et indexation</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CSV est un format <strong>texte</strong>, pas<br/>
binaire. Il s'ouvre avec n'importe quel éditeur<br/>
de texte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q03 : Séparateur en France</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi en France utilise-t-on souvent le <strong>point-virgule</strong><br/>
<code>;</code> comme séparateur dans les fichiers CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>D'autres séparateurs sont possibles : tabulation<br/>
(TSV), barre verticale <code>|</code>, etc. Le module <code>csv</code> de<br/>
Python permet de spécifier le délimiteur via<br/>
<code>delimiter=";"</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce qu'une norme ISO officielle l'impose strictement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CSV n'est pas strictement normé. Le<br/>
choix du séparateur dépend des conventions<br/>
locales.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que les fichiers seraient sinon trop volumineux</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport avec la taille.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Parce que la virgule sert de séparateur décimal en français, créant un conflit</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>1,5;Paris</code> est sans ambiguïté,<br/>
mais <code>1,5,Paris</code> ne l'est pas (s'agit-il d'un<br/>
ou deux champs ?). Excel et LibreOffice en<br/>
version française utilisent donc <code>;</code> par défaut.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Parce que le point-virgule est plus rapide à taper</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas une raison de saisie.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q04 : Ligne d'en-tête</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>À quoi sert la <strong>première ligne</strong> d'un fichier CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'en-tête est une <strong>convention</strong>, pas une<br/>
obligation. Certains CSV n'en ont pas (par exemple<br/>
des exports machine sans description). Il faut alors<br/>
le savoir avant de lire le fichier.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle indique la taille du fichier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>La taille d'un fichier<br/>
se mesure en octets et<br/>
se lit dans le système<br/>
de fichiers, pas dans<br/>
son contenu. L'en-tête<br/>
d'un CSV donne les noms<br/>
des colonnes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle contient toujours les données du premier enregistrement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : par convention, la première ligne<br/>
contient le plus souvent un <strong>en-tête</strong>, pas<br/>
des données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Elle est obligatoirement vide</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : au contraire, elle contient<br/>
généralement les noms de colonnes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Elle contient les noms des colonnes (en-tête)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'usage le plus répandu.<br/>
Les programmes (et <code>csv.DictReader</code>) s'en<br/>
servent pour donner un nom à chaque champ.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q05 : Extension de fichier</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est l'extension habituelle d'un fichier CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'extension <code>.csv</code> est reconnue par Excel,<br/>
LibreOffice Calc, Google Sheets et la plupart des<br/>
langages de programmation, qui peuvent<br/>
automatiquement proposer un import.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>.json</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : JSON est un autre format de données<br/>
(hiérarchique).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>.txt</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : techniquement possible (CSV est du<br/>
texte), mais l'extension conventionnelle est<br/>
différente.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>.csv</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est l'extension standard,<br/>
reconnue par les tableurs et les outils de<br/>
traitement de données.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>.xlsx</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>.xlsx</code> est le format propriétaire<br/>
d'Excel (binaire compressé), pas CSV.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q06 : Lecture sans le module csv</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Sans utiliser le module <code>csv</code>, comment peut-on lire<br/>
un fichier CSV simple en Python ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Cette approche a des limites : elle ne gère pas les<br/>
champs entre guillemets, les sauts de ligne dans<br/>
les champs, ou les caractères d'échappement. Pour<br/>
cela, mieux vaut le module <code>csv</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec <code>open()</code> puis <code>.split('\n')</code> sur chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque ligne parcourue ne contient qu'un saut de ligne, à sa fin. Sur <code>"Alice,17\n"</code>, <code>split('\n')</code> renvoie <code>['Alice,17', '']</code> : les champs ne sont pas séparés.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec <code>readlines()</code> seul, qui sépare déjà les champs</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>readlines()</code> découpe le fichier en<br/>
<strong>lignes</strong>, pas en champs ; il faut encore<br/>
séparer chaque ligne par le délimiteur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Avec <code>open()</code> puis <code>.split(',')</code> sur chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on ouvre le fichier en lecture<br/>
et on parcourt ligne par ligne, en séparant<br/>
chaque ligne par le délimiteur. Cela marche<br/>
pour les CSV simples mais échoue avec les<br/>
champs contenant le délimiteur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Avec <code>open()</code> puis <code>.strip(',')</code> sur chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>strip(',')</code> ne retire que les virgules<br/>
situées en début et en fin de ligne ; sur<br/>
<code>"Alice,17"</code>, il renvoie <code>"Alice,17"</code> inchangé.<br/>
La ligne n'est pas découpée en champs.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q07 : Module standard</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel module de la bibliothèque standard de Python<br/>
facilite la manipulation des fichiers CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Le module <code>csv</code> fait partie de la bibliothèque<br/>
standard (livré avec Python). Aucune installation<br/>
n'est nécessaire.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>csv</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>import csv</code> donne accès à <code>csv.reader</code> et <code>csv.DictReader</code>, qui découpent chaque ligne du fichier en champs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>math</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module <code>math</code> fournit des fonctions mathématiques comme <code>sqrt</code> ; il ne lit aucun fichier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>random</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module <code>random</code> produit des nombres au hasard ; il ne sait rien du format CSV.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>time</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module <code>time</code> sert à mesurer une durée ou à attendre, pas à lire un fichier.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q08 : Encodage recommandé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quel <strong>encodage</strong> est aujourd'hui recommandé pour les<br/>
fichiers CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>En Python, on précise l'encodage à l'ouverture :<br/>
<code>open("data.csv", encoding="utf-8")</code>. Si on omet<br/>
cet argument, Python utilise l'encodage par défaut<br/>
du système, ce qui peut poser problème entre<br/>
Windows et Linux.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>ISO-8859-1 uniquement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Encodage ancien (Latin-1), encore courant en<br/>
Europe mais limité à 256 caractères. À éviter<br/>
pour de nouveaux projets.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Binaire compressé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un CSV est du texte, pas du binaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>UTF-8</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : UTF-8 supporte tous les<br/>
caractères Unicode (français, chinois, emojis...).<br/>
C'est l'encodage standard moderne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>ASCII pur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ASCII ne couvre pas les caractères<br/>
accentués (é, à, ç...), inutilisables en<br/>
français.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q09 : Itération avec csv.reader</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que renvoie <code>csv.reader(f)</code> lorsqu'on l'utilise dans<br/>
une boucle <code>for ligne in csv.reader(f):</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Penser à convertir les valeurs numériques avec<br/>
<code>int()</code> ou <code>float()</code> avant tout calcul. CSV est<br/>
texte : <code>"17" + 1</code> ne fonctionnera pas.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un dictionnaire <code>{nom_colonne: valeur}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est ce que renvoie <code>csv.DictReader</code>,<br/>
pas <code>csv.reader</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une chaîne de caractères pour chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : pour avoir une chaîne, il suffirait<br/>
de boucler directement sur le fichier <code>f</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Un tuple immuable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est une liste mutable.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Une liste des champs de chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : chaque itération produit une<br/>
liste comme <code>["Alice", "17", "Lyon"]</code>. Tous les<br/>
éléments sont des chaînes (il faut convertir<br/>
si l'on veut des entiers).</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q10 : Une cellule de la table chargée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le fichier <code>notes.csv</code> contient :<br/>
<pre><code>nom,note
Ali,12
Zoe,15</code></pre><br/>
On le charge dans une table :<br/>
<pre><code>import csv
table = []
with open("notes.csv", encoding="utf-8") as f:
    for ligne in csv.reader(f):
        table.append(ligne)</code></pre><br/>
Que vaut <code>table[2][1]</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une table importée ainsi est un tableau doublement indexé : <code>table[i][j]</code> désigne la valeur de la ligne <code>i</code> et de la colonne <code>j</code>. L'en-tête compte comme une ligne, et chaque valeur reste une chaîne tant qu'on ne la convertit pas.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>15</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module <code>csv</code> ne convertit rien, toutes les valeurs lues sont des chaînes. Il faudrait écrire <code>int(table[2][1])</code> pour obtenir l'entier $15$.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>'12'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu oublies que l'en-tête est rangé dans la table, à l'indice $0$. La ligne de Ali est <code>table[1]</code>, celle de Zoe <code>table[2]</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>'15'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la ligne d'en-tête occupe l'indice $0$, donc <code>table[2]</code> vaut <code>['Zoe', '15']</code>, et son élément d'indice $1$ est la chaîne <code>'15'</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>'Zoe'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : dans chaque ligne aussi, les indices commencent à $0$. <code>table[2][0]</code> vaut <code>'Zoe'</code>, et <code>table[2][1]</code> désigne la colonne suivante, celle de la note.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q11 : Différence reader / DictReader</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle est la différence entre <code>csv.reader</code> et<br/>
<code>csv.DictReader</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p><code>DictReader</code> est généralement préférable quand le<br/>
fichier a un en-tête : le code est plus auto-documenté<br/>
(<code>ligne["age"]</code> plutôt que <code>ligne[2]</code>).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La classe <code>DictReader</code> lit nettement plus vite les fichiers</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la performance n'est pas la<br/>
différence essentielle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La fonction <code>reader</code> n'existe plus en Python 3</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : elle existe parfaitement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>reader</code> produit des listes, <code>DictReader</code> des dictionnaires</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>DictReader</code> consomme la<br/>
première ligne comme en-tête et permet<br/>
ensuite d'écrire <code>ligne["nom"]</code> au lieu de<br/>
<code>ligne[0]</code>. Plus lisible et robuste si l'ordre<br/>
des colonnes change.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>DictReader</code> ignore la ligne d'en-tête du fichier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est l'inverse, il <strong>utilise</strong><br/>
l'en-tête pour nommer les colonnes.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q12 : Conversion de types</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Après lecture, on obtient <code>ligne = ["Alice", "17"]</code>.<br/>
Comment obtenir un âge utilisable comme nombre ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Toujours convertir explicitement : <code>int()</code>,<br/>
<code>float()</code>, <code>bool()</code> selon le besoin. Penser aussi<br/>
au cas où la cellule est vide (chaîne <code>""</code>), qui<br/>
provoquerait <code>ValueError</code> avec <code>int()</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>age = int(ligne[1])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>int()</code> convertit la chaîne<br/>
<code>"17"</code> en entier <code>17</code>, utilisable dans des<br/>
calculs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>age = list(ligne[1])</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>list("17")</code> donne <code>['1', '7']</code>, pas<br/>
un entier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>age = ligne[1].number()</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la méthode <code>.number()</code> n'existe pas<br/>
sur les chaînes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>age = ligne[1]</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>age</code> reste une <strong>chaîne</strong>. Faire<br/>
<code>age + 1</code> lèverait <code>TypeError</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q13 : Spécifier le séparateur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment lire un CSV utilisant le <strong>point-virgule</strong><br/>
comme séparateur avec le module <code>csv</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour les fichiers exportés par Excel français, le<br/>
séparateur est <code>;</code>. Pour les CSV anglo-saxons ou<br/>
Google Sheets, c'est <code>,</code>. Pour TSV (tab-separated),<br/>
c'est <code>'\t'</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>csv.reader(f).set_separator(';')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette méthode n'existe pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>csv.reader(f, delimiter=';')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on précise le délimiteur via<br/>
l'argument nommé <code>delimiter</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>csv.reader_semicolon(f)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : cette fonction n'existe pas.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>csv.reader(f)</code> (suffisant, le module détecte tout seul)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : par défaut, le séparateur est la virgule. Le module ne devine pas le séparateur, il faut le lui indiquer.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q14 : Champs contenant le séparateur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment représente-t-on un champ contenant le<br/>
caractère séparateur (par exemple une virgule) dans<br/>
un CSV à séparateur virgule ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Et pour un guillemet à l'intérieur d'un champ<br/>
« guillemeté » ? On le double : <code>"il dit ""bonjour"""</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On échappe la virgule avec un antislash <code>\,</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce n'est pas la convention CSV<br/>
standard (qui utilise les guillemets).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On supprime la virgule du champ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on perdrait l'information.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>On change le séparateur pour ce champ uniquement</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un fichier CSV utilise un séparateur<br/>
unique pour tout le fichier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>On entoure le champ de guillemets doubles : <code>"Lyon, France"</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est la convention du format CSV. Le module <code>csv</code> gère cette syntaxe automatiquement, en lecture comme en écriture.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q15 : Trace de lecture</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le fichier <code>eleves.csv</code> contient :<br/>
<pre><code>nom;age
Alice;17
Bob;16</code></pre><br/>
Que vaut <code>ligne</code> au premier passage de la boucle<br/>
<code>for ligne in csv.DictReader(open("eleves.csv"), delimiter=";")</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Pour récupérer toutes les lignes d'un coup :<br/>
<code>lignes = list(csv.DictReader(...))</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Alice', '17']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait le retour de <code>csv.reader</code>,<br/>
pas de <code>csv.DictReader</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['nom', 'age']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>DictReader</code> consomme la première<br/>
ligne comme en-tête, elle n'apparaît pas dans<br/>
la boucle.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>{'nom': 'Alice', 'age': '17'}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>DictReader</code> saute l'en-tête<br/>
et associe chaque valeur à son nom de colonne.<br/>
Noter que <code>'17'</code> reste une chaîne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>{'Alice': '17', 'Bob': '16'}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on ne reçoit qu'une ligne à chaque<br/>
itération, pas tout le fichier.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q16 : Filtrer les données</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Comment afficher seulement les élèves de plus de<br/>
16 ans à partir d'un CSV <code>nom,age</code> lu via<br/>
<code>csv.DictReader</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Toujours convertir avant de comparer numériquement : toutes les valeurs lues par <code>csv.DictReader</code> sont des chaînes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for ligne in lecteur:
    if int(ligne["age"] &gt; 16):
        print(ligne["nom"])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la parenthèse est mal placée. Python évalue d'abord <code>ligne["age"] &gt; 16</code>, qui compare une chaîne et un entier et lève <code>TypeError</code>, avant même d'appeler <code>int</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for ligne in lecteur:
    if int(ligne[1]) &gt; 16:
        print(ligne[0])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>csv.DictReader</code> produit des<br/>
<strong>dictionnaires</strong> dont les clés sont les<br/>
en-têtes (<code>"nom"</code>, <code>"age"</code>), pas des listes :<br/>
<code>ligne[1]</code> lève <code>KeyError: 1</code>. L'accès par<br/>
indice vaut pour <code>csv.reader</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>for ligne in lecteur:
    if ligne["age"] &gt; 16:
        print(ligne["nom"])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>ligne["age"]</code> est une <strong>chaîne</strong><br/>
(<code>"17"</code>). En Python 3, comparer une chaîne et<br/>
un entier lève <code>TypeError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>for ligne in lecteur:
    if int(ligne["age"]) &gt; 16:
        print(ligne["nom"])</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on convertit l'âge en entier<br/>
(sinon <code>"17" &gt; 16</code> est invalide en Python 3),<br/>
on filtre, on affiche le nom.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q17 : Une virgule dans un fichier tabulé</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le fichier texte tabulé <code>contacts.txt</code> sépare ses champs par une tabulation. Sa première ligne contient <code>Dupont, Jean</code>, une tabulation, puis <code>17</code>.<br/>
<pre><code>import csv
with open("contacts.txt", encoding="utf-8") as f:
    for ligne in csv.reader(f, delimiter="\t"):
        print(ligne)</code></pre><br/>
Qu'affiche ce programme pour la première ligne ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Un fichier texte tabulé s'importe comme un fichier CSV, en indiquant <code>delimiter="\t"</code>. Choisir un séparateur absent des données évite de couper un champ par erreur.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Dupont', ' Jean', '17']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu fais couper le lecteur à la fois sur la virgule et sur la tabulation. Avec <code>delimiter="\t"</code>, seule la tabulation sépare les champs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>['Dupont, Jean', '17']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : seul le délimiteur indiqué, la tabulation <code>"\t"</code>, sépare les champs. La virgule n'est qu'un caractère ordinaire du premier champ.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Dupont, Jean\t17']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu supposes que la tabulation n'est pas reconnue, mais <code>"\t"</code> désigne justement ce caractère. Passé comme délimiteur, il découpe la ligne en deux champs.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Rien, une virgule étant interdite dans un fichier tabulé</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un champ de fichier tabulé peut contenir n'importe quel caractère, sauf la tabulation elle-même. C'est même l'intérêt de ce format quand les données contiennent des virgules.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q18 : Valeurs manquantes</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Dans un CSV avec <code>nom,age,ville</code> et la ligne<br/>
<code>Alice,,Lyon</code>, que vaut <code>ligne["age"]</code> après lecture<br/>
par <code>csv.DictReader</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Donnée manquante : il faut tester la valeur avant de la convertir, par exemple avec <code>if ligne["age"] != "":</code>, puis écarter la ligne ou lui attribuer une valeur choisie.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le programme lève une exception</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la lecture se passe sans erreur ;<br/>
c'est seulement la conversion ultérieure<br/>
(<code>int("")</code>) qui lèverait <code>ValueError</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le module ne fait aucune supposition.<br/>
Une absence n'est pas un zéro.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>None</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>csv.DictReader</code> ne convertit pas<br/>
automatiquement les vides en <code>None</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>''</code> (chaîne vide)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : un champ vide entre deux<br/>
séparateurs est lu comme une chaîne vide. Il<br/>
faut le tester explicitement avant toute<br/>
conversion : <code>if ligne["age"] != "":</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q19 : Export depuis tableur</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Quelle situation correspond à un cas d'usage typique<br/>
du format CSV ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Force du CSV : universalité. Faiblesses : pas de<br/>
types (tout est texte), pas de hiérarchie, pas de<br/>
schéma standard (séparateur, encodage variables).</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Échanger un tableau de notes entre Pronote et un tableur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : c'est exactement le rôle du<br/>
CSV, un format pivot universel pour les<br/>
données tabulaires, lisible par tous les<br/>
outils.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Stocker une vidéo en haute définition</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : CSV est un format texte, inadapté à<br/>
la vidéo (binaire compressé).</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Construire une page web interactive</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est le rôle du HTML/CSS/JS.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Programmer le microcontrôleur d'un objet connecté</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : on programme en C, Python, etc., pas<br/>
en CSV.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q20 : Des p-uplets construits à la lecture</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le fichier <code>ventes.csv</code> contient :<br/>
<pre><code>produit,quantite
stylo,4
cahier,6</code></pre><br/>
<pre><code>import csv
table = []
with open("ventes.csv", encoding="utf-8") as f:
    for ligne in csv.DictReader(f):
        table.append((ligne["produit"], int(ligne["quantite"])))</code></pre><br/>
Que vaut <code>table[1]</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Importer une table, c'est souvent la ranger dans un tableau de p-uplets : on choisit les descripteurs utiles et on convertit les valeurs numériques au moment de la lecture, une fois pour toutes.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>('stylo', 4)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les indices commencent à $0$. La ligne du stylo est <code>table[0]</code> ; <code>table[1]</code> désigne la ligne suivante, celle du cahier.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>('cahier', '6')</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu oublies l'appel à <code>int</code>, qui convertit la chaîne <code>'6'</code> en entier avant la construction du p-uplet.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>{'produit': 'cahier', 'quantite': 6}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : chaque ligne lue est bien un dictionnaire, mais le programme range dans la table un p-uplet construit à partir de deux de ses valeurs, et non le dictionnaire lui-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>('cahier', 6)</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>DictReader</code> utilise l'en-tête pour nommer les champs, la table ne reçoit que les deux lignes de données. <code>table[1]</code> est la seconde, dont la quantité a été convertie par <code>int</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q21 : Bug d'encodage</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un élève lit un CSV créé sous Windows et obtient<br/>
<code>CafÃ©</code> au lieu de <code>Café</code>. Quelle est la cause la<br/>
plus probable ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Indice révélateur : <code>Ã©</code> à la place de <code>é</code> est la <strong>signature classique</strong> d'une mauvaise interprétation d'UTF-8<br/>
en Latin-1. Il existe d'autres signatures<br/>
(<code>Ã¨</code> au lieu de <code>è</code>) qui pointent vers le même<br/>
problème.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Python est trop ancien pour gérer l'UTF-8</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : Python 3 gère parfaitement UTF-8<br/>
depuis sa sortie.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le fichier de données est partiellement corrompu</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le contenu est correct, c'est<br/>
l'<strong>interprétation</strong> de l'encodage qui pose<br/>
problème.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Le fichier UTF-8 est lu comme du Latin-1</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>é</code> en UTF-8 = <code>0xC3 0xA9</code>. Lu<br/>
comme Latin-1, ces deux octets donnent <code>Ã©</code>.<br/>
Solution : préciser <code>encoding="utf-8"</code> à<br/>
l'ouverture.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La connexion internet est instable</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : aucun rapport, on lit un fichier<br/>
local.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q22 : Parsing à la main</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pourquoi <code>ligne.split(',')</code> est-il <strong>insuffisant</strong><br/>
pour parser correctement la ligne CSV<br/>
<code>"Doe, John",42,"Lyon, France"</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Leçon : pour tout CSV non trivial (guillemets,<br/>
sauts de ligne dans les champs, échappements),<br/>
utiliser le module <code>csv</code>. Le « parsing manuel »<br/>
n'est correct que pour des cas très simples et<br/>
maîtrisés.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>split</code> ne fonctionne que sur des fichiers UTF-8</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>split</code> est indépendant de l'encodage.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>split</code> modifie le fichier d'origine sur le disque</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>split</code> ne modifie rien, il renvoie<br/>
une nouvelle liste.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>split</code> ignore les guillemets et coupe à chaque virgule</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on obtient cinq champs au lieu<br/>
de trois, <code>split(',')</code> produisant <code>['\"Doe',<br/>
' John\"', '42', '\"Lyon', ' France\"']</code>. Le<br/>
module <code>csv</code> gère correctement ce cas en<br/>
regroupant les champs entourés de guillemets.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La méthode <code>split</code> est beaucoup trop lente ici</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la performance n'est pas le<br/>
problème, la <strong>correction</strong> l'est.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q23 : Calcul d'une moyenne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Le fichier <code>notes.csv</code> contient une colonne <code>note</code><br/>
(entête en première ligne) avec des nombres entiers.<br/>
Quel code calcule correctement la <strong>moyenne</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Trois étapes systématiques : ouvrir, convertir<br/>
les types, calculer. Toujours penser à la<br/>
conversion en numérique avant tout calcul.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>moyenne = csv.mean("notes.csv", "note")</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la fonction <code>csv.mean</code> n'existe pas.<br/>
Le module <code>csv</code> se limite à la lecture/écriture.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>with open("notes.csv") as f:
    moyenne = sum(csv.reader(f)) / 2</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sum</code> ne sait pas additionner des<br/>
listes de chaînes ; et la division par 2 est<br/>
arbitraire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<pre><code>with open("notes.csv") as f:
    total = 0
    for ligne in csv.DictReader(f):
        total += ligne["note"]
    moyenne = total / len(lignes)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>ligne["note"]</code> est une <strong>chaîne</strong>.<br/>
<code>total += "12"</code> lève <code>TypeError</code>. De plus<br/>
<code>lignes</code> n'est pas défini.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<pre><code>with open("notes.csv") as f:
    notes = [int(ligne["note"]) for ligne in csv.DictReader(f)]
moyenne = sum(notes) / len(notes)</code></pre>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : on construit une liste<br/>
d'entiers (conversion explicite avec <code>int</code>),<br/>
puis <code>sum / len</code>. Code concis et correct.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q24 : Une table de dictionnaires construite à la main</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Sans utiliser <code>DictReader</code>, Hugo associe lui-même l'en-tête du fichier <code>eleves.csv</code> aux valeurs :<br/>
<pre><code>nom,classe
Ali,1A
Zoe,1B</code></pre><br/>
<pre><code>import csv
lignes = []
with open("eleves.csv", encoding="utf-8") as f:
    for ligne in csv.reader(f):
        lignes.append(ligne)
entete = lignes[0]
table = []
for i in range(1, len(lignes)):
    d = {}
    for j in range(len(entete)):
        d[entete[j]] = lignes[i][j]
    table.append(d)
print(table[1])</code></pre><br/>
Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Associer l'en-tête aux valeurs transforme un tableau doublement indexé en table de dictionnaires : pour chaque ligne de données, la valeur de la colonne <code>j</code> est rangée sous la clé <code>entete[j]</code>. C'est le travail que fait <code>csv.DictReader</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>{'nom': 'Ali', 'classe': '1A'}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu fais correspondre <code>table[1]</code> à <code>lignes[1]</code>. Comme l'en-tête n'est pas recopié dans <code>table</code>, les indices sont décalés d'un cran : la ligne de Ali devient <code>table[0]</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>{'Ali': '1A', 'Zoe': '1B'}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : tu prends les valeurs de la première colonne pour des clés. Les clés viennent de <code>entete[j]</code>, c'est-à-dire <code>'nom'</code> et <code>'classe'</code>, et chaque ligne donne son propre dictionnaire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>{'nom': 'Zoe', 'classe': '1B'}</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la boucle sur <code>i</code> commence à $1$ et saute l'en-tête. <code>table[0]</code> est construit à partir de la ligne de Ali, <code>table[1]</code> à partir de celle de Zoe, avec pour clés les noms de colonnes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Zoe', '1B']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>table</code> ne reçoit pas les listes lues, mais le dictionnaire <code>d</code> construit à chaque tour de la boucle sur <code>i</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q25 : Limite du CSV</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Parmi les affirmations suivantes sur le format CSV,<br/>
laquelle est <strong>fausse</strong> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Limites du CSV : pas de typage, pas de hiérarchie, séparateur variable, encodage variable. C'est au programme qui lit le fichier de connaître ces conventions et de convertir les valeurs.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>CSV impose un typage explicite des colonnes (entier, flottant, date)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Faux (donc bonne réponse) : tout est traité<br/>
comme du <strong>texte</strong> dans un CSV. Aucun type<br/>
n'est conservé. C'est au programme de lecture<br/>
de convertir explicitement.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>CSV ne gère pas nativement les structures hiérarchiques (listes imbriquées, dictionnaires)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est sa principale limite, un fichier CSV ne représente qu'une table à deux dimensions, lignes et colonnes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>CSV est un format texte, lisible avec n'importe quel éditeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est l'un de ses grands avantages.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le séparateur n'est pas standardisé universellement (virgule, point-virgule, tabulation...)</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Vrai : c'est une faiblesse historique du format. Selon le logiciel, on trouve une virgule, un point-virgule ou une tabulation.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q26 : Additionner une colonne lue en texte</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Une table lue depuis un fichier CSV contient trois lignes :<br/>
<pre><code>table = [{"nom": "Lou", "points": "12"},
         {"nom": "Sami", "points": "30"},
         {"nom": "Inès", "points": "8"}]
total = 0
for ligne in table:
    total = total + int(ligne["points"])
print(total)</code></pre><br/>
Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Tout ce qui sort d'un fichier CSV est du texte. Convertir les<br/>
nombres avec <code>int</code> ou <code>float</code> est la première étape de tout calcul.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>50</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : chaque valeur, lue comme une chaîne, est<br/>
convertie en entier par <code>int</code> avant l'addition.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>12308</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : sans <code>int</code>, <code>+</code> collerait les chaînes, mais ici la<br/>
conversion est bien faite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur, les points étant des chaînes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est ce qui arriverait sans <code>int</code>. La conversion rend<br/>
l'addition possible.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>total</code> est augmenté à chaque ligne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q27 : Compter les lignes d'une ville</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>La table contient quatre lignes dont les villes sont, dans l'ordre,<br/>
<code>Lyon</code>, <code>Nantes</code>, <code>Lyon</code> et <code>Paris</code>. Qu'affiche ce programme ?<br/>
<pre><code>retenues = []
for ligne in table:
    if ligne["ville"] == "Lyon":
        retenues.append(ligne)
print(len(retenues))</code></pre></p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Filtrer une table, c'est construire une nouvelle liste avec les<br/>
lignes qui vérifient une condition.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>2</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : seules les lignes dont la ville est exactement<br/>
<code>Lyon</code> sont ajoutées, soit deux.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>4</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le <code>if</code> filtre les lignes, toutes ne sont pas retenues.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>Lyon</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>len(retenues)</code> est un nombre de lignes, pas une ville.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur, la liste étant vide au départ</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une liste vide peut recevoir des éléments avec<br/>
<code>append</code>, et <code>len</code> d'une liste vide vaut 0.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q28 : Une comparaison qui échoue</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Après lecture d'un fichier CSV, Maya écrit <code>if ligne["age"] &gt; 15:</code><br/>
et obtient une erreur. Pourquoi ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Python refuse de comparer une chaîne et un nombre : l'erreur<br/>
rappelle qu'une conversion manque.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>ligne["age"]</code> est une chaîne, non comparable à un entier</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la valeur lue est <code>"17"</code>, pas <code>17</code>. Il faut<br/>
écrire <code>int(ligne["age"]) &gt; 15</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>La clé <code>age</code> n'existe pas dans une table lue depuis un CSV</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la clé existe si la colonne figure dans l'en-tête ; le<br/>
problème est le type de la valeur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>&gt;</code> n'est pas défini sur les dictionnaires d'une table</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la comparaison porte sur une valeur du dictionnaire,<br/>
pas sur le dictionnaire lui-même.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les nombres d'un CSV sont toujours lus comme des flottants</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce sont des chaînes, à convertir selon le besoin en<br/>
<code>int</code> ou en <code>float</code>.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q29 : Une moyenne malgré des cases vides</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Les notes d'une colonne ont été lues dans la liste <code>notes</code>,<br/>
une case vide donnant la chaîne vide :<br/>
<pre><code>notes = ["12", "", "15", "9"]
total = 0
n = 0
for note in notes:
    if note != "":
        total = total + float(note)
        n = n + 1
print(total / n)</code></pre><br/>
Qu'affiche ce programme ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Une valeur manquante dans un CSV arrive comme chaîne vide. La<br/>
tester avant conversion évite l'erreur et fausse moins la moyenne.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>12.0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : les cases vides sont ignorées à la fois dans la<br/>
somme et dans le compte, la moyenne porte sur les notes<br/>
présentes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>9.0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : ce serait la somme divisée par le nombre total de cases,<br/>
vides comprises ; or <code>n</code> ne compte que les notes présentes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Une erreur, <code>float("")</code> échouant</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : c'est précisément ce que le test <code>note != ""</code> évite.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>36.0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 36.0 est la somme ; le programme affiche la<br/>
moyenne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q30 : Trier des nombres lus en texte</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Pour trier une table par âge, Lina écrit :<br/>
<pre><code>def cle(ligne):
    return int(ligne["age"])

table_triee = sorted(table, key=cle)</code></pre><br/>
Pourquoi la fonction <code>cle</code> convertit-elle l'âge avec <code>int</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>La fonction passée en <code>key</code> dit comment comparer les lignes. Pour<br/>
un tri numérique sur des données textuelles, elle convertit.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Sinon le tri placerait <code>"9"</code> après <code>"10"</code>, ordre alphabétique</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : des chaînes se comparent caractère par<br/>
caractère, et <code>"1"</code> précède <code>"9"</code>. Convertir en entier rétablit<br/>
l'ordre numérique.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>sorted</code> refuse les chaînes de caractères dans une clé de tri</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>sorted</code> trie très bien des chaînes, mais dans l'ordre<br/>
des caractères, pas des nombres.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>int</code> accélère le tri en allégeant les comparaisons</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la conversion ne change pas la vitesse, seulement<br/>
l'ordre obtenu.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les dictionnaires ne peuvent pas contenir de chaînes</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un dictionnaire accepte n'importe quelle valeur, et les<br/>
valeurs lues sont justement des chaînes.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q31 : Compter les valeurs distinctes d'une colonne</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Qu'affiche ce programme ?<br/>
<pre><code>villes = ["Lyon", "Paris", "Lyon", "Nice", "Paris"]
vues = []
for v in villes:
    if v not in vues:
        vues.append(v)
print(len(vues))</code></pre></p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Ce schéma, tester l'appartenance avant d'ajouter, construit la<br/>
liste des valeurs distinctes d'une colonne.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>3</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : une ville n'est ajoutée à <code>vues</code> que si elle n'y<br/>
figure pas déjà. La liste finale contient chaque ville une<br/>
fois.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>5</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 5 est le nombre de lignes ; les répétitions ne sont<br/>
pas ajoutées.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>2</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : 2 est le nombre de répétitions écartées, pas le<br/>
nombre de villes distinctes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>0</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : la première ville rencontrée est toujours ajoutée.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q32 : Le mode d'ouverture d'un fichier</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que signifie le <code>"r"</code> dans <code>open("eleves.csv", "r", encoding="utf-8")</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p><code>open</code> prend le nom du fichier, un mode, et l'encodage. Lire du<br/>
CSV commence toujours par une ouverture en mode <code>"r"</code>.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Que le fichier est ouvert en lecture seule</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>"r"</code>, pour <em>read</em>, ouvre le fichier pour le<br/>
lire. Écrire dedans demanderait <code>"w"</code> ou <code>"a"</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Que le fichier sera relu plusieurs fois</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le nombre de lectures ne se règle pas à l'ouverture.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Que les retours à la ligne seront retirés</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les retours à la ligne restent dans les lignes lues ;<br/>
c'est <code>strip</code> qui les retire.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Que le fichier est au format CSV</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>open</code> ne connaît pas les formats ; il lit du texte.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q33 : Un retour à la ligne de trop</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>En lisant un fichier ligne par ligne avec <code>for ligne in fichier:</code>,<br/>
Théo découpe chaque ligne avec <code>ligne.split(";")</code> et constate que<br/>
la dernière valeur de chaque ligne contient un caractère de plus.<br/>
D'où vient-il ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Lire un fichier texte à la main demande deux gestes : <code>strip</code> pour<br/>
nettoyer la ligne, puis <code>split</code> pour la découper.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Chaque ligne lue garde son retour à la ligne final</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la lecture conserve le <code>\n</code> final, qui reste<br/>
collé au dernier champ. <code>ligne.strip().split(";")</code> règle le<br/>
problème.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le séparateur <code>;</code> est compté dans la dernière valeur</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>split</code> retire les séparateurs ; le caractère en trop<br/>
est le retour à la ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le fichier contient une colonne vide supplémentaire</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : une colonne en plus donnerait un champ de plus, pas un<br/>
caractère de plus dans le dernier champ.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>L'encodage UTF-8 ajoute un caractère invisible à chaque ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : l'encodage n'ajoute rien ; le caractère est le <code>\n</code><br/>
qui termine chaque ligne du fichier.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q34 : Découper une ligne de CSV</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Que vaut <code>"Lou;15;Lyon".split(";")</code> ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p><code>split</code> est l'outil de base pour lire un CSV sans module : chaque<br/>
ligne devient une liste de champs, tous textuels.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p><code>['Lou', '15', 'Lyon']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : <code>split</code> découpe la chaîne à chaque <code>;</code> et<br/>
renvoie une liste de chaînes, nombres compris.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Lou', 15, 'Lyon']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>split</code> ne convertit rien ; le nombre reste une chaîne<br/>
entre guillemets.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>['Lou;15;Lyon']</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le séparateur <code>;</code> est présent, la chaîne est bien<br/>
découpée.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>'Lou;15;Lyon'</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>split</code> renvoie une liste, pas une chaîne.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q35 : La première ligne n'est pas une donnée</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un programme lit un fichier CSV ligne par ligne et convertit le<br/>
deuxième champ de chaque ligne avec <code>int</code>. Il échoue dès la<br/>
première ligne. Quelle est la cause la plus probable ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>L'en-tête décrit les colonnes ; il se traite séparément, souvent<br/>
pour construire les clés des dictionnaires de la table.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>La première ligne est l'en-tête, et <code>int("age")</code> échoue</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : l'en-tête contient les noms des descripteurs,<br/>
pas des valeurs. Il faut la lire à part et ne convertir que les<br/>
lignes suivantes.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le fichier est vide, et <code>int</code> ne reçoit rien</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un fichier vide ne provoquerait aucune conversion,<br/>
donc aucune erreur.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p><code>int</code> ne s'applique pas aux champs d'un CSV</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : <code>int</code> convertit très bien <code>"17"</code> ; il refuse <code>"age"</code>.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le deuxième champ n'existe pas dans la première ligne</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : un champ absent donnerait une erreur d'indice, pas une<br/>
erreur de conversion.</p>]]></text>
    </feedback>
  </answer>
</question>

<question type="multichoice">
  <name>
    <text>Fichiers CSV — Q36 : Un fichier venu de Windows</text>
  </name>
  <questiontext format="html">
    <text><![CDATA[<p>Un fichier CSV créé sous Windows termine ses lignes par deux<br/>
caractères, <code>\r</code> puis <code>\n</code>, alors qu'un fichier créé sous Linux<br/>
n'utilise que <code>\n</code>. Quelle conséquence pour un programme qui lit<br/>
les lignes et les découpe ?</p>]]></text>
  </questiontext>
  <generalfeedback format="html">
    <text><![CDATA[<p>Les conventions de fin de ligne diffèrent selon les systèmes. Un<br/>
programme robuste nettoie chaque ligne avant de la découper.</p>]]></text>
  </generalfeedback>
  <defaultgrade>1.0</defaultgrade>
  <penalty>0.0</penalty>
  <hidden>0</hidden>
  <single>true</single>
  <shuffleanswers>true</shuffleanswers>
  <answernumbering>abc</answernumbering>
  <answer fraction="100" format="html">
    <text><![CDATA[<p>Un <code>\r</code> reste collé au dernier champ, sauf nettoyage par <code>strip</code></p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Bonne réponse : la lecture retire le <code>\n</code> mais garde parfois le<br/>
<code>\r</code>. <code>strip</code> élimine les deux, ce qui rend le programme<br/>
indépendant du système d'origine.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Le fichier ne peut pas être ouvert sous Linux sans conversion</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le fichier s'ouvre ; seule la fin de ligne diffère.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Chaque ligne est lue deux fois, une par caractère de fin</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : les deux caractères marquent une seule fin de ligne.</p>]]></text>
    </feedback>
  </answer>
  <answer fraction="0" format="html">
    <text><![CDATA[<p>Les séparateurs <code>;</code> sont remplacés par des virgules</p>]]></text>
    <feedback format="html">
      <text><![CDATA[<p>Erreur : le séparateur n'a rien à voir avec la fin de ligne.</p>]]></text>
    </feedback>
  </answer>
</question>

</quiz>
