Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 03 (01/07/2024)
Pièce jointe 656694
Ok !
Merci
Version imprimable
Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 03 (01/07/2024)
Pièce jointe 656694
Ok !
Merci
Maintenant, c'est bon.
Vous pouvez enchainer en renommant "correctement" les variables/champs/fonctions/paramètres.
Vous pouvez en profiter en utilisant aussi des "bons" types pour ces variables/champs/valeur de retour des fonctions et de leurs paramètres.
Je viens de comprendre le "problème" avec le nom de répertoire "Azertyuiop £££.[2024].Mini-série".
Effectivement, l'expression régulière, que j'ai donné, ne fonctionne pas sur ce nom car elle attends toujours un espace entre la ou les années et le nom du canal de diffusion.
Ici, ce n'est pas le cas.
Faut juste rendre cet espace optionnel.
J'ai aussi mis la formule pouvant récupérer les 2 années avant les autres pour gérer la priorité de capture :
(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?
https://regex101.com/r/32IXMi/1 donne la nouvelle version et les 2 exemples de textes : remarquez en hait à droite le décodage en groupe des éléments capturés par l'expression régulière.
Pouvez-vous mettre cette nouvelle expression dans le code ?
Il faut juste ajouter l'escaping C++ à la formule.
Courage ! :D
(C'est juste ajouter 3 "?" pour gérer un nouveau format de chaine de caractères, c'est quand même cool les expressions régulières, non ?)
Bonsoir,
https://github.com/laurentbouleau/Exemple : Juillet 04 (03/07/2024)
Pas fini !
Mais : serie.cpp
Je suis crevé !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 ... const std::wstring Serie::calculer_Annee_Debut() { std::size_t pos = m_annees.size(); std::wstring tmp; std::vector<std::wstring> annees_vec; std::wstringstream annees(m_annees); // ??? while (getline(annees, tmp, L'-')) {// ??? annees_vec.push_back(tmp); break; } std::tm tm; tm = saisons[0].m_dossier.first; assert(std::stoi(annees_vec[0], &pos) == (1900 + tm.tm_year) && L"année != saisons[0].m_dossier.first !!!"); return std::to_wstring(std::stoi(annees_vec[0])); } const std::wstring Serie::calculer_Annee_Fin(std::wstring& wstr) { std::wstring tmp; std::vector<std::wstring> annees_vec; std::wstringstream annees(m_annees); // ??? while (getline(annees, tmp, L'-')) {// ??? annees_vec.push_back(tmp); } std::tm tm; tm = saisons.back().m_dossier.first; return std::to_wstring(std::stoi(annees_vec.back())); } ... const std::wstring Serie::format_Annees() { //assert(m_annees.length() > 0 && L"L'année---");// ??? //assert(m_annees.size() < 10 && L"L'année 2---");// ??? bool found = false; std::wstring annees_str = calculer_Annee_Debut(); std::size_t pos = 0; std::wstring wstr = m_annees.substr(4); if (!found && wstr[0] != L'-') found = true; if (!found) { try { test_date_tire(wstr[0]); } catch (exception_date_tiret e2) { std::wcout << L"Exception a été capturée : " << e2.get_message() << std::endl; } annees_str += keyColor[1] + L'-'; wstr = wstr.substr(1); if (!found && wstr.length() == 0) { found = true; } if (!found) { found = true; annees_str += valuesColor + calculer_Annee_Fin(wstr); } } return keyColor[0] + L" (" + valuesColor + annees_str + keyColor[0] + L')' + valuesColor; } ...
Merci beaucoup:aie::aie::aie:
Bonjour,
Pas fini !
https://github.com/laurentbouleau/Exemple : Juillet 05 (04/07/2024)
Ok ou pas ?
Mais, serie.cpp :
Merci:oops:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 ... const std::wstring Serie::calculer_Annee_Debut() { std::wstring tmp; std::vector<std::wstring> annees_vec; std::wstringstream annees(m_annees); // ??? while (getline(annees, tmp, L'-')) {// ??? annees_vec.push_back(tmp); break; } std::tm tm; tm = saisons[0].m_dossier.first; assert(std::stoi(annees_vec[0]) == (1900 + tm.tm_year) && L"année != saisons[0].m_dossier.first !!!"); return std::to_wstring(std::stoi(annees_vec[0])); } ... const std::wstring Serie::calculer_Annee_Fin(std::wstring& wstr) { std::wstring tmp; std::vector<std::wstring> annees_vec; std::wstringstream annees(m_annees); // ??? while (getline(annees, tmp, L'-')) {// ??? annees_vec.push_back(tmp); } std::tm tm, tm2; tm = saisons[0].m_dossier.first; assert((std::stoi(annees_vec.back()) > (1900 + tm.tm_year)) && L"année != saisons.back().m_dossier.first !!!"); tm2 = saisons.back().m_dossier.first; assert((std::stoi(annees_vec.back()) == (1900 + tm2.tm_year)) && L"année != saisons.back().m_dossier.first !!!"); return annees_vec.back(); } ...
Expliquez-moi !
Serie.h
serie.cppCode:
1
2
3
4
5
6
7
8
9
10
11 ... class Serie { public: Serie(std::filesystem::path racine); ... std::wstring format_Annees(); std::pair<int, int> calculer_Annees_Diffusion(); std::pair<std::optional<int>, std::optional<int>> m_f_anneesProduction; ... };
Comment faire ?Code:
1
2
3
4 std::pair<int, int> Serie::calculer_Annees_Diffusion() { ??? }
Merci:oops::roll:;)
Vous continuez à produire du code bien trop complexe.
Pourquoi ???
Je vous ai déjà indiqué d'utiliser les "bons" types de données pour ne pas faire des usines à gaz.
Pourquoi "m_annees" est une "std::wstring" et pas une "std::pair<std::optional<int>, std::optional<int>>" ???
Simplement en reprenant mon code sur le champ "m_f_anneesProduction" réduirait considérablement la complexité de votre code, comme je l'ai déjà montré dans un précédent post.
Vous pouvez aussi faire ces simplifications dans "Saison::Saison", dans "Saison::initialiser_Fichier" et bien d'autres fonctions qui doivent extraire des "années" d'un nom de fichier (ou tout autre entier).
Vous avez voulu utiliser cette antiquité de "std::tm",ok , mais utilisez aussi des types plus adapter à votre besoin comme un int pour l'année.
Vous n'êtes pas dans de l'embarqué où chaque octet compte.
Vous semblez galérer pour utiliser la version corrigée de l'expression régulière :
Faut juste un peu de soin :Citation:
Code:// std::wregex filename_pattern{ L"(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?" };
Code:std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s?|\\d{4}\\-\\s?|\\d{4}\\s?)?([^\\]]*)\\])?(?:\\.(.+))?" };
Code horriblement complexe qui ne fait pas vraiment ce que son nom indique (mais c'est un peu mieux qu'avant). (Pas de mention de l'utilisation des saisons etc...)Citation:
Code:
1
2
3 const std::wstring Serie::calculer_Annee_Debut() { ... }
L'approche objet "classique", c'est de construire un objet valide dés la fin du constructeur atteinte.
Puis, à chaque modification de l'objet, on vérifie que les invariants de l'objet reste respecté et signaler le problème dès sa détection.
Donc, faire appel à "calculer_Annee_Debut" lors de l'appel à "Serie::format_Annees" qui est en fin de vie de l'objet (son affichage dans la console), c'est pas vraiment le "bon" moment.
C'est plus lors de l'ajout d'une saison qu'il faut vérifier ces années, je pense.
Pour savoir quand toutes les saisons ont été prises en compte, il faudrait que le traitement de tous les répertoires d'une série soit fait dans le contexte du constructeur de la classe Serie et pas dans la fonction "wmain".
A la fin de ce constructeur, vous pouvez lancer un ensemble de fonction pour détecter/corriger les problèmes.
Dans le cas où on "corrige" les dates :
Si je reprends mon champ "m_f_anneesProduction" (une "std::pair<std::optional<int>, std::optional<int>> donc) et que saison dispose d'un champ "m_f_anneesDiffusion" et type de type "std::optional<int>", initialisé de la même manière que "m_f_anneesProduction" mais dans le constructeur de Session, le code ressemblerait à :
On n'est d'accord que ce code est plus explicite que la tambouillle avec les "std::tm", non ?Code:
1
2
3
4
5
6
7 void Serie::corriger_Annee_Debut() { assert((m_f_anneesProduction.first || (saisons.size() > 0 && saisons[0].m_f_anneesDiffusion)) && "Il faut au moins une date de début."); if (!m_f_anneesProduction.first || (saisons.size() > 0 && saisons[0].m_f_anneesDiffusion && m_f_anneesProduction.first > saisons[0].m_f_anneesDiffusion)) m_f_anneesProduction.first = saisons[0].m_f_anneesDiffusion; }
Pour la date de fin, on fait la même chose, juste en faisant gaffe aux indices et au "<" à la place de ">" . En faisant l'assertion que "saisons" ordonne les saisons, ce qui n'est pas le cas actuellement.
Pourquoi votre fonction "Serie::format_Annees" et si compliqué quand j'en ai fourni une triviale ???
FAITES SIMPLE !!! (pas de try/catch, pas d'exit, pas de trace à la noix, pas faire 100 fois les mêmes bidouilles sur les chaines de caractères, etc...)Citation:
Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 std::wstring Serie::format_Annees() { if (m_f_anneesProduction.first && m_f_anneesProduction.second) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[1] + L'-' + valuesColor + std::to_wstring(m_f_anneesProduction.second.value()) + keyColor[0] + L')' + valuesColor; } else if (m_f_anneesProduction.first) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[1] + L')' + valuesColor; } else { std::pair<int, int> anneesDiffusion = calculerAnneesDiffusion(); return keyColor[0] + L" (" + valuesColor + std::to_wstring(anneesDiffusion.first) + keyColor[1] + L'-' + valuesColor + std::to_wstring(anneesDiffusion.second) + keyColor[0] + L')' + valuesColor; } }
EDIT :
Vous gagnez quoi avec "std::pair<int, int>" à la place de "std::pair<std::optional<int>, std::optional<int>>", à part le fait de ne plus gérer le caractère "optionnel" des dates ?
Si c'est obligatoire, Ok, mais j'ai pas l'impression que les assert de votre code soient "carrés" sur le sujet.
Moi, pas-à-pas !!!
Vous : Complexe !Citation:
Dans le cas où on "corrige" les dates :
Si je reprends mon champ "m_f_anneesProduction" (une "std::pair<std::optional<int>, std::optional<int>> donc) et que saison dispose d'un champ "m_f_anneesDiffusion" et type de type "std::optional<int>", initialisé de la même manière que "m_f_anneesProduction" mais dans le constructeur de Session, le code ressemblerait à :
Moi : Simple !!!
Et :
const std::wstring Serie::calculer_Annee_Debut()???
ou
void Serie::corriger_Annee_Debut()
Aller, j'en ai marre !!!
https://github.com/laurentbouleau/Exemple : Juillet 06 (04/07/2024)
Bon, je vais être moins directif.
Ce que je reproche à vos "Serie::calculer_Annee_xxx", c'est de faire un truc à la fin de vie de votre objet, alors que les informations doivent être correctes dès la fin de la création de l'objet.
Et aussi que vous vous enquiquinez à faire de la bidouille sur de la chaine de caractère au lieu d'avoir des "int" pour des années.
Si on n'a besoin de l'information pendant l'utilisation de l'objet, on fait quoi ? On calcule 2 fois le machin (avec peut-être d'autres informations pas encore "correctes") ?
J'ai fait exprès de mentionner "anneesProduction" et "anneesDiffusion" pour que vous vous posiez des questions sur l'ambiguïté des ces "années", mais vous n'avez pas réagi.
Pourquoi y des "dates"(années) dans les noms des répertoires de séries et aussi dans les nom des répertoires des saisons, si on peut déduire les premières (années des séries) à partir des secondes ("dates" des saisons), toute en sachant toujours pas à quoi correspondent ces dates.
Vous faites des manipulations sur les années, les années sont des entiers, donc dégagez moi cette cochonnerie de "std::wstring m_annees" qui n'a plus aucun sens.
Vous avez mis en commentaire "std::tm Date_Diffusee_a_partir_de" mais pourtant ce champ à plus de sens que "std::wstring m_annees".
Pourquoi n'avez-vous pas initialisé le champ "m_f_anneesDiffusion" de la classe saison ?
Un simple :
dans le constructeur de Saison est largement opérationnel.Code:m_f_anneesDiffusion = y;
Vous trouvez votre code simple, pas moi. Quand vous pondez des dizaines de lignes de code qui font (mal) 10 choses à la fois, je les résume souvent en 2 lignes qui font une seule chose à la fois (en supprimant des trucs qui ne servent pas immédiatement).
Donc, commencez par supprimer le champ "std::wstring m_annees" de la classe Serie et remplacez son usage par un ou des champs qui a/ont un sens précis et un type de variable qui leur correspondent.
Et réféchissez pour avoir des mécanismes qui font en sorte que ces champs aient des données "correctes".
Ok !
Avant L'AVC, le GREP (UNIX) !!! Ok !!!
Programmation C++/Expressions rationnelles : wregex !!! J'ai compris !!! Mais, difficile a lire !!
Les phrases simples ! Ok !
Les chiffres : Compliqués !!!
Les exemples :
- 0, 1, 3, ..., 8, 9 : je suis crevé !
- Les dates : 02/07/2024, 15h36 : pas compris !!!
- Les années : pas compris !!!
- Etc...
Complexes, non ?
Pourquoi ?
Et :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 Serie::Serie(std::filesystem::path racine) { this->racine = racine; auto nomDossier = racine.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); std::wstring annees; // ??? std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\s|\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\s)?([^\\]]*)\\])?(?:\\.(.+))?" }; //std::wregex filename_pattern{ L"(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring titres = match[1]; m_titres = Dossier_Titres(titres); m_annees = (match[2].matched) ? match[2].str() : L""; if (match[2].matched) { std::wstring annees_str = match[2].str(); std::wsmatch dummy; if (std::regex_match(annees_str, dummy, std::wregex(L"\\d{4}\\-\\d{4}\\s"))) { m_f_anneesProduction.first = stoi(annees_str); m_f_anneesProduction.second = stoi(annees_str.substr(5)); } else { m_f_anneesProduction.first = stoi(annees_str); } } std::size_t pos; pos = m_annees.find(L' '); if (pos != std::wstring::npos) m_annees = m_annees.substr(0, pos); m_sur = (match[3].matched) ? match[3].str() : L""; std::wstring sous_genre = (match[4].matched) ? match[4].str() : L""; m_sous_genre = sous_genre; } else { assert(false == true && "Le nom du répertoire n'est pas un nom valide."); } }
Et :Code:
1
2
3
4 std::pair<int, int> Serie::calculer_Annees_Diffusion() { return std::make_pair(???, ???); }
Comment faire ?Code:m_f_anneesDiffusion = y;
Ou qu'il ait ? Expliquez-moi !
Et :Code:
1
2
3
4
5
6 ??? Saisin::???_Annees_Diffusion(???) { ??? m_f_anneesDiffusion = y; ??? }
Etc...Code:
1
2
3
4
5
6
7
8
9
10 void Saison::initialiser_Fichier(fs::path const& cheminFichier) { ... if (nomFichier == L"???.txt") { ???_Annees_Diffusion(cheminFichier); return; } ... }
Alors pas "std::wstring m_annees", mais "int m_annees" et "std::vector<int> m_annees" ???
Ça aille, je suis crevé !!!
Merci:aie::aie::aie:
Et pourquoi ?
Titre : The Mandalorian (2019-) ...
et non pas :
Pièce jointe 656814
Les chiffres : calculer !!! C'est dure !!!
J'ai oublié !!!Citation:
Ce que je reproche à vos "Serie::calculer_Annee_xxx", c'est de faire un truc à la fin de vie de votre objet, alors que les informations doivent être correctes dès la fin de la création de l'objet.
Et aussi que vous vous enquiquinez à faire de la bidouille sur de la chaine de caractère au lieu d'avoir des "int" pour des années.
Pas compris !!!
Je suis pas sûr de comprendre vos interrogations.
Oui GREP utilise une sorte de syntaxe à base d'expression régulière.
Donc, si vous avez l'habitude de GREP, c'est très proche.
C'est vrai que l'escaping du C/C++ rend les expressions régulières moins lisibles, malheureusement.Citation:
difficile a lire !!
Pour "capturer" les nombres, c'est assez simple :
"\d", c'est pour un chiffre, un peu comme "[0-9]"
"\d{4}", on capture 4 chiffres consécutifs.
Pour une date de la forme "02/07/2024", c'est 2 chiffres suivi d'un slash ("/") suivi de 2 autres chiffres suivi par un second slash "/" suivi de 4 chiffres.
Si on reprend la définition mais avec la syntaxe des expressions régulière :
\d{2}/\d{2}/\d{4}
(Attention, dans les noms des fichiers de votre projet, les dates ont d'autres formats)
Pour une "date-heure" (datetime) de la forme "02/07/2024, 15h36", c'est assez ambigu car je ne sais pas si 9 heure sera écrit "09h00" ou "9h00".
Si c'est "09h00", cela sera assez proche du format de la date (je vous le laisse en exercice).
Si c'est "9h00", cela veut dire que l'heure est exprimé soit avec 1 chiffre soit avec 2 chiffres, ce qui donne en expression régulière "\d{1,2}". (le 1 à gauche, c'est le nombre minimum de chiffre; le 2 à droite, c'est le nombre maximum de chiffre).
"\s", c'est pour tous les types d'espace (caractère "espace", le caractère tabulation, etc...)
Donc pour une "(datetime)" de la forme "02/07/2024, 15h36", c'est capturable avec une expression de la forme :
\d{2}/\d{2}/\d{4},\s\d{1,2}h\d{2}
Les années, ça dépend, mais dans une date, c'est généralement les 4 chiffres qui se suivent.
"2024" dans "02/07/2024".
Dans les expressions régulières, ça correspondra donc à un truc comme "\d{4}".
Une année, c'est juste un nombre entier, comme 2024, contrairement au mois (Janvier, Février, etc...), donc c'est très simple de stocker une année (pas une date "complète") dans une variables entière type "int" ou "long".
Vous vous obstinez à stocker cette information dans le champ "tm_year" d'un "std::tm", où vous devez ajouter ou supprimer "1900" à chaque manipulation, car il ne stocke pas une année mais le nombre d'années à partir de 1900, c'est chiant.
Ca n'a aucun sens si vous n'avez que l'année mais pas le mois ou le jour d'en le mois, vous n'avez pas l'année "simplement" accessible.
Donc, pour vous simplifier la vie, créez un champ qui stockera directement l'année en plus ou à la place de remplir un "std::tm". (en plus si vous avez besoin de stocker le mois ou le jour dans le mois, à la place si vous n'avez besoin que de l'année)
Vous trouvez "(\d{2})/(\d{2})/(\d{4}),\s(\d{1,2})h(\d{2})" complexe pour décoder toute une "datetime" juste en 2 lignes de code ??? (on récupère 5 données en une seule fois)Citation:
Complexes, non ?
Vous vous posez beaucoup de questions qui se résument souvent à "Comment nommer un truc" ou "Quel type utiliser ou retourner" :
"Comment nommer un truc" : nommez en fonction de ce qu'il fait ou représente, s'il fait ou représente plusieurs choses, c'est que vous avez mal conçu la chose.
"Quel type utiliser ou retourner" : utilisez ou retournez un type correspondant à la chose que la variable représente/stocke. Si c'est un entier (comme une année) utilisez un "int", si c'est un film, une instance d'objet de type Film, si c'est un clafouti, une instance d'objet de type Clafouti, etc...
En mettant les années sous forme d'entier, cela permet de les classer (du plus vieux/ancien au plus récent/grand, par exemple), ou de gérer facilement leur formatage pour affichage (sur X caractères, avec des 0 devant s'il est trop petit, etc...).
Pour une série, vous avez une information qui correspond à une ou 2 années (on sait toujours pas si c'est des années de production ou de diffusion, au demeurant).
Une année, c'est un entier (en première approximation) : int
Vous n'avez pas forcement l'information sur l'année : std::optional<int>
Vous avez besoin d'au plus 2 années (début/fin) non obligatoire : std::pair<std::optional<int>, std::optional<int>>
Ceci n'est valable que pour une série.
Pour les autres classes, il faut reprendre ce qu'ils doivent stocker/gérer et en déduire des types potentiellement différents pour leurs champs, les types des valeurs retournées par leurs fonctions, les types que ces fonctions prennent en paramètre, etc...
Donc, à partir de là, j'ai vraiment l'impression que les réponses ne sont l'application que de ces 2 règles.
"annees" variable locale qui ne sert pas ou plus, donc pourquoi se poser la question ?Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 Serie::Serie(std::filesystem::path racine) { ... std::wstring annees; // ??? ... if (std::regex_match(nomDossier, match, filename_pattern)) { ... m_annees = (match[2].matched) ? match[2].str() : L""; if (match[2].matched) { std::wstring annees_str = match[2].str(); std::wsmatch dummy; if (std::regex_match(annees_str, dummy, std::wregex(L"\\d{4}\\-\\d{4}\\s"))) { m_f_anneesProduction.first = stoi(annees_str); m_f_anneesProduction.second = stoi(annees_str.substr(5)); } else { m_f_anneesProduction.first = stoi(annees_str); } } ... }
Ça dégage.
"m_annees" qui n'a pas le bon type pour une utilisation simple et que le champ "m_f_anneesProduction" remplace avantageusement (avec un nom plus précis, mais peut-être faux).
Donc, comme d'habitude, "m_annees", ça dégage. (Quitte à renommer le champ "m_f_anneesProduction" plus "correctement")
Je sais que c'est moi qui ait "donné" cette fonction mais c'était plus pour illustrer le fait de découper le travail en petites fonctions simples rend les choses simples et lisibles.Citation:
Code:
1
2
3
4 std::pair<int, int> Serie::calculer_Annees_Diffusion() { return std::make_pair(???, ???); }
Le typage des valeurs de retour y était approximatif, car ce n'était pas le sujet du propos.
Il faut donc faire une conception "réfléchie" du type de retour de la fonction avant même de réfléchir à son implémentation :
Pour une paire d'int, quand on sait qu'on n'a pas forcément les "années" ? (pas de saisons ou des saisons sans dates, etc...)
Vous voulez vraiment "forcer" un affichage d'années ??? (sans savoir si c'est les années de productions ou les années de diffusion qui seront affichées dans la console ?)
Pourquoi pas un "std::pair<std::optional<int>, std::optional<int>>" en type de retour qui n'oblige pas à trouver des années sorties du chapeau ?
En plus, elle calcule rien.
Franchement, je pense qu'elle ne sert à rien cette fonction.
Mais bon on va faire simple :
Code:
1
2
3
4 std::pair<int, int> Serie::calculer_Annees_Diffusion() { return make_pair<int, int>(m_f_anneesProduction.first.value_or(0), m_f_anneesProduction.second.value_or(0)); }
Citation:
Et :
Comment faire ?Code:m_f_anneesDiffusion = y;
Ou qu'il ait ? Expliquez-moi !
Code:
1
2
3
4
5
6 ??? Saison::???_Annees_Diffusion(???) { ??? m_f_anneesDiffusion = y; ??? }
Citation:
Citation:
dans le constructeur de Saison est largement opérationnel.
Code:
1
2
3
4
5 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { ... m_f_anneesDiffusion = y; }
C'est quoi la question ?Citation:
Code:
1
2
3
4
5
6
7
8
9
10 void Saison::initialiser_Fichier(fs::path const& cheminFichier) { ... if (nomFichier == L"???.txt") { ???_Annees_Diffusion(cheminFichier); return; } ... }
Surtout que vous avez mis en commentaire le code qui devrait gérer la majorité des fichiers .txt :
Avec le code suivant :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 if (std::regex_match(nomFichier, std::wregex{L"([[:digit:]]{1,2})x(.)+"})) { return; //InfosVisionnage info_vis{*this, m_cheminFichier}; //bool none(); /*if (m_liste_episodes.find(info_vis.m_NumeroEpisode) != m_liste_episodes.end()) { m_liste_episodes[info_vis.m_NumeroEpisode]->ajouter_SequenceVisionnage(info_vis); } else { m_liste_episodes.emplace(std::pair<const int, shared_ptr<Episode>>{ info_vis.m_NumeroEpisode, make_shared<Episode>(info_vis) }); }*/ }
cela fonctionne jusqu'à la ligne :Code:
1
2
3
4
5
6
7
8
9
10
11
12 if (std::regex_match(nomFichier, std::wregex{L"([[:digit:]]{1,2})x(.)+"})) { InfosVisionnage info_vis{*this, cheminFichier }; if (m_liste_episodes.find(info_vis.m_NumeroEpisode) != m_liste_episodes.end()) { m_liste_episodes[info_vis.m_NumeroEpisode]->ajouter_SequenceVisionnage(info_vis); } else { m_liste_episodes.emplace(std::pair<const int, shared_ptr<Episode>>{ info_vis.m_NumeroEpisode, make_shared<Episode>(info_vis) }); } }
dans le constructeur de "InfosVisionnage".Code:m_titres[0] = t[0].substr(0, pos);
Parce que vous gérez n'importe comment le champ "m_titres" de cette classe.
Bin Non, et de quelles années on parle ?Citation:
Alors pas "std::wstring m_annees", mais "int m_annees" et "std::vector<int> m_annees" ???
Pourquoi pas juste :
???Code:std::pair<std::optional<int>, std::optional<int>> m_f_anneesProduction;
EDIT :
Juste l'histoire de la couleur de la parenthèse fermante ?Citation:
Et pourquoi ?
Titre : The Mandalorian (2019-) ...
Juste une typo (faute de frappe) facile à repérer et à corriger :
"keyColor" sous la forme d'un tableau, c'est pas top.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 std::wstring Serie::format_Annees() { if (m_f_anneesProduction.first && m_f_anneesProduction.second) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[1] + L'-' + valuesColor + std::to_wstring(m_f_anneesProduction.second.value()) + keyColor[0] + L')' + valuesColor; } else if (m_f_anneesProduction.first) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[0] + L')' + valuesColor; } else { std::pair<int, int> anneesDiffusion = calculer_Annees_Diffusion(); return keyColor[0] + L" (" + valuesColor + std::to_wstring(anneesDiffusion.first) + keyColor[1] + L'-' + valuesColor + std::to_wstring(anneesDiffusion.second) + keyColor[0] + L')' + valuesColor; } }
Mais vous ne vous simplifiez pas la vie non plus.Citation:
Les chiffres : calculer !!! C'est dure !!!
Si vous avez un champ ""std::pair<std::optional<int>, std::optional<int>> m_f_anneesProduction" que vous initialisez dans le constructeur de Serie, pourquoi vous emmerdez à faire des calculs ?
Bonsoir,
https://github.com/laurentbouleau/Exemple : Juillet 07 (07/07/2024)
Attention :
Pièce jointe 656861
Non ===> (2019-) : ok !
Pas grave !!!
Mais exemple :
Kaleidoscope.[2023 Netflix]???
Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga
Etc...
Pièce jointe 656863
???
Je suis fatigué !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200 void SequenceVisionnage::Print() { ; system("PAUSE"); } /*void SequenceVisionnage::Print() { std::wstring wstr; bool chiffre_et_point_ou_pas = Print_Titre_chiffre_et_point_ou_pas(m_NumeroEpisod); if (chiffre_et_point_ou_pas) { wstr = std::to_wstring(m_saison) + keyColor[1] + L'x' + valuesColor + std::to_wstring(m_episode) + keyColor[1] + L" : " + valuesColor; } wstr += keyColor[1] + m_titre + valuesColor; if (m_deux_points != L"") wstr += m_deux_points + keyColor[1] + m_sous_titre + valuesColor; if (m_numero == 1) { wstr += keyColor[1] + L" (" + valuesColor + std::to_wstring(m_duree_en_seconde / 60) + keyColor[1] + m_min + L')' + valuesColor; } else { //wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(numero++) + keyColor[1] + L']' + valuesColor; //wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(saison_episode.numero++) + keyColor[1] + L']' + valuesColor; //wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(1 + saison_episode.numero++) + keyColor[1] + L']' + valuesColor; //numero++; //saison_episode.numero++; } wstr += keyColor[1] + L" : " + valuesColor; wstr += Print_Dates_de_visionnage(m_dates); // phrases if (m_numero == 1)//titre != L"") { wstr += L"\r\n" + m_phrases; //saison_episode.numero = 1; } std::wcout << wstr; }*/ // ###################################################################################################################################################### // # # // # std::wstring SequenceVisionnage::Print_Dates_de_visionnage(std::vector<DateRecord>& m_DatesVisionnage) # // # # // ###################################################################################################################################################### std::wstring SequenceVisionnage::Print_Dates_de_visionnage(std::vector<DateRecord>& m_DatesVisionnage) { const std::wstring date_format = L"%d" + keyColor[1] + L"/" + valuesColor + L"%m" + keyColor[1] + L"/" + valuesColor + L"%Y"; const std::wstring between_parenthesis = keyColor[1] + L"(" + valuesColor + L"%s" + keyColor[1] + L")" + valuesColor; const std::wstring same_date_format = between_parenthesis; const std::wstring prequel_format = between_parenthesis; const std::wstring streaming_format = keyColor[1] + L" : " + valuesColor + L"%s"; const std::wstring step_by_step_tag = L' ' + keyColor[1] + L'[' + valuesColor + L"pas-à-pas" + keyColor[1] + L']' + valuesColor; std::wstring dates_de_visionnage_wstr = L""; std::vector<std::wstring> v_wstr; std::time_t last_date{ 0 }; int same_date_counter = 0; for (auto dr : m_DatesVisionnage) { std::time_t time = std::mktime(&dr.date); if (last_date != time) { std::tm localtime = *std::localtime(&time); std::wstringstream target_stream; target_stream << std::put_time(&localtime, date_format.c_str()); std::wstring date_str = target_stream.str(); v_wstr.push_back(date_str); same_date_counter = 0; } else { same_date_counter++; if (same_date_counter == 1) { v_wstr.back() += wstring_format(same_date_format, L"1"); } v_wstr.back() += wstring_format(same_date_format, std::to_wstring(same_date_counter + 1).c_str()); } last_date = time; } for (auto i = 0; i < v_wstr.size(); i++) { if (i != 0) dates_de_visionnage_wstr += L", "; dates_de_visionnage_wstr += v_wstr[i]; } if (m_DatesVisionnage.size() == 1) { if (m_DatesVisionnage[0].someFlag) dates_de_visionnage_wstr += wstring_format(prequel_format, L"stop ou pas !"); } else { if (m_DatesVisionnage.size() > 0) { if (m_DatesVisionnage.back().someFlag) { dates_de_visionnage_wstr += wstring_format(prequel_format, L"à suivre"); } dates_de_visionnage_wstr += step_by_step_tag; } } if (m_streaming != L"" && dates_de_visionnage_wstr.length() > 0) dates_de_visionnage_wstr += wstring_format(streaming_format, m_streaming.c_str()); // return dates_de_visionnage_wstr; } // ###################################################################################################################################################### // # # // # bool SequenceVisionnage::Print_Titre_chiffre_et_point_ou_pas(unsigned short int episode) # // # # // ###################################################################################################################################################### bool SequenceVisionnage::Print_Titre_chiffre_et_point_ou_pas(unsigned short int episode) { if (episode == 0) return false; return true; } // ###################################################################################################################################################### // ###################################################################################################################################################### // ###################################################################################################################################################### // # # // # void Episode::Episode(InfosVisionnage const& seq_vis) :m_saison{ info_vis.m_saison } {}; # // # # // ###################################################################################################################################################### // Ok !!! /*Episode::Episode(InfosVisionnage const& seq_vis) { m_saison{ info_vis.m_saison }; }*/ /*Episode::Episode(SequenceVisionnage const& seq_vis) { //auto nomFichier = seq_vis.filename().wstring(); //auto nomFichier = seq_vis; m_liste_sequence_visionnages.push_back(seq_vis); //system("PAUSE"); //assert(nomFichier.length() > 0 && L"Nom de fichier vide"); //Episode episode(cheminFichier); //episodes.push_back(episode); // Episode //SequenceVisionnage sequencevisionnage(seq_vis); //titre = sequencevisionnage.titre; }*/ // ###################################################################################################################################################### // # # // # void Episode::ajouter_SequenceVisionnage(const InfosVisionnage& seq_vis) # // # # // ###################################################################################################################################################### void Episode::ajouter_SequenceVisionnage(const InfosVisionnage& info_vis) { m_liste_sequence_visionnages.push_back(SequenceVisionnage(*this, info_vis)); } // ###################################################################################################################################################### // # # // # void Episode::Print() # // # # // ###################################################################################################################################################### void Episode::Print() { //Print_Data(); // ??? for (auto vis : m_liste_sequence_visionnages) { vis.Print(); } } // ###################################################################################################################################################### // # # // # bool Episode::Print_Data() # // # # // ###################################################################################################################################################### /*void Episode::Print_Data() { }*/ /*bool Episode::Print_Titre_chiffre_et_point_ou_pas(unsigned short int episode) { if (episode == 0) return false; return true; }*/
Merci
Vous voulez que le "-" apparaisse ???Citation:
Non ===> (2019-) : ok !
Pas grave !!!
C'est quoi la logique d'affichage ou non du "-" ?
Vous ne pouvez plus vous basez uniquement sur le répertoire racine de la série car vous utilisez les années des saisons pour "corriger" ces valeurs.
Est-ce que c'est pour indiquer qu'une série est encore en production ?
Normalement, avec notre "nouvelle" architecture, il est simple de voir où est construit cet affichage :
Vous devriez maitriser assez le code pour trouver vous-même la source de l'affichage, non ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 std::wstring Serie::format_Annees() { if (m_f_anneesProduction.first && m_f_anneesProduction.second) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[1] + L'-' + valuesColor + std::to_wstring(m_f_anneesProduction.second.value()) + keyColor[0] + L')' + valuesColor; } else if (m_f_anneesProduction.first) { return keyColor[0] + L" (" + valuesColor + std::to_wstring(m_f_anneesProduction.first.value()) + keyColor[0] + L')' + valuesColor; } else { std::pair<int, int> anneesDiffusion = calculer_Annees_Diffusion(); return keyColor[0] + L" (" + valuesColor + std::to_wstring(anneesDiffusion.first) + keyColor[1] + L'-' + valuesColor + std::to_wstring(anneesDiffusion.second) + keyColor[0] + L')' + valuesColor; } }
On revient à l'usage "classique" du débogueur.Citation:
Mais exemple :
Kaleidoscope.[2023 Netflix]
Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga
Etc...
Vous n'avez qu'à cliquer sur le bouton "Recommencer" pour que le débugueur arrête le programme à la ligne où le problème a été détecté.
Vous verrez dans la pile d'appel (1 frame plus bas que l'endroit de détection) que la ligne problématique dans votre code est ligne 339 du fichier "serie.cpp" :
On est encore sur du code où une variable est utilisée des dizaines de fois pour des choses complètement différentes et où vous ne testez pas les conditions d'utilisation d'une expression avant de vous en servir.Code:initialiser_Duree(t[0]);
Ici, le fichier "1x8.2024-03-03.txt" est vide, donc "t[0]" plante.
Vous avez mis en commentaire l'utilisation de 4 expressions régulières, qui peuvent très facilement fusionner en une seule : "(.+)(?:\\s?\\:\\s|/|\\s\\-\\s)(.+)" (encore plus simplifiable si le motif à trouver est plus "logique").
Pour la remplacer par une usine à gaz à passe de "find" et d'utilisation anarchique de nom de variable comme "t". :aie::alerte::furieux:
Pourquoi faire aussi compliqué ???
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... std::vector<std::wstring> file_content = lire_fichierTxt(m_cheminFichier.wstring(), { L"\n" }, false); m_NumeroEpisode = std::stoi(match[filename_numero_episode_index]); if (file_content.size() > 0) { std::wsmatch soustitre_match; const std::wregex soustitre_format_rg{ L"(?:(\\d+)\\.)?(.+)(?:\\s?\\:\\s|/|\\s\\-\\s)(.+)" }; if (std::regex_match(file_content[0], soustitre_match, soustitre_format_rg)) { m_NumeroEpisode = soustitre_match[1].matched ? std::stoi(soustitre_match[1]) : 0; m_titres.push_back(soustitre_match[2]); m_titres.push_back(soustitre_match[3]); } else { m_titres.push_back(file_content[0]); } } if (file_content.size() > 1) initialiser_Duree(file_content[1]); if (file_content.size() > 2) { file_content.erase(file_content.begin()); //bof à revoir file_content.erase(file_content.begin()); //bof à revoir m_resume = file_content; } }
Quel rapport avec les fonctions "Print" de SequenceVisionnage ???Citation:
Code:
1
2
3
4
5 void SequenceVisionnage::Print() { ; system("PAUSE"); // <----WTF }
Le débogueur est votre ami.
"system("PAUSE");"n non mais, sérieux !!! Les points d'arrêt dans le débogueur, B***** !!!
Bonsoir,
Non, esthétiquement !Citation:
Vous voulez que le "-" apparaisse ???
C'est quoi la logique d'affichage ou non du "-" ?
Vous ne pouvez plus vous basez uniquement sur le répertoire racine de la série car vous utilisez les années des saisons pour "corriger" ces valeurs.
Est-ce que c'est pour indiquer qu'une série est encore en production ?
Exemple :
Pièce jointe 656918
Mais : Pourquoi ?
Exemple : The Mandalorian (dossiers)
2019-11-12Pouvez-vous expliquer ???
2020-10-30
2023-03-01
https://github.com/laurentbouleau/Exemple : Juillet 08 (08/07/2024)
Mais :
Pourquoi ?Code:
1
2
3
4
5
6
7
8
9
10
11 void Saison::initialiser_Fichier(fs::path const& cheminFichier) { ... if (int j = std::stoi(nomFichier)) { m_numero = j; // initialiser_Resume(cheminFichier); // ??? return; } ... }
Pas fini !!! Je suis crevé !!!
Merci:aie::aie::aie:
Ok, mais c'est quoi la "règle" esthétique ?Citation:
Non, esthétiquement !
Je ne suis pas sûr de comprendre la question.Citation:
Exemple : The Mandalorian (dossiers)
2019-11-12
2020-10-30
2023-03-01
Oui, il y a une différence de format entre le nom du fichier et ce qui est affiché.
C'est "vous" qui maitrisez le format de sortie via la ligne :
Code:
1
2
3
4 td::wstring SequenceVisionnage::Print_Dates_de_visionnage(std::vector<DateRecord>& m_DatesVisionnage) { const std::wstring date_format = L"%d" + keyColor[1] + L"/" + valuesColor + L"%m" + keyColor[1] + L"/" + valuesColor + L"%Y"; ...
Je sais pas moi, c'est vous qui avez écrit ce code, que je ne trouve pas logique.Citation:
Pourquoi ?Code:
1
2
3
4
5
6
7
8
9
10
11 void Saison::initialiser_Fichier(fs::path const& cheminFichier) { ... if (int j = std::stoi(nomFichier)) { m_numero = j; // initialiser_Resume(cheminFichier); // ??? return; } ... }
C'est vraisemblablement pour "gérer" des fichiers dont le nom ressemble à "8.txt", etc...
Mais des fichiers comme "1x8.2024-03-03.txt" devrait aussi passer dans le if, et c'est encore moins logique.
Bonjour,
Expliquez-moi ! Mais :
Pièce jointe 656935Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 ... void Episode::Print() { Print_Data(); // ??? for (auto vis : m_liste_sequence_visionnages) { vis.Print(); } } ... void Episode::Print_Data() { ??? } ...
Merci:aie::weird::roll::?
https://github.com/laurentbouleau/Exemple : Juillet 09 (09/07/2024)
Pouvez-vous être plus précis, SVP ?Citation:
Expliquez-moi !
La fonction "Episode:: Print" est là pour afficher dans la console les informations contenus dans l'objet Episode.
Comme "Serie:: Print" ou Saison:: Print".
Dans ces fonctions, vous avez conçus toutes une collection de fonctions chargées d'afficher tel ou tel élément d'une série ou d'une saison :
Serie:: Print_Header();
Serie:: Print_Titre_Original(m_titres_originaux, affichage_titres_originaux_actif, keyColor, valuesColor);
Serie:: Print_Chaine();
Serie:: Print_Audiodescription(m_audiodescription, affichage_audiodescription_actif, keyColor[0], valuesColor);
Serie:: Print_Creee_par();
Serie:: Print_Genres(m_genre, affichage_genres_actif, m_sous_genre, affichage_sous_genre_actif, keyColor[0], valuesColor);
Serie:: Print_En_relation_avec();
Serie:: Print_Nationalites(m_nationalite, affichage_nationalite_actif, keyColor[0], valuesColor);
Serie:: Print_Images(m_image, affichage_image_actif, keyColor[0], valuesColor);
Serie:: Print_Resume
Saison:: Print_Note();
Saison:: Print_Chaine();
Saison:: Print_Netflix();
Saison:: Print_Images();
Saison:: Print_Avec();
Vous devriez faire la même chose pour les informations stockées dans un épisode comme :
son "numéro"
sa "durée"
son "résumé"
etc...
PrintData, c'est juste une fonction "factice" que vous devez remplacer par ce qui est nécessaire, comme les autres fonctions "Serie:: Print_xxx" ou "Saison:: Print_xxx" que vous avez réussit à concevoir sans mon aide.
(moi, j'aurais fait bien moins de fonction de ce type)
Si vous n'en créez aucune, l'affiche d'un épisode se résumerait à l'affichage des sessions de visionnage de cet épisode. Pas terrible.
Pour le plantage dont vous donnez la pile d'appel, le problème est un peu plus loin que dans "Episode:: Print()" dans le pile d'appel.
dans : "Saison:: Print()"
Votre code fait l'assertion qu'il n'y a pas de "trou" dans les numéros d'épisode et qu'il commence à l'épisode numéro "0".Code:
1
2
3
4
5
6 std::size_t taille; taille = std::size(m_liste_episodes); for (auto i = 0; i < taille; i++) { m_liste_episodes[i]->Print(); }
'm_liste_episodes[0]" n'existe pas, mais "std::map" essaye de vous aider en créant à la voler le "std::shared_ptr<Episode>" qui manque avec un pointeur "par défaut", qui n'est pas fonctionnel.
Vous plantez donc quand vous essayez d'accèder aux champs de l'épisode qui n'existe pas.
Ce n'est pas avec une boucle "for classique" que vous devez itérer sur une "std::map" mais avec une "range-based for loop" :
P.S.: rien ne s'affiche de plus car vous n'affichez rien dans les objets "Episode" et "Séquence de Visionnage".Code:
1
2
3
4 for (auto episode : m_liste_episodes) { episode.second->Print(); }
Bonsoir,
https://github.com/laurentbouleau/Exemple : Juillet 10 (10/07/2024)
Comprends rien !!!
Pour quant (beaucoup) (saison) :
et un seul !!!Code:
1
2
3
4 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... }
Donc,Code:
1
2
3
4 void SequenceVisionnage::Print() { ... }
Pièce jointe 657036
Et :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 struct SequenceVisionnage { // ??? SequenceVisionnage(const Episode& episode, const InfosVisionnage& info_vis) : m_episode{ m_episode }, m_titres{info_vis.m_titres}, m_streaming{info_vis.m_streaming}, m_duree_en_seconde{ info_vis.m_duree * 60 }, m_resume{ info_vis.m_resume }, m_DatesVisionnage{ info_vis.m_DatesVisionnage } {}; void Print(); std::wstring Print_Dates_de_visionnage(std::vector<DateRecord>& dr); bool Print_Titre_chiffre_et_point_ou_pas(int episode); std::wstring m_min = L"min"; std::vector<std::wstring>keyColor{ L"\x1b[94;1m", L"\x1b[38;2;0;255;0m" }; // keyColor[0] (bleu) et keyColor[1] (vert) std::wstring valuesColor = L"\x1b[38;2;255;255;255m"; // Blanc std::wstring m_streaming{ L"" }; //bool m_fichier_pas_zero{ false }; //std::wstring m_titre; //std::wstring m_deux_points; //std::wstring m_sous_titre; std::vector<std::wstring> m_titres; long m_duree_en_seconde{ -1 }; std::vector<std::wstring> m_resume{}; std::vector<DateRecord> m_DatesVisionnage{}; int m_saison{ -1 }; int m_episode{ -1 }; int m_numero{ -1 }; long m_duree{ -1 }; private: //const Episode& m_episode; // ??? };
Etc...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 ... void SequenceVisionnage::Print() { std::wstring wstr; bool chiffre_et_point_ou_pas = Print_Titre_chiffre_et_point_ou_pas(m_numero); if (chiffre_et_point_ou_pas) { wstr = std::to_wstring(m_saison) + keyColor[1] + L'x' + valuesColor + std::to_wstring(m_episode) + keyColor[1] + L" : " + valuesColor; } bool found = false; if (!found && m_titres.size() == 0) found = true; if (!found && m_titres.size() == 1) { found = true; wstr += keyColor[1] + m_titres[0] + valuesColor; } else { found = true; wstr += m_titres[1] + keyColor[1] + m_titres[2] + valuesColor; } if (m_numero == 1) { wstr += keyColor[1] + L" (" + valuesColor + std::to_wstring(m_duree_en_seconde / 60) + keyColor[1] + m_min + L')' + valuesColor; } else { wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(m_numero++) + keyColor[1] + L']' + valuesColor; //wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(m_saison_episode.m_numero++) + keyColor[1] + L']' + valuesColor; // wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(m_saison.m_numero++) + keyColor[1] + L']' + valuesColor; //wstr += keyColor[1] + L" [" + valuesColor + std::to_wstring(1 + saison_episode.numero++) + keyColor[1] + L']' + valuesColor; m_numero++; //saison_episode.numero++; } wstr += keyColor[1] + L" : " + valuesColor; wstr += Print_Dates_de_visionnage(m_DatesVisionnage); // m_resume if (m_numero == 1)//titre != L"") { // std::wstring resume_str; // wstr += L"\r\n" /* + m_resume*/; // for (auto r : m_resume) // resume_str += r; // wstr += resume_str; //saison_episode.numero = 1; } std::wstring resume_str; if (m_resume.size() != 0) { // ??? for (auto r : m_resume) resume_str += r; } std::wcout << wstr << resume_str << L"\r\n"; } ... void Saison::ajouter_InfosVisionnage(SequenceVisionnage const& seq_vis) { // ??? //m_liste_episodes.insert({ 1, seq_vis }); //m_liste_episodes.insert({ 1, seq_vis }); //m_numero++; //auto [xxx, success] = m_liste_episodes.insert({ m_numero, seq_vis }); //m_liste_episodes.insert(std::pair<int, Episode>(m_numero, seq_vis)); //m_liste_episodes.insert({ m_numero, seq_vis }); } ...
Je suis perdus !!!
Désolé !!!
Merci:aie::weird::roll:8O:ptdr:
Pas de panique.
Si vous avez des questions plus précises, ça serait plus efficace.
On va essayer d'être synthétique.
Avez-vous les connaissances de base de la programmation objet ? (classe, fonction de classe, membre d'une classe)
Sinon, il faudrait apprendre le principe de ces notions.
Il y a pas mal de "grosses boulettes" dans le code que vous avez posté sur Git.
Exemple :
- Vous avez "converti" le champ "m_episode" d'une "const Episode&" en un "int".
Pourquoi ?
Un épisode, c'est bien plus qu'un nombre !
En plus vous avez initialisé ce champ de type "int" avec des données "foireuses":
Vous initialisez le champ avec le contenu du champ, qui n'est pas initialisé. WTF ???Citation:
Code:
1
2 SequenceVisionnage(const Episode& episode, const InfosVisionnage& info_vis) : m_episode{ m_episode },...
Le code d'avant était bien plus "logique" :
Ici, on initialise m_episode avec le paramètre du constructeur, ce paramètre, c'est l'objet de type "Episode" qui représente l'épisode dont la "séquence de visualisation" (celle qu'on est en train de construire, vu qu'on est dans son constructeur).Code:
1
2 SequenceVisionnage(const Episode& episode, const InfosVisionnage& info_vis) : m_episode{m_episode },...
Avec ce champ" m_episode" de type "const Episode&", on a accès à toutes les informations publiques stockées par un objet de type "Episode".
Cela change un peu la manière dont on récupère ces infos :
Citation:
Code:wstr = std::to_wstring(m_saison) + keyColor[1] + L'x' + valuesColor + std::to_wstring(m_episode) + keyColor[1] + L" : " + valuesColor;
Code:wstr = std::to_wstring(m_episode.m_saison.m_numero) + keyColor[1] + L'x' + valuesColor + std::to_wstring(m_episode.m_numero) + keyColor[1] + L" : " + valuesColor;
- Vous n'initialisez pas la première séquence de visionnage lors de la création d'un épisode :
Citation:
Code:Episode(InfosVisionnage const& info_vis) :m_saison{ info_vis.m_saison } {};
Code:Episode(InfosVisionnage const& info_vis) :m_saison{ info_vis.m_saison } { ajouter_SequenceVisionnage(info_vis); };
Qu'est-ce qui se passe si vous avez 2 éléments dans "m_titres" ?Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 bool found = false; if (!found && m_titres.size() == 0) found = true; if (!found && m_titres.size() == 1) { found = true; wstr += keyColor[1] + m_titres[0] + valuesColor; } else { found = true; wstr += m_titres[1] + keyColor[1] + m_titres[2] + valuesColor; }
Ça plante.
(Pas top comme code)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 bool found = false; if (!found && m_titres.size() == 0) found = true; if (!found && m_titres.size() == 1) { found = true; wstr += keyColor[1] + m_titres[0] + valuesColor; } else { found = true; wstr += m_titres[0] + keyColor[1] + m_titres[1] + valuesColor; }
- etc...
Pouvez-vous expliquer ce que vous avez compris du fonctionnement actuel de votre programme ?
Je pourrais voir là où vous faites fausse route dans votre compréhension du programme.
C'est le constructeur de InfosVisionnage. C'est appelé pour chaque fichier dont le nom respecte la règle de construction des informations de visionnage :Citation:
Pour quant (beaucoup) (saison) :
Code:
1
2
3
4 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... }
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 if (std::regex_match(nomFichier, std::wregex{L"([[:digit:]]{1,2})x(.)+"})) { InfosVisionnage info_vis{ *this, cheminFichier }; if (m_liste_episodes.find(info_vis.m_NumeroEpisode) != m_liste_episodes.end()) { m_liste_episodes[info_vis.m_NumeroEpisode]->ajouter_SequenceVisionnage(info_vis); } else { m_liste_episodes.emplace(std::pair<const int, shared_ptr<Episode>>{ info_vis.m_NumeroEpisode, make_shared<Episode>(info_vis) }); } return; }
C'est appelé pour chacune de séquence de visionnage de chacun des épisodes de chacune des saisons de chacune des séries :Citation:
et un seul !!!
Code:
1
2
3
4 void SequenceVisionnage::Print() { ... }
Ça fait donc un paquet d'appel. (Normalement autant que de création d'objet "SequenceVisionnage").
Pourquoi avoir changer le type de m_episode ???Citation:
Code:
1
2 struct SequenceVisionnage { // ???
Pouvez-vous m'expliquer la logique d'utilisation du champ "m_numero" ??? (C'est complètement foireux, je pense)Citation:
Code:
1
2 void SequenceVisionnage::Print() {...
Ca sert à quoi ???Citation:
Code:
1
2 void Saison::ajouter_InfosVisionnage(SequenceVisionnage const& seq_vis) {...
Il semble que l'affichage des informations d'une séquence de visionnage ne dépend pas uniquement du contenu d'un objet "SequenceVisionnage" mais de sa place dans l'ordre de l'ensemble des séquences de visionnage d'un épisode.
Dans ce cas, il faudrait mieux "supprimer/modifier la logique" de la fonction "SequenceVisionnage:: Print" car l'objet n'a pas toutes les billes et le code en devient trop complexe.
Si on transfert l'affichage d'une SequenceVisionnage de la fonction "SequenceVisionnage:: Print" à une fonction "Episode:: PrintFirstSequenceVisionnage" pour la première séquence de visionnage et "Episode:: PrintSequenceVisionnage" pour les autres :
deviendraitCode:
1
2
3
4
5
6
7 void Episode::Print() { for (auto vis : m_liste_sequence_visionnages) { vis.Print(); } }
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void Episode::Print() { bool first = true; for (auto vis : m_liste_sequence_visionnages) { if(first) { PrintFirstSequenceVisionnage(vis); } else { PrintSequenceVisionnage(vis); } first = false; } }
Bonsoir,
Un petit peu ! L'AVC !Citation:
On va essayer d'être synthétique.
Avez-vous les connaissances de base de la programmation objet ? (classe, fonction de classe, membre d'une classe)
Sinon, il faudrait apprendre le principe de ces notions.
Et '.' (LIST) :
- Vous avec "coversi" le...
...
Avec ce champ" m_episode" de type "const Episode&", on a accès à:roll:
Aie !!! Narrateur est planté ou cassé :aie: Alors...
Exemple :Citation:
Pouvez-vous expliquer ce que vous avez compris du fonctionnement actuel de votre programme ?
Je pourrais voir là où vous faites fausse route dans votre compréhension du programme.
Comment faire ???Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 struct InfosVisionnage :[LIST] { ... unsigned short int m_NumeroSaison{}; unsigned short int m_NumeroEpisode{}; ... int m_numero{ -1 }; ... }; struct SequenceVisionnage { ... int m_numero{ -1 }; ... }; ...
Je suis fatigué !!!
Ok !!!Citation:
C'est appelé pour chacune de séquence de visionnage de chacun des épisodes de chacune des saisons de chacune des séries :
Ça fait donc un paquet d'appel. (Normalement autant que de création d'objet "SequenceVisionnage").
Pouvez-vous expliquer ?Citation:
Pourquoi avoir changer le type de m_episode ???
Ben oui !!!:?:aie:Citation:
Pouvez-vous m'expliquer la logique d'utilisation du champ "m_numero" ??? (C'est complètement foireux, je pense)
Ah !!!Citation:
Ca sert à quoi ???
Il semble que l'affichage des informations d'une séquence de visionnage ne dépend pas uniquement du contenu d'un objet "SequenceVisionnage" mais de sa place dans l'ordre de l'ensemble des séquences de visionnage d'un épisode.
Dans ce cas, il faudrait mieux "supprimer/modifier la logique" de la fonction "SequenceVisionnage:: Print" car l'objet n'a pas toutes les billes et le code en devient trop complexe.
Si on transfert l'affichage d'une SequenceVisionnage de la fonction "SequenceVisionnage:: Print" à une fonction "Episode:: PrintFirstSequenceVisionnage" pour la première séquence de visionnage et "Episode:: PrintSequenceVisionnage" pour les autres :
Comment faire ?
Pièce jointe 657068
https://github.com/laurentbouleau/Exemple : Juillet 11 (11/07/2024)
Merci:aie::aie::aie:
Bonjour,
Excusez-moi !
et pas :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... std::vector<std::wstring> file_content = lire_fichierTxt(m_cheminFichier.wstring(), { L"\n" }, false); m_NumeroEpisode = std::stoi(match[filename_numero_episode_index]); if (file_content.size() > 0) { std::wsmatch soustitre_match; const std::wregex soustitre_format_rg{ L"(?:(\\d+)\\.)?(.+)(?:\\s?\\:\\s|/|\\s\\-\\s)(.+)" }; if (std::regex_match(file_content[0], soustitre_match, soustitre_format_rg)) { m_NumeroEpisode = soustitre_match[1].matched ? std::stoi(soustitre_match[1]) : 0; m_titres.push_back(soustitre_match[2]); m_titres.push_back(soustitre_match[3]); } else { m_titres.push_back(file_content[0]); } } ... }
La phrase : verbre
Que faire ?Code:const std::wregex soustitre_format_rg{ L"(?:(\\d+)\\.)?(.+)(?:\\s?\\:\\s|/|\\s\\-\\s)(.+)" };
Pas dormis !
Merci:aie::aie::aie:
Ou :
La phrase: verber
ou
La phrase/verber
ou
La phrase / verber
ou
La phrase - verber
ou
La phrase - verber
bacelar : 02/07/2024, 15h36
Marches pas !!!Citation:
Je viens de comprendre le "problème" avec le nom de répertoire "Azertyuiop £££.[2024].Mini-série".
Effectivement, l'expression régulière, que j'ai donné, ne fonctionne pas sur ce nom car elle attends toujours un espace entre la ou les années et le nom du canal de diffusion.
Ici, ce n'est pas le cas.
Faut juste rendre cet espace optionnel.
J'ai aussi mis la formule pouvant récupérer les 2 années avant les autres pour gérer la priorité de capture :
(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?
Bonsoir,
Question :
Avec :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { ... std::wregex filename_pattern{ L"???" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { ??? ... wchar_t sp = L' ', tiret = L'-'; auto y = std::stoi(wstr, &pos); assert(1582 <= y && L"L'année est inférieur !"); m_f_anneesDiffusion = y; ... } else { assert(false == true && "Le nom du répertoire n'est pas un nom valide."); } }
2021
2021 abc
2021-02
2021-02 abc
2021-02-30
2021-02-30 abc
Ok ou pas !
Merci beaucoup:aie::weird:8O:oops:
Bonsoir,
Exemple (film) :
Star Wars- The Clone Wars.(2008-08-27).Animation
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 int wmain(int argc, wchar_t* argv[]) { ... // Film film(racine); std::wregex film_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\]]*)\\])?(?:\\.(.+))?" }; // ??? std::wsmatch match; if (std::regex_match(nomDossier, match, film_pattern)) { std::wcout << nomDossier << std::endl; std::wcout << L"\r\n"; std::wcout << L"Ok !!!" << L"\r\n"; return EXIT_SUCCESS; } ... }
https://en.cppreference.com/w/cpp/regex : Complexe !!! Alors...
https://regex101.com ???
Je suis crevé ! Mais, bon:roll:
https://github.com/laurentbouleau/Exemple : Juillet 12 (13/07/2024)
Merci:aie::aie::aie:
Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 13 (14/07/2024)
std::regex : L".(" et L")" : Tant pis !!!
Et :
Ok !Code:
1
2
3 ... Film film(racine); ...
Merci:roll::weird::calim2:
Vous ne pouvez pas lire les posts avec des listes à puces (LIST) ou vous ne pouvez pas répondre "facilement" à ces posts ?Citation:
Un petit peu ! L'AVC !
Et '.' (LIST) :
- Vous avec "coversi" le...
...
Avec ce champ" m_episode" de type "const Episode&", on a accès à
Aie !!! Narrateur est planté ou cassé :aie: Alors...
Je vais donc éviter de les utiliser.
Répondez à la question précédente, SVP. Pour savoir si je dois reformuler ces réponses.
Pouvez-vous résumer en quelques mots ce qu'est une structure en C ?Citation:
Un petit peu ! L'AVC !Citation:
Bonsoir,
On va essayer d'être synthétique.
Avez-vous les connaissances de base de la programmation objet ? (classe, fonction de classe, membre d'une classe)
Sinon, il faudrait apprendre le principe de ces notions.
Quelles différences entre une structure C et une structure en C++, toujours en quelques mots ?
(BIS)Citation:
Citation:
Pouvez-vous expliquer ce que vous avez compris du fonctionnement actuel de votre programme ?
Je pourrais voir là où vous faites fausse route dans votre compréhension du programme.
Vous n'avez pas répondu.
J'attends une explication succincte du fonctionnement du programme, SVP.
Plutôt que d'avoir 10 fois la même information à 10 endroits différents, l'objectif est d'avoir l'information "correcte" à un seul endroit, facile d'accès.Citation:
Exemple :
Comment faire ???Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 struct InfosVisionnage :[LIST] { ... unsigned short int m_NumeroSaison{}; unsigned short int m_NumeroEpisode{}; ... int m_numero{ -1 }; ... }; struct SequenceVisionnage { ... int m_numero{ -1 }; ... }; ...
J'espère que vous vous êtes rendu compte que le processus de construction des objets lors du scan du système de fichier est là pour construire une arborescence d'objets.
Vous avez des objets "Serie" qui "contiennent" chacune les objets Saison de la Serie "contenant" la saison. Un objet Saison par saison constituant la Serie. Les objets Saison contiennent chacun les objet Episode constituant la saison. Les Episodes contiennent les séquences de visionnage de cet épisode.
Vous avez un objet "Serie" par série. Votre fonction "wmain", dans "Exemple.cpp" ne scanne qu'un répertoire, vous aurez donc construit qu'un seul objet Serie.
Vous construisez l'arborescence des autres objets dans cette boucle :Code:Serie serie(racine);
Depuis un objet Serie, le champ "saisons" contient l'ensemble des saisons de la serie.Code:
1
2
3
4 for (const auto& entry_serie : fs::directory_iterator((serie.getRacine()))) { .... }
Depuis un objet Saison, le champ "m_liste_episodes" contient l'ensemble des épisodes de la Saison.
Depuis un objet Episode, le champ "m_liste_sequence_visionnages" contient l'ensemble des sessions de visionnage de l'épisode.
Pendant la construction de l'arborescence, on a pris soin de stocker le lien inverse de l'arborescence, pour pouvoir "remonter" l'arborescence.
Depuis un objet Saison, on obtient la Serie contenant la saison via son champ "m_serie".
Depuis un objet Episode, on obtient la saison contenant l'épisode via son champ "m_saison".
Depuis un objet SequenceVisionnage, on obtient l'épisode correspondant à la séquence de visionnage via son champ "m_episode".
On peut donc facilement obtenir toutes les informations depuis une séquence de visionnage :
Des informations sur l'épisode :
Des informations sur la saison :Code:
1
2
3
4
5
6 void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(...) { ... auto uneInfoDeLEpisode = m_episode.lInfoQuiMInteresse; ... }
Des informations sur la série :Code:
1
2
3
4
5
6 void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(...) { ... auto uneInfoDeLaSaison = m_episode.m_saison.lInfoQuiMInteresse; ... }
Cela fonction à n'importe quel niveau de l'arborescence et on peut "naviguer" dans l'arborescence dans les 2 sens :Code:
1
2
3
4
5
6 void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(...) { ... auto uneInfoDeLaSerie = m_episode.m_saison.m_serie.lInfoQuiMInteresse; ... }
Serie => Saison :
(foireuse cette boucle, utilisez plutôt une "range-based for loop")Code:
1
2
3
4
5
6
7
8
9
10
11
12 const void Serie::Print_Saisons() { if (affichage_saisons_actif) { std::size_t taille; taille = std::size(saisons); for (int i = 0; i < taille; i++) { Print_Saison(saisons[i]); } } }
Saison => Episode
Episode => Séquence de VisionnageCode:
1
2
3
4
5
6
7
8
9 void Saison::Print() { ... for (auto episode : m_liste_episodes) { episode.second->Print(); } .... }
Tout ceci n'est donc pas "nouveau".Code:
1
2
3
4
5
6
7 void Episode::Print() { for (auto vis : m_liste_sequence_visionnages) { vis.Print(); } }
Si ce n'est toujours pas clair, cette notion d'accès aux informations dans une arborescence d'objet, pouvez-vous poser des cas concrets qui vous posent problème ?
Ceux que je vais citer ci-après, c'est des cas un peu "spéciaux".
La classe InfosVisionnage est un cas spécial car on l'utilise à un moment ou on ne sait pas si elle représente juste une séquence de visionnage ou un Episode et une séquence de visionnage.Citation:
Code:
1
2
3
4
5
6
7
8
9 struct InfosVisionnage { ... unsigned short int m_NumeroSaison{}; unsigned short int m_NumeroEpisode{}; ... int m_numero{ -1 }; ... };
On peut donc facilement avoir accès aux informations de la saison via un code comme :
Donc votre champCode:
1
2
3
4
5
6 void InfosVisionnage::UneFonctionDeLaClasseInfosVisionnage(...) { ... auto uneInfoDeLaSaison = m_saison.lInfoQuiMInteresse; ... }
ne présente aucun intérêt, à par complexifier le code pour l'initialiser et le maintenir à jour.Code:unsigned short int m_NumeroSaison{};
Le code ci-dessus fait largement le travail sans avoir à vous trimballer un Xème champ qui n'a rien à voir avec l'objet.Code:
1
2
3
4
5
6 void InfosVisionnage::UneFonctionDeLaClasseInfosVisionnage(...) { ... auto NumeroSaison= m_saison.m_numero; ... }
Je suis très dubitatif sur l'utilité d'avoir accès à un numéro d'épisode dans un "InfosVisionnage" quand on ne sait pas encore si lui-même (l'"InfosVisionnage") représente juste une séquence de visionnage ou un Episode et une séquence de visionnage.
Ce n'est pas le cas quand on n'est dans la classe "SequenceVisionnage" mais, dans ce cas, on dispose d'un champ "m_episode" qui fait le travail.
Quand une conception rend difficile des choses qui n'ont pas de sens mais simple les cas d'usage logique, c'est que la conception est bonne.
Ici, je trouve que c'est le cas.
De quel "numero" on parle ???Citation:
Code:
1
2
3
4
5
6 struct SequenceVisionnage { ... int m_numero{ -1 }; ... };
Si c'est le numéro de l'épisode, on a déjà répondu avec un "m_saison.m_numero".
Pour moi, un "numéro" n'a aucun sens au niveau d'une séquence de visionnage.
Si c'est pour classer chronologiquement les séquences de visionnage, ce numéro devrait changer à chaque fois qu'une séquence de visionnage plus ancienne est ajoutée, un enfer.
Si c'est vraiment utile, vous pouvez toujours vous adresser à l'épisode qui, lui, a une vue d'ensemble de toutes les "séquences de visionnage" de l'épisode.
En implémentant une fonction "GetNumero" au niveau de l'épisode, ça devrait le faire, si c'est nécessaire.
Et vous n'aurez qu'à appeler pour avoir une information à jour et fiable :Code:
1
2
3
4 int Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis) { ... }
Code:
1
2
3
4
5
6 void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(...) { ... auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); ... }
Donc, ça dépend. Mais quand c'est compliqué, c'est vraisemblablement que vous avez un problème de conception ou que vous vous prenez la tête sur un "faux" problème.Citation:
Comment faire ???
C'est vous qui avez changé le type de m_episode !Citation:
Pouvez-vous expliquer ?Citation:
Pourquoi avoir changer le type de m_episode ???
C'est donc à vous de nous expliquer pourquoi vous l'avez changé.
Moi, je pense que vous auriez pas dû. :aie:
Bon, il semble que vous êtes revenu sur cette action dans les dernières versions des sources.
Alors, si je comprends bien :Citation:
Ben oui !!!Citation:
Pouvez-vous m'expliquer la logique d'utilisation du champ "m_numero" ??? (C'est complètement foireux, je pense)
On initialise le champ à -1 au moment de la construction de l'objet.
On fait absolument rien avec jusqu'à l'appel de la fonction "SequenceVisionnage:: Print()", en fin du cycle de vie de l'objet.
On appel dans cette fonction "SequenceVisionnage:: Print_Titre_chiffre_et_point_ou_pas"
Code:
1
2
3
4
5 void SequenceVisionnage::Print() { ... bool chiffre_et_point_ou_pas = Print_Titre_chiffre_et_point_ou_pas(m_numero); ...
Comme le paramètre "episode" est toujours égale à "-1", donc _"chiffre_et_point_ou_pas" est toujours égale à "true".Code:
1
2
3
4
5
6 bool SequenceVisionnage::Print_Titre_chiffre_et_point_ou_pas(int episode) { if (episode == 0) return false; return true; }
Pourquoi s'embêter avec tout ça, juste pour toujours avoir le même début de chaine d'affichage ???
Ligne 346 de serie.cpp:
On n'entre jamais dans le if.Code:
1
2
3
4 if (m_numero == 1) { .... }
Donc toujours s'embêter pour rien.
Ligne 353 de serie.cpp:
Tout ça pour toujours afficher un "-1" ???Code:duree_str += keyColor[1] + L" [" + valuesColor + std::to_wstring(m_numero) + keyColor[1] + L']' + valuesColor;
Il y a beaucoup beaucoup plus simple, non ?
Ligne 364 de Serie.cpp :
Ok, m_numero est toujours "-1", donc, encore un if pour rien.Code:
1
2 if (m_numero == 1 && m_resume.size() != 0)//titre != L"") {
Ligne 377 de Serie.cpp :
Cool, m_numero passe de -1 à 0, mais comme c'est à la fin de "SequenceVisionnage:: Print()", ça sert à rien !!!Code:m_numero
Alors, si c'est bien ce que vous vouliez faire avec ce champ "m_numero", c'est bien, mais moi, je vois pas l'intérêt de tout ce bordel.
Il y a un champ "m_numero" par objet/instance de SequenceVisionnage. Il n'est pas commun à tous les objets/instances "SequenceVisionnage", et heureusement.
Bin, déjà, en ne mettant en commentaire le code que j'ai fourni :Citation:
Comment faire ?
Vous n'avez qu'à implémenter tranquillement les fonctions "PrintFirstSequenceVisionnage" et "PrintSequenceVisionnage".Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 // ===> Ici !!! /*void Episode::Print() { bool first = true; for (auto vis : m_liste_sequence_visionnages) { if (first) { PrintFirstSequenceVisionnage(vis); } else { PrintSequenceVisionnage(vis); } first = false; } }*/
Comme vous ne nous avez pas expliqué quelles différences existent entre l'affichage de la première séquence de visionnage et les suivantes (même s'il y a une différence, c'est pas sûr), on ne peut pas vous aider à les implémenter.
Ces différences ne sont-elles pas juste l'affichage des informations de l'épisode en plus des informations de la séquence de visionnage ?
Pouvez-vous nous présentez comment vous voulez que les informations de l'épisode et des informations des séquences de visionnage soient concrètement affichées, SVP ?
Ainsi, on pourrait vous aiguiller pour l'implémentation de "PrintFirstSequenceVisionnage" et/ou "PrintSequenceVisionnage".
Quelle est la question ???Citation:
Excusez-moi !et pas :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... std::vector<std::wstring> file_content = lire_fichierTxt(m_cheminFichier.wstring(), { L"\n" }, false); m_NumeroEpisode = std::stoi(match[filename_numero_episode_index]); if (file_content.size() > 0) { std::wsmatch soustitre_match; const std::wregex soustitre_format_rg{ L"(?:(\\d+)\\.)?(.+)(?:\\s?\\:\\s|/|\\s\\-\\s)(.+)" }; if (std::regex_match(file_content[0], soustitre_match, soustitre_format_rg)) { m_NumeroEpisode = soustitre_match[1].matched ? std::stoi(soustitre_match[1]) : 0; m_titres.push_back(soustitre_match[2]); m_titres.push_back(soustitre_match[3]); } else { m_titres.push_back(file_content[0]); } } ... }
La phrase : verbre
m_titres[0] contient bien " La phrase " et m_titres[1] contient bien "verbre".
C'est quoi le problème ??? Les espaces au début et à la fin de m_titres[0] ???
Je rappelle que le but d'une expression régulière est de reconnaitre un "motif" dans une chaine de caractère et d'isoler les différentes parties du motif dans des "captures".
"La phrase : verbre" correspond au motif "(.+)(?:\s?\:\s|/|\s\-\s)(.+)"
Qui peut s'exprimer en :
- "n'importe quelle chaine de caractère" => (.+)
Suivi par :
- soit un espace puis un ":" suivi encore par un espace => \s\:\s
Mais le premier espace n'est pas obligatoire =>\s?\:\s
- soit un slash "/" => /
- soit un espace puis un "-" suivi encore par un espace => \s\-\s
Le tout suivi par "n'importe quelle chaine de caractère" => (.+)
Vous devriez donc retrouver ces différentes parties du motif dans l'expression régulière, ces parties sont entourées de parenthèse "()" pour indiquer au moteur d'expression régulière quelles parties de la chaine de caractère récupérer dans les "captures".
Ici, c'est "soustitre_match" qui contient les différentes captures.
"soustitre_match[1]" contient la capture correspondant aux chiffres indiquant le numéro de l'épisode.
"soustitre_match[2]" contient la capture correspondant à la chaine de caractère avant l'un des séparateurs spécifiés.
"soustitre_match[3]" contient la capture correspondant à la chaine de caractère après l'un des séparateurs spécifiés.
Faites des tests avec des cas simples avec l'outil à l'URL https://regex101.com pour vous faire la main.
Comprendre comment fonctionne les expressions régulières.Citation:
Que faire ?
Quelle est là question ???Citation:
Ou :
La phrase: verber
ou
La phrase/verber
ou
La phrase / verber
ou
La phrase - verber
ou
La phrase - verber
"La phrase: verber", motif déjà gérer avec : "\s?\:\s"
"La phrase/verber", motif déjà gérer avec : "/"
"La phrase / verber", facile à ajouter : "\s/\s"
"La phrase - verber", motif déjà gérer avec : "\s\-\s"
"La phrase - verber", quelle différence avec le motif précédent ?
Donc, pour prendre en compte le nouveau format, rien de plus simple :
(.+)(?:\s?\:\s|/|\s\-\s|\s/\s)(.+)
(A vous d'ajouter l'escaping lié au C/C++)
L'expression serait vraisemblablement simplifiable, mais vous ne nous donnez pas de définition "synthétique" des motifs utilisables dans les noms de fichier et le contenu des fichiers.
Si vous ne vous en sortez pas avec les expressions régulières, c'est possible de faire la même chose avec vos "std::find", mais il faut le faire correctement, ce que vous ne faisiez pas et le faire correctement demande bien plus de code, peu lisible, et, je trouve, plus compliqué à mettre au point correctement.
Oups, j'ai mal lu le résultat sur https://regex101.com/r/bhCcJO/1Citation:
bacelar : 02/07/2024, 15h36
Marches pas !!!Citation:
Je viens de comprendre le "problème" avec le nom de répertoire "Azertyuiop £££.[2024].Mini-série".
Effectivement, l'expression régulière, que j'ai donné, ne fonctionne pas sur ce nom car elle attends toujours un espace entre la ou les années et le nom du canal de diffusion.
Ici, ce n'est pas le cas.
Faut juste rendre cet espace optionnel.
J'ai aussi mis la formule pouvant récupérer les 2 années avant les autres pour gérer la priorité de capture :
(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?
L'évaluation OK/pas OK est bonne mais le découpage en parties n'est pas bonne.
https://regex101.com/r/0fqBFb/1
Donne une version qui découpe les parties plus correctement.
Mais la formule donnée : "(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?" n'est pas celles implémentées par le code.
Elle doit être bonne, mais faut que vous l'utilisiez dans votre code. (ça ne l'ai pas dans la version "Juillet 12 (13/07/2024)" des sources)
Vérifiez avec https://regex101.com les formules que vous devriez être capable de créer.
Mais vous devriez avoir une vue synthétique de quoi et comment doit être formés les noms et textes que vous devez analyser. Sinon, les expressions régulières vont se complexifier inutilement.
Oui, faut juste réfléchir un peu pour trouver la "bonne" expression régulière.Citation:
Avec :Code:
1
2
3
4
5
6
7
8
9 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { ... std::wregex filename_pattern{ L"???" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { ??? ...
2021
2021 abc
2021-02
2021-02 abc
2021-02-30
2021-02-30 abc
Ok ou pas !
Démonstration d'une expression régulière qui fait le travail :
https://regex101.com/r/QQy0ai/1
réponse rapide : (\d{4})(?:-(\d{2})(?:-(\d{2}))?)?(?:\s(.+))?
Vous n'arrivez pas à accéder aux sauvegardes des expressions régulières + tests que j'y ai sauvegardé ???Citation:
Faut juste faire on sorte de prendre des parenthèses à la place des crochets :Citation:
Star Wars- The Clone Wars.(2008-08-27).Animation
Code:std::wregex film_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?" };
Normal, c'est pour cela que j'ai indiqué l'outil https://regex101.comCitation:
Ok ! Je suis crevé !
Mais, Film film : presque !
Demain ou plus tard;)
Merci beaucoup:aie::aie::aie:
Bonsoir,
Des listes à puces (LIST) : il bug !!! (Windows 10 : Paramètres : Options d'ergonomie : Narrateur). Windows 11, peu être ?Citation:
Vous ne pouvez pas lire les posts avec des listes à puces (LIST) ou vous ne pouvez pas répondre "facilement" à ces posts ?
Ok = C ! Mais, j'ai oublié ! Alors, C++ : très dure !Citation:
Pouvez-vous résumer en quelques mots ce qu'est une structure en C ?
Quelles différences entre une structure C et une structure en C++, toujours en quelques mots ?
Ben ! Oh : j'ai oublié (bis) ! Aie !Citation:
(BIS)
Vous n'avez pas répondu.
J'attends une explication succincte du fonctionnement du programme, SVP.
Eh ! Difficile a lire ! Plus simple ! Mais, bon:roll:Citation:
Depuis un objet Serie, le champ "saisons" contient l'ensemble des saisons de la serie.
Depuis un objet Saison, le champ "m_liste_episodes" contient l'ensemble des épisodes de la Saison.
Depuis un objet Episode, le champ "m_liste_sequence_visionnages" contient l'ensemble des sessions de visionnage de l'épisode.
Pendant la construction de l'arborescence, on a pris soin de stocker le lien inverse de l'arborescence, pour pouvoir "remonter" l'arborescence.
Depuis un objet Saison, on obtient la Serie contenant la saison via son champ "m_serie".
Depuis un objet Episode, on obtient la saison contenant l'épisode via son champ "m_saison".
Depuis un objet SequenceVisionnage, on obtient l'épisode correspondant à la séquence de visionnage via son champ "m_episode".
Pouvez-vous expliquer ?Code:void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(???)
Oui ! Comment faire ?Citation:
(foireuse cette boucle, utilisez plutôt une "range-based for loop")
Ok !Citation:
Saison => Episode
Ok ! Comme "range-based for loop" ?Citation:
Episode => Séquence de Visionnage
Ben, alors, ... ???Citation:
Tout ceci n'est donc pas "nouveau".
Si ce n'est toujours pas clair, cette notion d'accès aux informations dans une arborescence d'objet, pouvez-vous poser des cas concrets qui vous posent problème ?
Rien compris !!!Citation:
Ceux que je vais citer ci-après, c'est des cas un peu "spéciaux".
...
Ainsi, on pourrait vous aiguiller pour l'implémentation de "PrintFirstSequenceVisionnage" et/ou "PrintSequenceVisionnage".
Ben, non !Citation:
Quelle est la question ???
m_titres[0] contient bien " La phrase " et m_titres[1] contient bien "verbre".
C'est quoi le problème ??? Les espaces au début et à la fin de m_titres[0] ???
Je rappelle que le but d'une expression régulière est de reconnaitre un "motif" dans une chaine de caractère et d'isoler les différentes parties du motif dans des "captures".
Ben, non :Citation:
"La phrase: verber", motif déjà gérer avec : "\s?\:\s"
"La phrase/verber", motif déjà gérer avec : "/"
"La phrase / verber", facile à ajouter : "\s/\s"
"La phrase - verber", motif déjà gérer avec : "\s\-\s"
"La phrase - verber", quelle différence avec le motif précédent ?
Exemple :
PhraseBen oui !
Phrase / verberPhrase : titre !
verbre : sous-titre !
Et :
Voilà !!!Code:
1
2
3
4
5
6
7
8
9 const std::wstring d_p = L" : "; pos = t[0].find(d_p); if (!found && pos != std::wstring::npos) { m_titres[0] = t[0].substr(0, pos); m_titres[1] = d_p; m_titres[2] = t[0].substr(pos + 3); found = true; }
https://regex101.com : Demain !!!
Je suis fatigué !!!
Merci beaucoup:aie::aie::aie:
https://github.com/laurentbouleau/Exemple : Juillet 14 (15/07/2024)
Film : ok !
Merci:aie::aie::aie:
Bonjour,
Peux dormir !
Exemple :
https://geek.judgehype.com/article/s...e-mandalorian/Citation:
The Mandalorian.[2019-2023 Disney+].Mini-série
Citation:
2019-11-12
Citation:
1x1.2024-06-14.txt
Citation:
1. Chapitre 1 : Le Mandalorien
41 min
Un chasseur de primes Mandalorien traque une cible pour un mystérieux et fortuné client.
https://www.allocine.fr/series/fiche.../saison-34684/
https://www.allocine.fr/series/fiche...2/saison-6030/Citation:
Star Wars- The Clone wars.[2008-2020].Animation
Citation:
2008
Citation:
1x01.2024-06-15.txt
Citation:
1. Embuscade
26 min
Le maître Jedi Yoda est en mission secrète pour établir un traité avec le roi du système stratégique de Toydaria lorsque le comte Dooku tend une embuscade à son vaisseau. Yoda et trois soldats clones doivent faire face à l'assassin de Dooku, Asajj Ventress, et à son imposante armée de droides, pour prouver que les Jedi sont assez forts pour protéger le roi et son peuple des forces de la guerre...
https://starwars.fandom.com/fr/wiki/...The_Clone_Wars
https://www.allocine.fr/series/fiche...rie=24636.htmlCitation:
Star Trek - Prodigy.[2021- Netflix].Animation
Citation:
2021-10-28
Citation:
1x01.2024-01-10.txt
Citation:
1. Perdu et trouvé - 1re partie
23 min
Prisonnier sur une planète minière, le jeune Dal décide d'aider un fugitif et fait une mystérieuse découverte qui pourrait bien leur permettre de s'échapper.
Citation:
1x03.2024-01-12.txt
Citation:
3. Un travail d'équipe
24 min
La conseillère holographique du Protostar propose de guider le vaisseau, mais la méfiance de Dal envers l'autorité met tout l'équipage en grand danger.
https://www.netflix.com/fr/title/81725736
https://www.allocine.fr/series/fiche.../saison-35233/Citation:
Giri$Haji.[2019].Mini-série
Citation:
Titre.txt
Citation:
Giri/Haji
60 min
Aidé par un jeune prostitué nippo-britannique, un détective tokyoïte, Kenzo, ratisse Londres pour retrouver son frère, impliqué avec les Yakuza et recherché pour meurtre.
Citation:
2019-10-17
Citation:
1x1.2020-01-16_16_17_18.txt
Citation:
1. Episode 1
57 min
Lorsque le neveu du chef d'un clan Yakuza de Tokyo est tué, un rival part se cacher à l'étranger, plongeant un détective dans un mystère qui le touche de très près.
https://www.netflix.com/fr/title/80190519
Voilà:roll:
Ok !Citation:
Merci ;)
Bonsoir,
Pourquoi ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { auto nomDossier = cheminFichier.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); assert(nomDossier.length() > 3 && L"Nom de fichier trop court pour avoir au moins une date"); wchar_t sp = L' ', tiret = L'-'; //std::wregex filename_pattern{ L"(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))?" }; std::wregex filename_pattern{ L"(\\d{4})(?:\\-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))?" }; // Ok ! std::wsmatch match; bool found = false; if (std::regex_match(nomDossier, match, filename_pattern)) // Ok ! { std::wstring year = match[1]; auto y = std::stoi(year); assert(1582 <= y && L"L'année est inférieur !"); // L"(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))? if (match[2].matched) // Marches pas !!! { std::wstring wstr = match[2].str(); std::wsmatch dummy; if (std::regex_match(wstr, dummy, std::wregex(L"(?:-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))?"))) { ; } else { ; } } ... }
Pièce jointe 657222
Merci d'avance:aie::aie::aie:
Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 17 (17/07/2024) Ok ou pas ?
https://github.com/laurentbouleau/Exemple/ : Tracker.[2024-]/Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { auto nomDossier = cheminFichier.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); assert(nomDossier.length() > 3 && L"Nom de fichier trop court pour avoir au moins une date"); //std::wregex filename_pattern{ L"(\\d{4})(?:-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))?" }; std::wregex filename_pattern{ L"(\\d{4})(?:\\-(\\d{2})(?:-(\\d{2}))?)?(?:\\s(.+))?" }; std::wsmatch match; std::tm tm; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring year = match[1]; auto y = std::stoi(year); assert(1582 <= y && L"L'année est inférieur !"); auto m = 0, d = 0; tm.tm_year = y - 1900; if (match[2].matched) { std::wstring mon = match[2]; auto m = std::stoi(mon); assert((1 <= m && m <= 12) && L"Le mois invalide !"); tm.tm_mon = m - 1; if (match[3].matched) { std::wstring mday = match[3]; auto d = std::stoi(mday); assert((1 <= d && d <= 31) && L"Le jour invalide !"); if (!checkday(m, d, y)) { std::wcout << L"Le jour invalide !!!" << std::endl; exit(1); } tm.tm_mday = d; } } } else { assert(false == true && "Le nom du répertoire n'est pas un nom valide."); } if (match[4].matched) { m_date_diffusee_a_partir_de.second = match[4]; } m_date_diffusee_a_partir_de.first = tm; }
https://www.allocine.fr/series/fiche.../saison-54037/ ???
Merci beaucoup:roll:
Pièce jointe 657253
???
Rrr !!!
Sinon :
Merci beaucoup:aie::aie::aie:Code:
1
2
3
4 Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { ... }
Mais :
Compliqué !Citation:
Plutôt que d'avoir 10 fois la même information à 10 endroits différents, l'objectif est d'avoir l'information "correcte" à un seul endroit, facile d'accès.
...
Ainsi, on pourrait vous aiguiller pour l'implémentation de "PrintFirstSequenceVisionnage" et/ou "PrintSequenceVisionnage".
Pas-à-pas !!!
Et :Je suis crevé !!!Citation:
Quelle est la question ???
m_titres[0] contient bien " La phrase " et m_titres[1] contient bien "verbre".
C'est quoi le problème ??? Les espaces au début et à la fin de m_titres[0] ???
...
Mais la formule donnée : "(.+?)(?:\.\[(\d{4}\-\d{4}\s?|\d{4}\-\s?|\d{4}\s?)?([^\]]*)\])?(?:\.(.+))?" n'est pas celles implémentées par le code.
Elle doit être bonne, mais faut que vous l'utilisiez dans votre code. (ça ne l'ai pas dans la version "Juillet 12 (13/07/2024)" des sources)
Simple !
(15/07/2024, 00h05)
Bonsoir,
Excusez-moi !
https://github.com/laurentbouleau/Exemple : Juillet 18 (18/07/2024)
Exemple :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 ... Saison::Saison(fs::path const& cheminFichier, const Serie& serie) : m_serie{ serie } { ... } ... void Saison::Print_Header() { wchar_t date_tab[15]; std::wstring date_str{}; if (m_date_diffusee_a_partir_de.first.tm_mday == -858993460 && m_date_diffusee_a_partir_de.first.tm_mon == -858993460) { std::wcsftime(date_tab, 15, L"%Y", &m_date_diffusee_a_partir_de.first); std::wstring date_tab_str = date_tab; date_str = date_tab_str; } else if (m_date_diffusee_a_partir_de.first.tm_mday == -858993460) { std::wcsftime(date_tab, 15, L"%m/%Y", &m_date_diffusee_a_partir_de.first); std::wstring date_tab_str = date_tab; date_str = date_tab_str.substr(0, 2) + keyColor[1] + L'/' + valuesColor + date_tab_str.substr(3, 4); } else { std::wcsftime(date_tab, 15, L"%d/%m/%Y", &m_date_diffusee_a_partir_de.first); std::wstring date_tab_str = date_tab; date_str = date_tab_str.substr(0, 2) + keyColor[1] + L'/' + valuesColor + date_tab_str.substr(3, 2) + keyColor[1] + L'/' + valuesColor + date_tab_str.substr(6, 4); } std::wstring dossier_str; ... } ...
===> Star Wars- The Clone wars.[2008-2020].Animation
Merci:roll: