Rrr !
https://github.com/laurentbouleau/Exemple : Juillet 19 (18/07/2024)
===> std::tm tm{ -1, -1, -1, -1, -1, -1, -1, -1, -1 };
Voilà !
Version imprimable
Rrr !
https://github.com/laurentbouleau/Exemple : Juillet 19 (18/07/2024)
===> std::tm tm{ -1, -1, -1, -1, -1, -1, -1, -1, -1 };
Voilà !
Bonjour,
J'ai beaucoup de mal à lire, donc j'utilise le narrateur de l'ordi. Mais pour lire les listes à puces (LIST) : le narrateur bugue !!! J'ai Windows 10. Peut-être que ça marcherait avec le narrateur de Windows 11?Citation:
Vous ne pouvez pas lire les posts avec des listes à puces (LIST) ou vous ne pouvez pas répondre "facilement" à ces posts ?
Je sais ce qu'est une strusture en C, mais je ne peux pas l'expliquer, à cause de mes troubles du langage (aphasie). Je vois un peu la différence entre la structure en C et en C++, mais ce n'est pas clair du tout pour moi.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 ?
J'ai appris C++ par moi-même après mon AVC, donc c'est compliqué pour moi.
Non, je ne peux pas l'expliquer; ce n'est pas clair pour moi. En plus, je ne peux pas écrire des phrases complètes tout seul.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.
Là, c'est mon orthophoniste qui écrit ce que je veux dire.
Pour moi, ce serait vraiment plus facile si vous donniez des indications peu à peu, de façon courte. Lire une très grande page d'explications est très décourageant car ça me prend des heures.
-------------------------------------------
(Moi même !)
Mais, 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 int wmain(int argc, wchar_t* argv[]) { ... const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga"; ... bool found = false; std::wregex film_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?" }; std::wsmatch match; if (!found && std::regex_match(nomDossier, match, film_pattern)) { Film film(racine); found = true; for (const auto& entry_film : fs::directory_iterator((film.getRacine()))) { if (entry_film.is_regular_file()) { film.initialiser_Fichier(entry_film); continue; } } film.Print(); found = true; } if (!found) { std::wregex serie_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\s|\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" }; std::wsmatch match2; if (!found && std::regex_match(nomDossier, match2, serie_pattern)) { Serie serie(racine); for (const auto& entry_serie : fs::directory_iterator((serie.getRacine()))) { if (entry_serie.is_regular_file()) { serie.initialiser_Fichier(entry_serie); continue; } if (fs::is_directory(entry_serie)) { Saison saison(entry_serie, serie); for (const auto& entry_saison : fs::directory_iterator(entry_serie)) { if (entry_saison.is_regular_file()) { saison.initialiser_Fichier(entry_saison); } } serie.saisons.push_back(saison); } } serie.Print(); } } ... }
Je n'y arrive pas !Code:const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga";
Merci:?
Bonsoir,
Exemple serie.cpp :
Ok ! Mais, tant pis !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 const void Serie::Print_Header() { ... if (affichage_sur_actif && m_sur != L"" && m_sur != L"Disney+" && m_sur != L"Netflix") { sur_str += keyColor[0] + L" (" + keyColor[1] + L"sur " + valuesColor + m_sur + keyColor[0] + L')' + valuesColor; } if (affichage_sur_actif && (m_sur == L"Disney+" || m_sur == L"Netflix")) { sur_str += keyColor[0] + L" (" + keyColor[1] + L"sur " + valuesColor + m_sur + keyColor[1] + L" : " + valuesColor; // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += m_disney_sj; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += m_netflix_sj; sur_str += keyColor[0] + L')' + valuesColor; } else { // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += keyColor[0] + L" (" + valuesColor + L"Disney+" + keyColor[1] + L" : " + valuesColor + m_disney_sj + keyColor[0] + L')' + valuesColor; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += keyColor[0] + L" (" + valuesColor + L"Netflix" + keyColor[1] + L" : " + valuesColor + m_netflix_sj + keyColor[0] + L')' + valuesColor; } ... }
Et :
Merci:?Code:
1
2
3
4
5
6
7
8
9
10
11 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... if (file_content.size() > 2) { //file_content.erase(file_content.begin()); //bof à revoir //file_content.erase(file_content.begin()); //bof à revoir file_content.erase(file_content.begin(), file_content.begin() + 1); m_resume = file_content; } }
Pour l'utilisation des "puces", je ne les utiliserai plus ici.
J'ai ouvert un sujet sur le forum lié aux évolutions "des forums", pour voir s'il s'agit d'un problème connu. (voir s'il y a une solution de "contournement")
Pour les longs messages, comme vous faites beaucoup de messages entre chacune de mes réponses, que les questions n'y sont pas forcément très claires et que vous ne répondez pas aux questions de mes réponses précédentes, cela fait mécaniquement augmenter la taille des réponses suivantes, pour ne pas "perdre" de sujets.
Mais comme cela part dans tous les sens. Je vais vraisemblablement "élaguer" des choses, quitte à revenir après sur le sujet.
Je vais donc répondre à mes propres questions car vous ne semblez pas pouvoir "facilement" y répondre. (Si vous ne comprenez pas la réponse indiquez le moi explicitement et ce que vous ne comprenez pas dans mon "autoréponse").
- Une structure de données en C est un regroupement d'informations/données.
- Uns structure de données en C++, c'est comme une structure en C, mais on n'y ajoute les fonctions nécessaires à l'initialisation des données (via le constructeur) et la manipulation "cohérente" de ces données (c'est une très mauvaise définition mais c'est un début et on verra plus tard comment utiliser/concevoir "correctement" une structure/classe C++).
- L'architecture du programme s'articule en 3 "étapes" :
-> initialisation de l'environnement d'exécution (lignes 440 à 470 d'Exemple.cpp)
-> création d'une arborescence d'objets contenant les informations qui nous intéressent (cf. le schéma ci-après) (lignes 476 à 530 d'Exemple.cpp)
-> affichage des informations récoltées dans la console (ligne 531 d'Exemple.cpp)
(Le découpage est assez "arbitraire" car le code est assez mal structuré, mais c'est pas très compliqué à corriger.)
Schéma de l'arborescence des objets créées pendant la 2ème étape du programme :
Pièce jointe 657510
Il y a les lignes noirs qui vont du tronc de l'arbre, ici le seul et unique objet "Serie" créé ligne 509 d'Exemple.cpp, vers les feuilles : les séquences de visionnages.
saisons -> m_liste_episodes -> m_liste_sequence_visonnages
Il y a aussi les flèches de couleurs, qui vont dans l'autre sens, des feuilles vers le tronc.
m_episode -> m_saison -> m_serie
"UneFonctionDeLaClasseSequenceVisionnage", c'est juste le nom d'une fonction quelconque de la classe SequenceVisionnage, qu'elle existe déjà ou une future/nouvelle fonction.Citation:
Citation:
Code:
1
2
3
4
5
6 void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(...) { ... auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); ... }
Pouvez-vous expliquer ?Code:void SequenceVisionnage::UneFonctionDeLaClasseSequenceVisionnage(???)
Elle ne devrait jamais s'appeler "UneFonctionDeLaClasseSequenceVisionnage" car cela n'a pas de signification "valable".
Déjà expliqué :Citation:
Oui ! Comment faire ?Citation:
(foireuse cette boucle, utilisez plutôt une "range-based for loop")
Les "boucles" ("range-based for loop") permettent d'aller dans toutes les "branches/feuilles" de l'arborescence (de gauche à droite sur le schéma ci-avant).Code:
1
2
3
4
5
6
7
8
9
10 const void Serie::Print_Saisons() { if (affichage_saisons_actif) { for (auto saison : saisons) { Print_Saison(saison); } } }
Bin, c'est vous qui devez me donner un exemple d'accès à des données qui vous bloque.Citation:
Ben, alors, ... ???
On va le faire pas à pas.Citation:
Rien compris !!!
Donnez-moi à quoi doit ressembler l'affichage des informations, SVP.
Heu, bon si, c'est pas vous qui choisissez comment fonctionnent les expressions régulières, vous devez savoir comment elles fonctionnent pour pouvoir vous en servir correctement.Citation:
Ben, non !
C'est pas forcement évident, la preuve, un mème qu'un collèque vient de m'envoyer : :aie:
https://www.topito.com/top-gif-code-developpeur
Rien compris, en plus le code qui suit ne correspond pas aux formats et n'utilise pas d'expression régulière.Citation:
Ben, non :
Exemple :
Phrase
Ben oui !
Phrase / verber
Phrase : titre !
verbre : sous-titre !
Et :
Message du "16/07/2024, 10h13":
Quel est la question ?
Quel rapport avec les pages Web.
J'ai déjà signalé que votre approche n'est pas adaptée à la récupération d'information via du "scrapping" de site Web.
Message du "16/07/2024, 22h25"
Bin normale, "match[1]" contient l'année de départ et "match[2]" est le mois de départ, qui n'est pas renseigné, donc "match[2].matched" est 'false'.Citation:
Code:if (match[2].matched) // Marches pas !!!
Message du "17/07/2024, 15h22" :
Pouvez-vous utiliser le débugueur pour voir où cela ne fonctionne pas ?
Comme vous ne nous donnez pas le format des noms de fichiers mais juste des cas d'utilisation, cela complexifie inutilement l'expression régulière : quel est donc le format des noms de fichiers, SVP ?
Vous devriez être capable de corriger vous-même cette erreurCitation:
Erreur C4716:
Rrr !!!
Je ne comprends pas, vous me demandez de faire du pas-à-pas sur du code que vous avez vous-même créé.Citation:
Compliqué !
Pas-à-pas !!!
Pourquoi vous emmerdez avec un std::tm, quand vous n'avez pas de "time" ???Citation:
===> std::tm tm{ -1, -1, -1, -1, -1, -1, -1, -1, -1 };
Ici, c'est un peu compliqué.Citation:
Je n'y arrive pas !Code:const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga";
Vous avez 4 motifs possibles (alternatives) :
\\d{4}\\s => Année + un espace
\\d{4}\\-\\d{4}\\s => "Année1 - Année2" + un espace
\\d{4}\\-\\s => "Année-", comme dans "Tracker.[2024-]", + un espace (et c'est pour ça que cette formule échoue pour "Tracker.[2024-]"
\\d{4} => Année
Les alternatives sont évaluées dans l'ordre dans lequel elles apparaissent dans l'expression régulière.
Donc, pour ne pas avoir de problème, vous devriez commencer par les alternatives les plus longues puis les un peu plus courtes, etc... jusqu'aux plus courtes.
Pour le cas "Tracker.[2024-]", il n'y a pas d'alternavite qui accepte ce motif.
Le plus simple, c'est d'ajouter le motif "\\d{4}\\-" aux autres, mais en respectant l'ordre "du plus long au plus court".
Faites des tests avec https://regex101.com pour comprendre comment ça fonctionne. Mais commencez avec des cas simples.
Une fois que vous avez une expression régulière qui fonctionne avec le nouveau format, ajoutez l'alternative correspondante à la la capture qui est entre parenthèses "()" en respectant l'ordre "du plus long au plus court".
Pour rappel, les différentes alternatives d'une capture sont séparées par un caractère "|" (pipe).
Je suis encore en train de faire un message à rallonge pour répondre à toutes vos "interrogations" mais comme vous faites au moins 3 versions entre chacune de mes réponses et que vous modifiez énormément de code à chaque fois, sans vraiment le simplifier, ça tombe toujours à coté.
Je vous demande de poster une version, avec UNE question qui correspond à l'étape que vous voulez atteindre grâce à une réponse de ma part, et d'attendre ma réponse avant dans poster d'autres versions et d'autres questions, SVP. :oops:
Dans la (l'une des) version(s) sous Git "Juillet 20 (23/07/2024)", les "lInfoQuiMInteresse" et "Une_Fonction_De_La_Classe_SequenceVisionnage" ne devraient pas exister (à moins que c'est pour vos tests de compréhension).
Il y a quasiment systématiquement 2 versions avec le même nom dans Git, faudrait configurer votre client Git pour qu'il nomme "correctement" (de manière unique) les versions sous Git.
Dans cette même version, si vous utilisez correctement le débugueur pour faire du pas à pas, vous devriez voir que la ligne 505 d'Exemple.cpp
pose un problème avec le répertoireCode:std::wregex serie_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\s|\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" };
Car l'expression régulière ne gère pas le fait qu'une paire d'année ne soit pas suivi par un espace.Code:const std::wstring racine = t + L"Star Wars- The Clone wars.[2008-2020].Animation";
Mais cela ne crée pas de disfonctionnement immédiat car le test "std::regex_match(nomDossier, match2, serie_pattern)" est toujours bon, même si le découpage en motif est foireux.
On a la même expression régulière un peu plus loin dans le code, ligne 1236 de serie.cpp, "std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\s|\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?")", qui pose le même problème mais qui entraîne ici un disfonctionnement car le découpage foireux a un impact dans la suite du code.
(Avoir la même expression régulière à 2 endroits différents du code, c'est vraiment pas terrible)
En réordonnant les alternatives de la plus longues à la plus courte et en ajoutant la nouvelle alternative (en rouge dans le code ci-après), et en corrigeant aussi l'expression régulière ligne 1248, ça donne :
Avec ce code, les champs m_f_anneesProduction.first et m_f_anneesProduction.second sont correctement *initialisés.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 Serie::Serie(std::filesystem::path racine) { this->racine = racine; auto nomDossier = racine.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\d{4}|\\d{4}\\-\\s|\\d{4}\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring titres = match[1]; m_titres = Dossier_Titres(titres); 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); } } 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."); } }
On peut, je pense, simplifier les expressions régulières mais vous devez nous donner le format des noms de répertoires/fichiers de manière plus synthétique.
P.S.: est-ce que des schémas comme dans ce post vous permet de mieux comprendre ?
Bonjour,
Ben oui ! Mais, j'ai perdu en capacité !!! C'est vrai ! L'AVC !Citation:
Je vais donc répondre à mes propres questions car vous ne semblez pas pouvoir "facilement" y répondre. (Si vous ne comprenez pas la réponse indiquez le moi explicitement et ce que vous ne comprenez pas dans mon "autoréponse").
- Une structure de données en C est un regroupement d'informations/données.
Ben non !Citation:
- Uns structure de données en C++, c'est comme une structure en C, mais on n'y ajoute les fonctions nécessaires à l'initialisation des données (via le constructeur) et la manipulation "cohérente" de ces données (c'est une très mauvaise définition mais c'est un début et on verra plus tard comment utiliser/concevoir "correctement" une structure/classe C++).
Ok, vous avez peut-être une définition plus "exacte" de ce qu'est une structure en C++.Citation:
Ben non !
Pouvez-vous m'indiquer en quelques mots, avec des exemples si nécessaire, ce qui vous fait dire que "ma" définition simpliste n'est pas la "bonne" ?
Si, c'est "non, je ne sais pas", vous n'avez retenir que ce que j'ai indiqué :
Voulez-vous des schéma graphiques plus "propres" pour vous aider dans la compréhension de l'arborescence de fichier ?Citation:
Une structure de données en C++, c'est comme une structure en C, mais on n'y ajoute les fonctions nécessaires à l'initialisation des données (via le constructeur) et la manipulation "cohérente" de ces données (c'est une très mauvaise définition mais c'est un début et on verra plus tard comment utiliser/concevoir "correctement" une structure/classe C++).
Avez-vous "compris" la correction de la fonction "Serie::Serie(std::filesystem::path racine)" que j'ai proposé dans mon précédent post.
Bonjour,
Peux dormir !
Un peux :Citation:
Ok, vous avez peut-être une définition plus "exacte" de ce qu'est une structure en C++.
Exemples : https://zestedesavoir.com/tutoriels/...-en-c-moderne/
https://zestedesavoir.com/tutoriels/...-les-fichiers/Après, c'est dure !!!
...
https://zestedesavoir.com/tutoriels/...-discographie/
Ben non !Citation:
Pouvez-vous m'indiquer en quelques mots, avec des exemples si nécessaire, ce qui vous fait dire que "ma" définition simpliste n'est pas la "bonne" ?
Si, c'est "non, je ne sais pas", vous n'avez retenir que ce que j'ai indiqué :
Ok ! Oui !!!Citation:
Voulez-vous des schéma graphiques plus "propres" pour vous aider dans la compréhension de l'arborescence de fichier ?
Comment faireCitation:
Avez-vous "compris" la correction de la fonction "Serie::Serie(std::filesystem::path racine)" que j'ai proposé dans mon précédent post.
etCitation:
"compris"
Avant ou plus tard ?Citation:
"précédent post"
Merci:?;)
Ok, ça va être compliqué.
Ce cours fait des simplifications pédagogiques, comme moi, pour permettre l'apprentissage.
Je ne fais pas les mêmes simplifications, car j'essaye de simplifier le propos en fonction de ce que j'essaye de comprendre de vos difficultés.
Donc, un peu d'indulgence "épistémique", SVP.
https://zestedesavoir.com/tutoriels/...-en-c-moderne/
Page générale, table des matières du cours, rien de précis par rapport à ce que je vous avais demandé/expliqué.
https://zestedesavoir.com/tutoriels/...-les-fichiers/
Idem, je vois pas trop le rapport avec ce que je vous avait demandé/expliqué.
https://zestedesavoir.com/tutoriels/...-discographie/
Les structures "Artiste", "Album" ou "Morceau" dans l'article du lien ci-dessus sont des structures qui correspondent à MA définition de structure C, et non C++. Ce type de structure est créable quasi identiquement en C.
Le tutoriel que vous donnez en référence n'a pas été conçu pour aider les programmeurs C à comprendre les différences avec le C++.
Ils nomment "structures C++" un usage très très simplifié des "classes/structures C++" pour mettre le pied à l'étrier à des personnes sans expériences de la programmation.
Quand ce tutoriel (au moins au début) indique "structures C++", il faut comprendre "structure à la C", selon ma définition.
Je n'ai pas lu ce tutoriel, juste survolé, mais ils indiquent que la partie POO n'est pas fini, et c'est la POO qui différentie principalement le C du C++ (au moins au début).
De ce que j'ai survolé, une utilisation C++ d'une structure est faite ici :
https://zestedesavoir.com/tutoriels/...ien-serviables
Dans la structure "Fraction" qui y est présentée, on commence à y insérer des comportements ( par exemple : "simplification()") , pas juste des données ("numerateur" ou "denominateur").
C'est cette différence que je cherche à vous montrer.
Est-ce que vous comprenez maintenant cette différence entre une "structure à la C" et une "structure/class C++" ?
"Ben non !", non quoi ???
Si c'est un refus, vous devez me faire confiance.
Ce qui est indiqué comme "structure C++" dans le tutoriel que vous référencé sont des "structures à la C".
Vous devez comprendre la différence avec une "structure/class C++".
Si "Ben non !", c'est pour votre incapacité à voir la différence, on revient sur le fait qu'une "structure/class C++" contient des comportements (rend des services) en plus de stocker des infirmations.
C'est la différence entre une structure "Artiste", "Album" ou "Morceau" : "structures à la C" ; et la "structure/class C++" Fraction (qui a un comportement/service "simplification" en plus des données).
Je vous fournis un schéma de classe avec le formalisme UML (fait avec de lointain souvenirs, si des personnes peuvent me corriger ce schéma SVP)
Pièce jointe 657588
Si vous avez lu des livres sur la POO, ils ont dû aborder les notations UML.
Je ne trouve pas cela forcément beaucoup plus clair, mais c'est normé et ça fait "plus propre" (moins bricolé).
Si c'est moins lisible pour vous, on fera avec un formalisme moins "standardisé".
Mais vous devriez poser des questions aussi, SVP.
Je vous donne un nouveau code qui fonctionne mieux dans mes post.
Vous n'avez qu'à voir les différences avec le vôtre, comprendre pourquoi celui que je fournis fonctionne mieux que celui d'avant.
Si vous ne comprenez pas pourquoi j'ai fait ces corrections, essayez, avec le débugueur de voir les différences de comportement des 2 codes (le vôtre, et celui que je fourni).
Bin là où j'ai posté le code de la fonction "Serie::Serie(std::filesystem::path racine)".
post du : 24/07/2024, 20h04
Je suis dans le brouillard au niveau de votre niveau de compréhension.
Comprenez-vous maintenant l'architecture générale en 3 étapes du programme ?
Avez-vous compris le mécanisme de création de l'arborescence d'objets construire dans la 2ème étape du programme ?
Qu'est-ce qui vous empêche actuellement de mieux maitriser le programme ?
Si c'est des lignes de code qui ne sont pas claires pour vous, donnez-nous les premières de celles-ci.
Pas fini !!!Citation:
De ce que j'ai survolé, une utilisation C++ d'une structure est faite ici :
https://zestedesavoir.com/tutoriels/...ien-serviables
Dans la structure "Fraction" qui y est présentée, on commence à y insérer des comportements ( par exemple : "simplification()") , pas juste des données ("numerateur" ou "denominateur").
C'est cette différence que je cherche à vous montrer.
Est-ce que vous comprenez maintenant cette différence entre une "structure à la C" et une "structure/class C++" ?
Mais :
https://github.com/laurentbouleau/Exemple : Juillet 21 (27/07/2024)
Vous continuez à ajouter des fonctionnalités (comme l'affichage des durées) sans avoir appliqué aux moins 70% de nos (mes) remarques.
Vous n'allez jamais stabiliser votre programme en continuant comme ça.
Maitrisez les concepts avant de vous en servir (mal) ailleurs.
Votre code devrait fonctionner sans problèmes majeurs avant d'en ajouter. Sinon, vous vous prendrez la tête sur de "faux" problèmes pendant des heures, pour pondre du mauvais code, encore et encore.
Quasiment tous les nouveaux codes sont bancals car concepts encore mal maitrisés ou non prise en compte de nos remarques.
Par exemple :
Dans le constructeur d'InfosVisionnage, à la fin:
Vous avez remplacé
ParCode:file_content.erase(file_content.begin(), file_content.begin() + 0);
Mais vous n'avez pas testé ou mal compris le résultat de l'exécution.Code:file_content.erase(file_content.begin(), file_content.begin() + 1);
https://cplusplus.com/reference/vector/vector/erase/
La documentation indique bien que l'élément "pointé" par le second paramètre ne sera supprimé.
C'est donc le code suivant qu'i faut utiliser :
Testez toujours le code que vous modifiez.Code:file_content.erase(file_content.begin(), file_content.begin() + 2);
(Mais c'est bien que vous ayez pris un peu de temps pour nettoyer le code un peu sale que j'avais fourni)
Dans la fonction "void SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage(...)" :
Vous avez mis en commentaire la seule ligne qui avait un sens :
La fonction "void SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage(...)" n'a pas de sens en elle même.Code://auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804
J'avais donné un nom de fonction comme celui-ci pour indiquer n'importe quelle fonction de la classe, pas pour en créer une avec ce nom en particulier.
C'est la même logique pour les paramètres "...", c'était pour ne pas donner une liste de paramètres en particulier.
Vous ne devriez jamais utiliser ce type de liste de paramètres, car "..." a un sens très précis qui n'a rien a voir avec ce que vous semblez penser.
Désolé pour les noms de fonction "Une_Fonction_De_La_Classe_xxx", les listes de paramètres "..." ou encore les champs "lInfoQuiMInteresse", c'était pour illustrer mon propos avec des noms "génériques", pas à prendre "au pied de la lettre".
Pour la fonction "void Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis)", le type de la valeur de retour de la fonction : "void", n'est pas cohérent avec l'utilité de la fonction : "GetNumeroXXX", c'est pour récupérer un numéro, pas "rien".
Mais comme déjà indiqué, je ne suis pas sûr que la fonction "Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis)" est un intérêt. (cf. les fonctions "PrintFirstSequenceVisionnage" et "PrintSequenceVisionnage" de la classe Episode)
Implémenter "correctement" cette fonction demanderait une bonne maitrise des arcanes du C++.
Stabilisez votre code existant avant de vouloir en ajouter.
Pour la fonction "void Film::initialiser_Duree(std::wstring& m)", l'expression régulière "([01234])?" est très insuffisante pour des valeurs comme "2h 42min" dans "Avatar.(2009-12-16)\Titre.txt".
https://regex101.com/r/Cjhee3/1
Vous ne capturez que le premier "2".
Il faut juste un peu de méthode.
Le format de la durée est composé de 2 parties optionnelles.
- Le nombre d'heures
- Le nombre de minutes "restantes"
Ces 2 parties peuvent être séparées par un espace.
On va donc avoir 2 parties distinctes dans l'expression régulière.
La première partie, c'est le nombre d'heure, donc un ou plusieurs chiffres suivis d'un "h" : \d+h
On veut récupérer/capturer justes les chiffres, donc on ajoute des parenthèses autour de "\d+" : (\d+)h
Il se peut que cela doit un "H" et pas un "h", alors il faut faire une alternative entre "h" et "H" : (\d+)(h|H)
(il y a la possibilité de rendre l'expression régulière "case insensitive" mais pour un point de vue pédagogique, on ne l'utilise pas ici.)
Comme on ne veut pas savoir si c'est un "h" ou un "H", on ajoute un "?:" au début du contenu de la seconde pair de parenthèse : (\d+)(?:h|H)
La seconde partie, c'est le nombre de minutes, donc un ou plusieurs chiffres suivis d'un "min" : \d+min
En appliquant le même raisonnement que pour la partie heure, on obtient : (\d+)(?:min|MIN)
Si on veut récupérer les 2 parties d'un coup, quand elles sont séparées par un espace, on les écrit cote à cote, en spécifiant le séparateur entre, ici "\s" pour l'espace : (\d+)(?:h|H)\s(\d+)(?:min|MIN)
Comme l'espace qui sépare les 2 parties n'est pas obligatoire, on va le rendre optionnel dans l'expression régulière : (\d+)(?:h|H)\s?(\d+)(?:min|MIN)
Comme la première partie n'est pas obligatoire, on va l'encapsulé dans une "capture" optionnelle : (?:(\d+)(?:h|H))?\s?(\d+)(?:min|MIN)
Idem pour la seconde partie qui n'est pas obligatoire : (?:(\d+)(?:h|H))?\s?(?:(\d+)(?:min|MIN))?
A la fin :
(?:(\d+)(?:h|H))?\s?(?:(\d+)(?:min|MIN))?
On aura donc le nombre d'heures dans la capture "1" et le nombre de minutes dans la capture "2". (La capture "0" contient toute la chaine analysée)
En ajoutant un "^" au début et un "$" à la fin pour respectivement correspondre à un début de ligne et à une fin de ligne, ça donne cela dans l'évaluateur en ligne :
https://regex101.com/r/sXgN87/1
Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 22 (28/07/2024)
Pas fini !!! Cercle !!!Citation:
De ce que j'ai survolé, une utilisation C++ d'une structure est faite ici :
https://zestedesavoir.com/tutoriels/...ien-serviables
Dans la structure "Fraction" qui y est présentée, on commence à y insérer des comportements ( par exemple : "simplification()") , pas juste des données ("numerateur" ou "denominateur").
C'est cette différence que je cherche à vous montrer.
Est-ce que vous comprenez maintenant cette différence entre une "structure à la C" et une "structure/class C++" ?
Mais :
Pourquoi ?Code:
1
2
3
4 if (affichage_duree_actif) { duree_str = L' ' + std::to_wstring(m_duree / (60 * 60)) + keyColor[0] + L"h" + valuesColor + L' ' + std::to_wstring(m_duree / 60) + keyColor[0] + L"min " + valuesColor; }
---------------
Ça ne fonctionne pas ! Pourquoi ?Citation:
Dans la fonction "void SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage(...)" :
Vous avez mis en commentaire la seule ligne qui avait un sens :
...
La fonction "void SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage(...)" n'a pas de sens en elle même.
J'avais donné un nom de fonction comme celui-ci pour indiquer n'importe quelle fonction de la classe, pas pour en créer une avec ce nom en particulier.
C'est la même logique pour les paramètres "...", c'était pour ne pas donner une liste de paramètres en particulier.
Vous ne devriez jamais utiliser ce type de liste de paramètres, car "..." a un sens très précis qui n'a rien a voir avec ce que vous semblez penser.
Désolé pour les noms de fonction "Une_Fonction_De_La_Classe_xxx", les listes de paramètres "..." ou encore les champs "lInfoQuiMInteresse", c'était pour illustrer mon propos avec des noms "génériques", pas à prendre "au pied de la lettre".
Pour la fonction "void Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis)", le type de la valeur de retour de la fonction : "void", n'est pas cohérent avec l'utilité de la fonction : "GetNumeroXXX", c'est pour récupérer un numéro, pas "rien".
Mais comme déjà indiqué, je ne suis pas sûr que la fonction "Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis)" est un intérêt. (cf. les fonctions "PrintFirstSequenceVisionnage" et "PrintSequenceVisionnage" de la classe Episode)
Implémenter "correctement" cette fonction demanderait une bonne maitrise des arcanes du C++.
Stabilisez votre code existant avant de vouloir en ajouter.
Et :
Ok !Citation:
Prey.(2022-08-05 Disney+)
Se reposer !!!
Vous posez des questions toujours sur le "nouveau" code sans prendre la peine de corriger l'ancien, on arrivera à rien comme ça.Citation:
Code:
1
2
3
4 if (affichage_duree_actif) { duree_str = L' ' + std::to_wstring(m_duree / (60 * 60)) + keyColor[0] + L"h" + valuesColor + L' ' + std::to_wstring(m_duree / 60) + keyColor[0] + L"min " + valuesColor; }
Ici, vous avez oublié de soustraire le nombre de minutes déjà compté dans les heures.
Code:duree_str = L' ' + std::to_wstring(m_duree / (60 * 60)) + keyColor[0] + L"h" + valuesColor + L' ' + std::to_wstring((m_duree -((m_duree / (60 * 60))*60*60))/ 60) + keyColor[0] + L"min " + valuesColor;
Quel rapport avec les concepts de base du C++ ???Citation:
Pas fini !!! Cercle !!!
Pourquoi voulez-vous que cela marche, si vous ne nous écoutez pas et continuez à pondre du code sans corriger l'existant ?Citation:
Ça ne fonctionne pas ! Pourquoi ?
Attention, les parties sont optionnelles!!!Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 void Film::initialiser_Duree(std::wstring& m) { const std::wregex duree_format_rg{ L"^(?:(\\d+)(?:h|H))?\\s?(?:(\\d+)(?:min|MIN))?$" }; std::wsmatch match; if (std::regex_match(m, match, duree_format_rg)) { auto duree_en_heure = std::stoi(match[1]); auto duree_en_minute = std::stoi(match[2]); m_duree = duree_en_heure * 60 * 60 + duree_en_minute * 60; } else { throw std::invalid_argument("'" + std::string{ m.begin(),m.end() } + "' n'est pas un format de durée valide."); } }
Code:m_duree = (match[1].matched ? std::stoi(match[1]) : 0) * 60 * 60 + (match[2].matched ? std::stoi(match[2]) : 0) * 60;
Bonjour,
https://github.com/laurentbouleau/Exemple : Juillet 23 (29/07/2024)
Attention : Film : Je sais faire, tout seul !!! (Enfin, peux être !!!).
https://zestedesavoir.com/tutoriels/...ien-serviables
const noexcept, noexcept et return distance(cercle.centre, point) <= cercle.rayon;Et :
https://zestedesavoir.com/tutoriels/...ruire-tout-ca/
m_, default, delete
Merci;):?
Code:
1
2
3
4
5
6
7
8
9 void SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage(...) { auto uneInfoDeLEpisode = m_episode.lInfoQuiMInteresse; auto uneInfoDeLaSaison = m_episode.m_saison.lInfoQuiMInteresse; auto uneInfoDeLaSerie = m_episode.m_saison.m_serie.lInfoQuiMInteresse; auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804 }
Comme faire ???
GetNumeroSequenceVisionnage(*this)Pas compris !!!
Merci:weird::aie::aie::calim2:
Bonjour,
Pas dormir !!!
https://github.com/laurentbouleau/Exemple : Juillet 24 (30/07/2024)
Je ai marre !!!
Merci :aie::aie::aie:
https://github.com/laurentbouleau/Exemple : Août 01 (01/08/2024)
Ben, non ! Que faire ???Code:
1
2
3
4
5 const Episode* SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage_xxx(...) { auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804 return *NumeroSequenceVisionnage; }
Tant pis !
Bonjour,
Je n'ai arrive pas ! Je ne sais plus comment faire ! Pouvez-vous expliquer ? Et pas-à-pas !
Google :
Pas de solution !!!Citation:
c++ pointeur et fonction
c++ pointeur sur fonction
c++ pointeur par fonction
c++ pointeur avec fonction
et :
Pièce jointe 657827Code:auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804
Je suis perdu !!!Citation:
Schéma de l'arborescence des objets créées pendant la 2ème étape du programme :
Excusez-moi ! Les jours : 2h ou 3h = je suis crevé !
Désolé !!!
Merci:weird::weird::aie::aie::?:?
Class/Struct : T ?
pointeur et fonction ?
Comment fait ?
Struct SequenceVisionnage, ou struct Episode ?
Je suis fatigue !Code:
1
2 auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804
Merci beaucoup:aie::aie::aie:
Bonsoir,
https://github.com/laurentbouleau/You---Copie : Août 02 (04/08/2024)
https://github.com/laurentbouleau/Exemple : Août 02 (04/08/2024)
L'exemple (serie.cpp) :
Ben non !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 void Serie::initialiser_Titre(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre) { // Titre ... std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s?|\\d{4}\\-\\s?|\\d{4}\\s?)?([^\\]]*)\\])?(?:\\.(.+))?" }; std::wsmatch match; if (std::regex_match(contenu[0], match, filename_pattern)) { t.push_back(match[1]); if (match.length() > 2) { t.push_back(match[2]); } if (match.length() > 3) { t.push_back(match[3]); } } else { t.push_back(contenu[0]); } ... }
L'exemple :
Ok ou 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
24
25
26
27
28
29
30
31
32
33
34
35
36
37 ... std::size_t pos = 0; ... const std::wstring d_p = L" : "; pos = file_content[0].find(d_p); bool found = false; if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p); m_titres.push_back(file_content[0].substr(pos + 3)); found = true; } const std::wstring d_p2 = L": "; pos = file_content[0].find(d_p2); if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p2); m_titres.push_back(file_content[0].substr(pos + 2)); found = true; } const std::wstring d_p3 = L"/"; pos = file_content[0].find(d_p3); if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p3); m_titres.push_back(file_content[0].substr(pos + 1)); found = true; } if (!found) { m_titres.push_back(file_content[0]); found = true; } ...
Merci d'avance:aie::aie::aie:
Désolé pour le délai.
Le cours que vous suivez me semble bon. (Il jouit d'une bonne réputation dans les forum C++)
Que vous ayez des difficultés à tout comprendre du premier coup, et même avec beaucoup de relecture, c'est normal. Il n'y a rien d'évident dans tout cela.
Je ne pense pas mieux expliquer que ce cours dans les "courts" messages que constitue cette "conversation" de forum.
Vous semblez un peu suivre leurs conseils récemment. (ou c'est à force de vous bassiner avec dans mes précédents messages. :aie:)
Vos dernières modifications (transfert de la fonction "const Episode* SequenceVisionnage::Une_Fonction_De_La_Classe_SequenceVisionnage_xxx(...)" à la fonction "void Episode::Une_Fonction_De_La_Classe_SequenceVisionnage_xxx(...)") montre que le concepts d'interface publique d'une classe n'est pas forcément très bien maîtrisé.
Comme c'est moi qui aie "créé" la fonction initiale, c'est peut-être que vous n'avez pas compris le propos de cette fonction.
Le propos de ces fonctions "Une_Fonction_De_La_Classe_xxx", c'est juste des fonctions membres d'une classe ou d'une autre (cf. le nom de la classe dans le nom de la fonction) pour illustrer le fait que chaque classe dispose d'une "interface publique" distincte que l'on peut façonner à ses besoins.
Une fonction "membre" de l'interface publique de la classe "SequenceVisionnage" n'a pas de sens dans une autre classe comme "Episode".
Le nom de ces fonctions n'était peut-être pas très pertinent, c'était juste à titre pédagogique, pour montrer l'utilisation d'une "interface publique" d'une classe dans le code d'une autre classe.
Comme déjà indiqué, implémenter correctement la fonction "int Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis)" se révèle assez complexe.
Vous n'en avez pas vraiment besoin si vous utilisez les fonctions "void Episode::PrintFirstSequenceVisionnage(const SequenceVisionnage& vis)" et "void Episode::PrintSequenceVisionnage(const SequenceVisionnage& vis)" qui seront beaucoup plus simple à faire.
(Et d'un point de vue conception générale, externaliser l'affichage d'un objet dans la console est souvent bien mieux que de l'intégrer à l'interface publique de la classe.)
Pouvons-nous mettre au point ces 2 fontions "Print" avant de revenir sur "GetNumeroSequenceVisionnage" ?
J'espère ne pas vous avoir dit d'utiliser des pointeurs. On verra leurs usages plus tard, si c'est nécessaire.Citation:
Google :
Citation:
c++ pointeur et fonction
c++ pointeur sur fonction
c++ pointeur par fonction
c++ pointeur avec fonction
Pour les messages d'erreur, pas de panique. On verra après pour "GetNumeroSequenceVisionnage" (faut juste comprendre le nom de la fonction => donc son type de valeur de retour).
A cette question précise : je vous pose une autre question :Citation:
Comment fait ?
Struct SequenceVisionnage, ou struct Episode ?
Code:auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804
"logiquement", quel objet peut savoir si une séquence de visionnage est la première d'un épisode, la seconde ou la troisième ?
Pour moi, c'est l'épisode qui trie "ses" séquences de visionnage, donc "GetNumeroSequenceVisionnage" devrait être une fonction de la classe Episode.
Vous pouvez vous dire que non, que votre logique fait que c'est à la classe "SequenceVisionnage" de connaitre "son" ordre, mais c'est, pour moi, moins "naturel" mais aussi beaucoup beaucoup plus de boulot pour rendre ces numéros "cohérents".
Ben non Quoi ???Citation:
L'exemple (serie.cpp) :
Ben non !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 void Serie::initialiser_Titre(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre) { // Titre ... std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s?|\\d{4}\\-\\s?|\\d{4}\\s?)?([^\\]]*)\\])?(?:\\.(.+))?" }; std::wsmatch match; if (std::regex_match(contenu[0], match, filename_pattern)) { t.push_back(match[1]); if (match.length() > 2) { t.push_back(match[2]); } if (match.length() > 3) { t.push_back(match[3]); } } else { t.push_back(contenu[0]); } ... }
L'expression régulière "filename_pattern" est là pour extraire les information du nom du fichier, d'où le nom de la variable "filename_pattern".
Ici, la variable "contenu" n'est pas le nom du fichier mais son contenu, qui ne respecte donc pas les mêmes expressions régulières.
Soit vous vous basez sur le contenu du fichier et il vous faut des expressions régulières proches de celles utilisées dans la fonction "void Saison::initialiser_Titre(std::filesystem::path const& cheminFichier)" comme "titre_pattern" et pas de "filename_pattern".
Soit vous vous basez sur le nom du fichier pour avoir ces informations supplémentaires, vous devez alors légèrement modifier "filename_pattern" pour les récupérer. Mais des caractères comme ":" et "/" posent des problèmes dans les noms de fichier dans les systèmes de fichiers "classiques"/Windows. Cela explique que les expressions régulières sur les NOMS de fichiers ne sont pas les mêmes que sur le CONTENU de fichiers.
En résumé, vous appliquez les expressions régulières aux mauvaises données.
Vous pouvez être plus à l'aise avec des "find" qu'avec des expressions régulières mais si vous les appliquez "mal", l'une comme l'autre, ne fonctionneront pas.
Ici, "find" fonctionne parce que vous appliquez la "bonne" formule aux bonnes données, mais les expressions régulières fonctionnent aussi bien ( même mieux) si vous appliquez les "bons" patterns/motifs aux bonnes données.
Ne disqualifiez pas les expressions régulières parce que vous vous en servez mal et sur les mauvaises données.
Les 37 lignes de code "L'exemple :" sont facilement remplaçables par les ~10 lignes au cœur de "void Saison::initialiser_Titre(std::filesystem::path const& cheminFichier)" tout en étant plus lisible, plus flexible, "sans" bugs (le code à base "find" gère très mal de nombreux cas).
Donc :
Pas OK, car le problème n'est pas là où vous croyez.Citation:
Ok ou pas ?
Bonjour tous mondes,
Pas fini ! Mais :
serie.cpp :
Et :Code:
1
2
3
4
5
6
7 void Saison::Print() { ... // AD Print_Audiodescription(m_audiodescription, affichage_audiodescription_actif, keyColor[1], valuesColor); ... }
Exemple.cpp :
fiml_serie.cpp :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 int wmain(int argc, wchar_t* argv[]) { ... std::size_t pos, pos2; const std::wstring d_p1 = L".("; pos = nomDossier.find(d_p1); const std::wstring d_p2 = L")"; pos2 = nomDossier.find(d_p2); if (!found && pos > 2 && pos2 > (pos + 4 + 1 + 2 + 1 + 2) && pos != std::wstring::npos && pos2 != std::wstring::npos) { Film film(racine); found = true; for (const auto& entry_film : fs::directory_iterator((film.getRacine()))) { if (entry_film.is_regular_file()) { film.initialiser_Fichier(entry_film); } } film.Print(); } const std::wstring d_p3 = L".["; pos = nomDossier.find(d_p3); const std::wstring d_p4 = L"]"; pos2 = nomDossier.find(d_p4); if (!found && pos > 2 && pos2 > (pos + 4) && pos != std::wstring::npos && pos2 != std::wstring::npos) { Serie serie(racine); found = true; for (const auto& entry_serie : fs::directory_iterator((serie.getRacine()))) { if (entry_serie.is_regular_file()) { serie.initialiser_Fichier(entry_serie); continue; } if (fs::is_directory(entry_serie)) { Saison saison(entry_serie, serie); for (const auto& entry_saison : fs::directory_iterator(entry_serie)) { if (entry_saison.is_regular_file()) { saison.initialiser_Fichier(entry_saison); } } serie.saisons.push_back(saison); } } serie.Print(); } ... }
film.cpp :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 std::vector<std::wstring> xyz_Titre(std::wstring& file_content) { // Titre assert(file_content.length() > 0 && L"Nom de titres vide"); // ??? pour Mot de... ? std::vector<std::wstring> titres; std::size_t pos = 0; const std::wstring d_p = L" : "; pos = file_content.find(d_p); bool found = false; if (!found && pos != std::wstring::npos) { titres.push_back(file_content.substr(0, pos)); titres.push_back(d_p); titres.push_back(file_content.substr(pos + 3)); found = true; } const std::wstring d_p2 = L": "; pos = file_content.find(d_p2); if (!found && pos != std::wstring::npos) { titres.push_back(file_content.substr(0, pos)); titres.push_back(d_p2); titres.push_back(file_content.substr(pos + 2)); found = true; } const std::wstring d_p3 = L"/"; pos = file_content.find(d_p3); if (!found && pos != std::wstring::npos) { titres.push_back(file_content.substr(0, pos)); titres.push_back(d_p3); titres.push_back(file_content.substr(pos + 1)); found = true; } const std::wstring d_p4 = L" - "; pos = file_content.find(d_p4); if (!found && pos != std::wstring::npos) { titres.push_back(file_content.substr(0, pos)); titres.push_back(d_p4); titres.push_back(file_content.substr(pos + 3)); found = true; } const std::wstring d_p5 = L"- "; pos = file_content.find(d_p5); if (!found && pos != std::wstring::npos) { titres.push_back(file_content.substr(0, pos)); titres.push_back(d_p5); titres.push_back(file_content.substr(pos + 2)); found = true; } if (!found) { titres.push_back(file_content); found = true; } return titres; }
serie.cpp :Code:
1
2
3
4
5
6
7 std::vector<std::wstring> Film::Dossier_Titres(std::wstring titres) { assert(titres.length() > 0 && L"Nom de titres vide"); // ??? pour Mot de... ? ... m_titres = ::xyz_Titre(titres); return m_titres; }
Par contre :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 ... void Saison::initialiser_Titre(std::filesystem::path const& cheminFichier) { auto nomFichier = cheminFichier.filename().wstring(); assert(nomFichier.length() > 0 && L"Nom de fichier vide"); std::vector<std::wstring> titre = lire_fichierTxt(cheminFichier.wstring(), { L"\n" }); assert((titre.size() != 0)); m_titres = ::xyz_Titre(titre[0]); } ... void Serie::initialiser_Titre(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre) { // Titre auto nomFichier = cheminFichier.wstring(); assert(nomFichier.length() > 0 && L"Nom de fichier vide"); std::vector<std::wstring> contenu = lire_fichierTxt(cheminFichier.wstring(), { L"\n" }); assert((contenu.size() != 0)); ... m_titres = ::xyz_Titre(contenu[0]); contenu.erase(contenu.begin()); if (contenu.size() > 0) { initialiser_Duree(contenu[0]); contenu.erase(contenu.begin()); if (contenu.size() > 0) m_resume = contenu; } }
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 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... const std::wstring d_p = L" : "; pos = file_content[0].find(d_p); bool found = false; if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p); m_titres.push_back(file_content[0].substr(pos + 3)); found = true; } const std::wstring d_p2 = L": "; pos = file_content[0].find(d_p2); if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p2); m_titres.push_back(file_content[0].substr(pos + 2)); found = true; } const std::wstring d_p3 = L"/"; pos = file_content[0].find(d_p3); if (!found && pos != std::wstring::npos) { m_titres.push_back(file_content[0].substr(0, pos)); m_titres.push_back(d_p3); m_titres.push_back(file_content[0].substr(pos + 1)); found = true; } if (!found) { m_titres.push_back(file_content[0]); found = true; } //m_titres = ::xyz_Titre(file_content[0]); } ... }
film_serie.cpp :
Peux être ?Code:
1
2
3
4 void initialiser_Titre_Original(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre_original) { // Titre Original ... }
Je n'y arrive pas !
Merci beaucoup:aie::aie::aie:
Citation:
Vos dernières modifications (transfert de la fonction "const Episode*
...
Les 37 lignes de code "L'exemple :" sont facilement remplaçables par les ~10 lignes au cœur de "void Saison::initialiser_Titre(std::filesystem::path const& cheminFichier)" tout en étant plus lisible, plus flexible, "sans" bugs (le code à base "find" gère très mal de nombreux cas).
Bonsoir,
https://github.com/laurentbouleau/Exemple : Août 04 (07/08/2024)
serie.cpp :
m_titres = :: xyz_Titre(...) : Ok (serie.cpp, fiml.cpp et film_serie.cpp) et void initialiser_Titre_Original(...) : ok !Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 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) { if (file_content[0] == L"") return; std::size_t pos = 0; if (m_NumeroEpisode != 0) { pos = file_content[0].find(L". "); file_content[0] = file_content[0].substr(pos + 2); } m_titres = ::xyz_Titre(file_content[0]); } ... }
Ok ou non ?Code:
1
2 if (file_content[0] == L"") return;
Ok ou pas ! Mais, peux être ? Ou un autre ?Code:
1
2
3
4
5 if (m_NumeroEpisode != 0) { pos = file_content[0].find(L". "); file_content[0] = file_content[0].substr(pos + 2); }
m_titres : Pas fini !!!
Mais :
Regeix ???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 std::vector<std::wstring> xyz_Titre(std::wstring& titre) { // Titre assert(titre.length() > 0 && L"Nom de titres vide"); // ??? pour Mot de... ? std::wstring& t = titre; std::vector<std::wstring> titres; std::size_t pos = 0; bool found = false; const std::wstring d_p = L" : "; pos = t.find(d_p); if (!found && pos != std::wstring::npos) { titres.push_back(t.substr(0, pos)); titres.push_back(d_p); titres.push_back(t.substr(pos + 3)); found = true; } const std::wstring d_p2 = L": "; pos = titre.find(d_p2); if (!found && pos != std::wstring::npos) { titres.push_back(t.substr(0, pos)); titres.push_back(d_p2); titres.push_back(t.substr(pos + 2)); found = true; } const std::wstring d_p3 = L"/"; pos = t.find(d_p3); if (!found && pos != std::wstring::npos) { titres.push_back(t.substr(0, pos)); titres.push_back(d_p3); titres.push_back(t.substr(pos + 1)); found = true; } const std::wstring d_p4 = L" - "; pos = t.find(d_p4); if (!found && pos != std::wstring::npos) { titres.push_back(t.substr(0, pos)); titres.push_back(d_p4); titres.push_back(t.substr(pos + 3)); found = true; } const std::wstring d_p5 = L"- "; pos = t.find(d_p5); if (!found && pos != std::wstring::npos) { titres.push_back(t.substr(0, pos)); titres.push_back(d_p5); titres.push_back(t.substr(pos + 2)); found = true; } if (!found) { titres.push_back(t); found = true; } return titres; }
et xyz_Titre un autre (exemple : void initialiser_Nationalite(...) ?
Je suis crevé !!!
Merci:aie::aie::aie:
Très bien, vous restez motivé et assez autonome.
Mais, comme je l'ai déjà dit, il faudrait mieux fiabiliser le code plutôt que d'ajouter de nouvelles fonctionnalités. cf. Print_Audiodescription
(A moins que ces fonctionnalités servent à simplifier le code existant, ça c'est cool. cf. xyz_Titre (mais c'est un nom "horrible" !))
Votre code semble "fonctionner", donc, mes remarques sont plus de l'ordre du vieux con qui aime bien les choses "carrées", ou du vieil oracle aveugle qui voit les emmerdes arrivées à des années lumières.
_
_
Vous mentionnez la fonction "Print_Audiodescription" dans le précédent message mais la fonction semble exister depuis un petit moment, mais elle n'était pas dans les "problèmes" qui vous bloquait.
Si, c'est pour vous mettre en confiance avec votre maitrise du C++, OK, dont acte, mais restez focus pour résoudre les difficultés l'une après les autres.
_
"Print_Audiodescription" est une fonction libre qui permet de gérer l'affichage de l'audiodescription aussi bien d'un Film que d'une Serie.
Avoir le réflexe d'utiliser une fonction libre quand du code dans 2 classes distinctes se ressemble, c'est bien.
_
Mais Film et Serie sont quand même, il me semble, des concepts assez proches.
Ce qui me "dérange" dans la fonction "Print_Audiodescription", c'est de passer pas mal de paramètres issus des champs de ces classes Film et Serie, partant les mêmes noms ou presque.
Il serait plus "naturel" de faire une classe "Mère" aux classes "Film" et "Serie" qui regrouperait tout ce qui est commun aux 2 classes, une classe "Media", par exemple.
Dans ce cas, il serait plus "logique" de faire de la fonction "Print_Audiodescription" une fonction membre de la classe mère "Media". (Les légères différences seraient facilement gérées par quelques champs supplémentaires dédiés)
_
Vous pouvez trouver que ce rapprochement des classes Film et Serie soit un peu "artificiel" et que les noms de leurs champs respectifs soit identiques par pure coïncidence.
Si c'est le cas, alors je ferais en sorte de gommer tout lien avec les champs des classes Film et Serie, aussi bien en termes de nom de paramètre, de variables locales, etc...
Ainsi, c'est fonction "Print_Audiodescription" pourrait être encore plus généralistes.
Chose qu'il faut faire au maximum pour les fonctions libres qui ne font pas implicitement partie d'une interface publique d'une classe (cf. l'utilisation du "friend" dans le cours que vous mentionnez en référence).
En supprimant toute référence à Audiodescription mais que vous gardiez la logique d'afficher 2 choses (une clé + une valeur) dans 2 couleurs potentiellement différentes, vous devriez vous retrouver avec une fonction libre bien plus polyvalente/généraliste :
(Encore que le paramètre "actif" me semble superfétatoire, comme déjà indiqué depuis des mois.)Code:
1
2
3
4
5
6
7
8 void Print_CleValeur(const std::wstring& cle, const std::wstring& valeur, bool actif, std::wstring& keyColor, std::wstring& valuesColor) { if (actif && valeur.size() > 0) { std::wstring valeur_str = keyColor + cle + L" : " + valuesColor + valeur+ L"\r\n"; std::wcout << valeur_str ;// << std::endl; } }
_
_
Pour la partie liée à "int wmain(int argc, wchar_t* argv[])", votre code montre que vous "abandonnez" l'utilisation des expressions régulières pour l'utilisation de "find", plus simple à comprendre mais bien plus limité.
Dont acte, votre code est plus verbeux mais comme vous ne gérez pas encore les parties optionnelles et que vous n'avez pas encore fait d'erreur d'inattention "il fonctionne" dans les cas "simples".
Pour gérer les parties optionnelles, votre approche à base de "find" va devenir un enfer, je pense.
Et cela ne règle pas le problème "de fond" que vous avez eu avec les expressions régulières : confondre le format des noms de fichier et le format dans le contenu des fichiers.
Avec l'approche à base de "find", on se retrouve avec des formules cabalistes comme ceci :
A quoi correspond le 4 ? le premier 1 ? le premier 2 ? le second 1 ? le second 2 ?Code:pos2 > (pos + 4 + 1 + 2 + 1 + 2)
Comment changer ces valeurs si les séparateurs changent ?
Encore plus probable dans votre code qui est fait de beaucoup de copier-coller, comment changer ces valeurs après un copier-coller et un changement de séparateurs ?
Vous devriez utiliser des constantes qui correspondent à ce à quoi elles font références, comme "c_annee_size" à la place de "4", etc...
Ces formules à base de "pos + x ...." sont de plus fausses, sauf dans des cas très très simples.
Cas simples qu'une expression régulière simple comme "(.*?)\.\((.*?)\)(.*?)" gèrerait aussi bien, (voire bien bien mieux).
Donc, si vous voulez continuer avec une solution à base de "find", vous devriez réduire vos prétentions en termes de richesse de formats possibles et aussi simplifier son utilisation en n'utilisant pas de valeur "en dur".
Il y a quelques autres détails qui me gênent dans cette implémentation à base de "find", comme l'appel inutile à la fonction "find" quand on sait déjà que cela ne servira à rien, mais c'est négligeable par rapport à la fragilité et au manque de polyvalence/souplesse de cette montagne de code.
_
_
"xyz_Titre", c'est quoi ce nom de fonction sorti des enfers ???
Reprenons ce que fait cette fonction, sans se faire abuser par les noms des arguments et des variables locales qui n'ont toujours pas le soin nécessaire pour avoir un code "sain".
Cette fonction "extrait" les titres/sous-titres d'une ligne de texte (et pas d'un nom de fichier ou de répertoire qui ne peuvent pas contenir de ":" ou de "/" dans la quasi-totalité des systèmes de fichiers).
Donc, un nom "raisonnable" à cette fonction, ça pourrait être "extraire_Titres_Depuis_UneLigne".
Avec le suffixe "_Depuis_UneLigne", qui serait en opposition avec de potentielles fonctions avec un suffixe "_Depuis_NomDeFichier_Ou_NomDeRepertoire", on pourrait voir que la ligne 184 de film.cpp :
n'a aucun sens, car, ici, "titres" contient un bout du nom du fichier et pas une ligne contenu DANS le fichier.Code:m_titres = ::xyz_Titre(titres);
On en revient toujours à "correctement" nommer les choses.
Avec les expressions régulières, le nom des variables indiquait leur usage et pouvait faire détecter l'anomalie en utilisant la "mauvaise" expressions régulières sur le mauvais type de données.
Avec l'utilisation d'une fonction libre très très mal nommée, ce mauvais usage est beaucoup moins facile à détecter.
Comme pour "wmain", le code est très très long tout en étant très fragile et peu souple.
_
_
"Film::Dossier_Titres", comme indiqué ci-avant, l'utilisation de la fonction "xyz_Titre" est une grosse erreur (pas mélanger nom de fichier/répertoire avec le contenu d'une ligne dans un fichier).
_
_
Mauvais nom de variable, ce n'est pas le titre mais le contenu du fichier.Citation:
Code:
1
2
3
4
5
6
7
8 void Saison::initialiser_Titre(std::filesystem::path const& cheminFichier) { auto nomFichier = cheminFichier.filename().wstring(); assert(nomFichier.length() > 0 && L"Nom de fichier vide"); std::vector<std::wstring> titre = lire_fichierTxt(cheminFichier.wstring(), { L"\n" }); assert((titre.size() != 0)); m_titres = ::xyz_Titre(titre[0]); }
Code identique à "Saison::initialiser_Titre", pourquoi ne pas les fusionner dans une fonction libre ou dans une fonction d'une classe mère ?Citation:
Code:void Serie::initialiser_Titre(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre)
Ce qui diffère "Serie::initialiser_Titre" de "Saison::initialiser_Titre" n'a rien à faire dans "Serie::initialiser_Titre".
Dans la ligne :
dans la fonction "Serie::initialiser_Titre", "m_titres", c'est quoi ? le paramètre de la fonction "Serie::initialiser_Titre" ou le champ de la classe "Serie" ???Code:m_titres = ::xyz_Titre(contenu[0]);
N'utilisez pas de préfixe "m_" pour des paramètres.
Si possible, n'utilisez pas de paramètre inutile au bon fonctionnement de la fonction.
_
_
Le code que vous postez est censé remplacer :Citation:
Code:InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison }
J'ai indiqué en rouge dans l'expression régulière, le fait que la ligne peut commencer par le numéro de l'épisode.Code:
1
2
3
4
5
6
7
8
9
10
11
12 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]); }
Le fichier ".\Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga\2021-11-02\1x1.2021-07-16_08-01_.txt" commence par la ligne :
Pour avoir le même "niveau de service" que la version avec expression régulière, il faut donc gérer le fait que le numéro d'épisode puisse apparaître en début de ligne.Citation:
1. La phrase : verbre
_
_
Quelle est la question ?Citation:
Code:void initialiser_Titre_Original(fs::path const& cheminFichier, std::vector<std::wstring>& m_titre_original)
("m_titre_original", encore ces foutus "m_" dans les noms de paramètres !!!)
Même remarque que pour "Print_Audiodescription", une fonction libre ou une fonction membre d'une classe mère "Media" ?
Moi, pour une fonction libre, je retournerais le résultat en valeur de retour de la fonction :
Et quelques modifications pourraient la rendre beaucoup plus polyvalente.Code:
1
2
3
4
5
6 std::vector<std::wstring> initialiser_Titre_Original(fs::path const& cheminFichier) { std::vector<std::wstring> resultats; ... return resultats; }
_
_
P.S.: vous devriez dégager tous ces "extern ..." dans vos .cpp car ils ne servent à rien dans votre cadre de développement sans bibliothèques statiques.
NON !!!Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11 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) { if (file_content[0] == L"") return; ...
Vous ne gérez pas correctement le fait que le numéro de l'épisode est optionnel, juste que le fichier peut être vide.
Et évitez les "return" au milieu d'une fonction.
C'est quoi la "logique" de ce test ???Citation:
Code:if (m_NumeroEpisode != 0)
Evitez de modifier des variables qui servent ailleurs.Citation:
Code:
1
2
3
4
5
6 if (m_NumeroEpisode != 0) { pos = file_content[0].find(L". "); file_content[0] = file_content[0].substr(pos + 2); } m_titres = ::xyz_Titre(file_content[0]);
Code:
1
2
3
4
5
6
7
8
9
10 const std::wstring separateur_numero_episode = L". "; ... auto title_line = file_content[0]; if (m_NumeroEpisode == -1) { pos = title_line.find(separateur_numero_episode); title_line = title_line.substr(pos + separateur_numero_episode.length()); } m_titres = ::xyz_Titre(title_line);
Oui, exactement celles que vous avez mise en commentaire :Citation:
Regeix ???
Code:std::wregex titre_pattern{L"(.+?)(\\s\\:\\s|\\:\\s|/|\\s\\-\\s|\\-\\s)(.+)"}
Bonsoir,
Peu dormi !!! Les Acouphènes : plus fort ! Et hier L'ORL (Médecin) ! Enfin...
Pas fini ! m_titres !
https://github.com/laurentbouleau/Exemple : Août 05 (08/08/2024)
Et : https://regex101.com/r/hu1CUo/1 : Pas fini, mais ça va ! Expliquez-moi !
Et : hexadécimale (std::vector<std::wstring> extraire_Titres_Depuis_UneLigne(std::wstring& titre) ??? Comment pos et find !
Merci beaucoup:aie::aie::aie:
Il reste toujours un problème dans la fonction "Film:: Dossier_Titres" où vous utilisez la fonction "extraire_Titres_Depuis_UneLigne" avec une partie du nom du fichier et non une ligne de son contenu.Citation:
Pas fini ! m_titres !
Dans la fonction "Serie:: Dossier_Titres", vous ne faites pas cette erreur.
Ok.Citation:
votre expression régulière :
(.+?)(?:\.\((\d{4}\-\d{2}\-\d{2}\s)?([^\)]*)\))?(?:\.(.+))?
J'ai mis en rouge les "?" qui font que la capture entre parenthèse () juste avant est optionnelle.
On a donc 3 grandes parties dans l'expression régulière :
(.+?)(?:\.\((\d{4}\-\d{2}\-\d{2}\s)?([^\)]*)\))?(?:\.(.+))?
La capture bleu n'est pas optionnelle, les 2 autres le sont.
Par défaut, une capture est "greedy" (gloutonne), c'est à dire qu'elle capture le maximum de caractères qu'elle peut, quitte à ce que les captures qui suivent échouent.
Le "?" dans la capture bleu : (.+?), c'est pour faire l'inverse du greedy/glouton, en prendre le moins possible pour que les captures qui suivent réussissent.
Comme dans votre expression régulière, les 2 captures qui suivent sont optionnelles, le moteur de règle que vous avez sélectionné "PCRE2 (PHP >=7.3)" (parce que c'est le genre de détails qui peut changer d'un moteur d'expression régulière à un autre), la première capture "attrape" un caractère, le premier de la ligne ; pour la 2ème capture ça doit commencer par un ".(" => échec ; pour la 3ème capture ça doit commencer par un "." => échec : comme les 2 dernières captures sont optionnelles, ça passe :
1ère capture : le 1er caractère
2ème capture : rien
3ème capture : rien
Après, le moteur continu à la suite pour appliquer l'expression régulière au reste de la ligne, donc pour la seconde itération de l'évaluation de l'expression régulière :
1ère capture : le 2ème caractère
2ème capture : rien
3ème capture : rien
ect...
A la 27ème itération de l'application de l'expression régulière sur la ligne contenant "Avatar 2 - la voie de l'eau.(2022-12-14)":
1ère capture : "u" ( le 27ème caractère )
2ème capture : ".(2022-12-14)"
3ème capture : rien
Maintenant qu'on sait pourquoi "ça marche pas", il faut trouver un moyen pour que la capture bleu prennent la chaine la plus longue même si les captures vertes et jaunes sont optionnelles.
Vient ici un caractère à la signification spéciale : "$" pour "fin de ligne".
(.+?)(?:\.\((\d{4}\-\d{2}\-\d{2}\s)?([^\)]*)\))?(?:\.(.+))?$
https://regex101.com/r/OdNHtb/1
En ajoutant la condition que le moteur doit capturer toute une ligne en une itération, vous forcez la capture bleu à prendre d'un coup tout ce qui est avant le ".(" de la capture verte et/ou tout ce qui est devant le "." de la capture jaune.
P.S.: Le caractère spéciale "^" peut aussi spécifier "début" de ligne.
https://regex101.com/r/mcjxdt/1
Bonjour,
Je suis fatigué ! Les Acouphènes : plus fort !!! Rendez-vous : ORL : 30/09/2024 ! Rrrr !!!
Donc, marche pas !!!
ouCode:std::wregex nomDossier_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Exemple :Code:std::wregex nomDossier_pattern{ L"^(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Ok !!!Code:const std::wstring racine = t + L"Star Wars- The Clone Wars.(2008-08-27).Animation";
Code:const std::wstring racine = t + L"Avatar 2 - la voie de l'eau.(2022-12-14)";
Code:const std::wstring racine = t + L"Prey.(2022-08-05 Disney+)";
Mais (avant serie.cpp) :
Marche-pas !!!Code:const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga";
Pouvez-vous expliquer ?
Sinon :
https://fr.wikipedia.org/wiki/Expres...A9guli%C3%A8re : Difficile à dire !!!
POSIXAvec :
et/ou
Unicode
Ici : https://stackoverflow.com/questions/8666378/detect-windows-or-linux-in-c-cCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */ #define OS_Windows 0 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #elif defined(_WIN32) || defined(WIN32) /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */ #define OS_Windows 1 #include <windows.h> #include <stdio.h> #include <tchar.h> #define DIV 1048576 #define WIDTH 7 #endif
Ou :
https://learn.microsoft.com/fr-fr/cp...?view=msvc-170
https://www.boost.org/doc/libs/1_32_...ix_windows.cpp
Etc...
Et exemple :
Exemple.h
et/ou
std::vector<std::wstring> extraire_Titres_Depuis_UneLigne(std::wstring& titre)
Voilà ! C'est tout !
Merci d'avance:aie::aie::aie:
Ou :
Projet CMake ?
Application de bureau Windows (int windmain(...) mais simple !!!
Bonsoir,
https://github.com/laurentbouleau/Exemple : Août 06 (09/08/2024)
film_serie.cpp :
Pas fini ! Mais, titres.??? avec pourcentage ? (exemple : 80%)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 void abc_Titres(std::vector<std::wstring>& m_titres, std::vector<std::wstring>& titres) { assert(m_titres.size() < 4 && L"???"); assert(titres.size() < 4 && L"???"); bool found = false; if (m_titres == titres) found = true; else { if (titres.size() == m_titres.size()) { if (titres.size() == 1 && m_titres.size() == 1) { m_titres = titres; found = true; } if (titres.size() == 3 && m_titres.size() == 3 && titres[0] == m_titres[0] && titres[1] != m_titres[1] && titres[2] == m_titres[2]) { m_titres[1] = titres[1]; found = true; } if (titres.size() == 3 && m_titres.size() == 3 && (titres[0] != m_titres[0] || titres[1] != m_titres[1] || titres[2] != m_titres[2])) { m_titres = titres; found = true; } } } }
Merci vraiment:aie::aie::aie:
Bonsoir,
https://github.com/laurentbouleau/Exemple : Août 07 (10/08/2024)
serie.cpp :
Ok ou pas !Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... if (file_content.size() > 0 && file_content[0] != L"") { std::size_t pos = 0; if (m_NumeroEpisode != 0) { pos = file_content[0].find(L". "); file_content[0] = file_content[0].substr(pos + 2); } m_titres = ::extraire_Titres_Depuis_UneLigne(file_content[0]); } ... }
Merci :?:roll::aie:
https://github.com/laurentbouleau/Exemple : Août 08 (10/08/2024)
Etc...Code:const std::size_t c_annee_size = 4;
https://github.com/laurentbouleau/Exemple : Août 09 (12/08/2024)
void Print_Audiodescription(...) ===> void Print_CleValeur(...)
Merci;)
Bonjour,
https://github.com/laurentbouleau/Exemple : Août 11 (13/08/2024)
film.cpp :
Donc :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 void Film::initialiser_Making_of(std::filesystem::path const& cheminFichier) { auto nomFichier = cheminFichier.wstring(); assert(nomFichier.length() > 0 && L"Nom de fichier vide"); std::vector<std::wstring> contenu = lire_fichierTxt(cheminFichier.wstring(), { L"\n" }); assert((contenu.size() != 0)); if (contenu.size() > 0) { m_making_of_duree = initialiser_Duree(contenu[0]); contenu.erase(contenu.begin()); if (contenu.size() > 0) { m_making_of_resume = contenu; m_making_of = true; } } }
Making-of.txtet/ou0h 18min
Netflix a partagé un making-of de la fabrication du film Sous La Seine, avec un focus sur les effets visuels, avec les explications de Arnaud Fouquet.
Les assets CGI du requin ont été supervisés par Florian Wolff côté MPC Paris et Ryan Bardoul de MPC Liège.
Making-of.txtet/ou
Making-of.txtet/ou0h 18min
Making-of.txtQue faire ?Netflix a partagé un making-of de la fabrication du film Sous La Seine, avec un focus sur les effets visuels, avec les explications de Arnaud Fouquet.
Les assets CGI du requin ont été supervisés par Florian Wolff côté MPC Paris et Ryan Bardoul de MPC Liège.
--------
Et :
Expliquez-moi ! Mais simple !!!Code:auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this);
(Problème : Les acouphènes : plus forts)
Merci:aie::aie::aie:
Bonjour,
https://github.com/laurentbouleau/Exemple : Août 12 (14/08/2024)
Etc...Code:
1
2
3 std::wstring m_min = L"min"; std::vector<std::wstring>m_keyColor{ L"\x1b[94;1m", L"\x1b[38;2;0;255;0m" }; // keyColor[0] (bleu) et keyColor[1] (vert) std::wstring m_valuesColor = L"\x1b[38;2;255;255;255m"; // Blanc
Merci:roll:
Bonsoir,
https://github.com/laurentbouleau/Exemple : Août 13 (15/08/2024)
serie.cpp :
Ok !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 void Saison::Print_Header() { std::wstring hors_saison_str; if (m_hors_saison) hors_saison_str += m_keyColor[1] + L"Hors Saison : " + m_valuesColor; wchar_t date_tab[15]; std::wstring date_str{}; if (m_date_diffusee_a_partir_de.first.tm_mday == -1 && m_date_diffusee_a_partir_de.first.tm_mon == -1) { 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 == -1) { 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) + m_keyColor[1] + L'/' + m_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) + m_keyColor[1] + L'/' + m_valuesColor + date_tab_str.substr(3, 2) + m_keyColor[1] + L'/' + m_valuesColor + date_tab_str.substr(6, 4); } std::wstring dossier_str; if (m_date_diffusee_a_partir_de.second != L"") dossier_str = m_keyColor[0] + m_date_diffusee_a_partir_de.second + m_valuesColor + L' '; std::wstring titre_str; if (m_titres.size() != 0) { titre_str = m_keyColor[0] + m_titres[0] + m_valuesColor; if (m_titres.size() > 1) { titre_str += m_keyColor[1] + m_titres[1] + m_valuesColor + m_keyColor[0] + m_titres[2] + m_valuesColor; } titre_str += m_keyColor[1] + L" : " + m_valuesColor; } std::wstring resume_str; if (m_serie.m_resume != m_resume) { for (auto r : m_resume) resume_str += r; } else { resume_str = stringFormatOneLine(m_resume.size() > 0 ? m_resume[0] : L"", 40 + 3 + 5, L"...", 3, m_keyColor[1] + L'(' + m_valuesColor + L"Bis" + m_keyColor[1] + L')' + m_valuesColor, 5); } std::wstring numero_str = L' ' + m_keyColor[1] + L'(' + m_valuesColor + std::to_wstring(m_numero) + m_keyColor[1] + L')' + m_valuesColor; std::wcout << hors_saison_str << date_str << dossier_str << m_keyColor[1] + L" : " + m_valuesColor << titre_str << resume_str << numero_str << std::endl; }
Mais :
Pas ok !!!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 Serie::Serie(std::filesystem::path racine) { this->racine = racine; auto nomDossier = racine.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\d{4}|\\d{4}\\-\\s|\\d{4}\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring titres = match[1]; m_titres = Dossier_Titres(titres); 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::wstring sur = (match[3].matched) ? match[3].str() : L""; m_sur = sur; 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 attention (film_serie.cpp) :
Ben !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 ... const std::vector<std::wstring> Sur { L"Apple TV+", L"Amazon Prime Video", L"Crunchyroll", L"Disney+", L"DVD", L"Netflix", L"SⱯLTO", L"VOD" }; ...
Pourquoi ?Code:std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\d{4}|\\d{4}\\-\\s|\\d{4}\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" };
Et : exemple :
Dr. STONE.[2019-2022 Crunchyroll].MangaPièce jointe 658271
???
Merci:aie::calim2::weird:
Bonjour,
https://github.com/laurentbouleau/Exemple : Août 14 (16/08/2024)
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 Serie::Serie(std::filesystem::path racine) { this->racine = racine; auto nomDossier = racine.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\d{4}|\\d{4}\\-\\s|\\d{4}\\s|\\d{4})?([^\\]]*)\\])?(?:\\.(.+))?" }; // Marches pas !!! std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring titres = match[1]; m_titres = Dossier_Titres(titres); 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::wstring sur = (match[3].matched) ? match[3].str() : L""; //void initialiser_Sur(std::wstring& m_s) m_sur = sur; 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."); } }
Je suis crevé !!! J'en ai marre ! (Les Acouphènes)Code:
1
2
3
4
5
6 void Episode::GetNumeroSequenceVisionnage(const SequenceVisionnage& sev_vis) { //... //auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this); // ??? #804 auto NumeroSequenceVisionnage = /*m_episode.*/GetNumeroSequenceVisionnage(sev_vis); // ??? #804 }
Merci d'avance:aie::aie::aie:
Attention, je trouve que vous ajoutez/cherchez pas mal de choses sans fiabiliser avant correctement les fonctionnalités déjà implémentées. (projet CMake, code "portable", etc...)
Citation:
Donc, marche pas !!!
ouCode:std::wregex nomDossier_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Exemple :Code:std::wregex nomDossier_pattern{ L"^(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Code:const std::wstring racine = t + L"Star Wars- The Clone Wars.(2008-08-27).Animation";
Code:const std::wstring racine = t + L"Avatar 2 - la voie de l'eau.(2022-12-14)";
Ok !!!Code:const std::wstring racine = t + L"Prey.(2022-08-05 Disney+)";
Mais (avant serie.cpp) :
Marche-pas !!!Code:const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga";
Pouvez-vous expliquer ?
Qu'est-ce qui ne fonctionne pas précisément ???Citation:
Donc, marche pas !!!
"Ok" quoi ???Citation:
Ok !!!
Mais quoi ???Citation:
Mais (avant serie.cpp) :
J'ai décommenté ces fameuses lignes (et un peu "corrigé") :
et corrigé la ligne qui les précède :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 ... std::wregex nomDossier_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s?)?([^\\)]*)\\))?(?:\\.(.+))?$" }; ... std::wsmatch match; if (!found && std::regex_match(nomDossier, match, nomDossier_pattern)) { Film film(racine); found = true; for (const auto& entry_film : fs::directory_iterator((film.getRacine()))) { if (entry_film.is_regular_file()) { film.initialiser_Fichier(entry_film); } } film.Print(); }...
Et la/le "détection/décodage" du nom du répertoire c'est très bien passé(e) pour les 3 exemples de film que vous données (Star Wars- ..., Avatar 2 - ..., Prey...).Code:if (!found && pos > 2 && pos2 > (pos + 4 + 1 + 2 + 1 + 2) && pos != std::wstring::npos && pos2 != std::wstring::npos){}
Les objets "film" créé à la ligne "Film film(racine);" ont des champs mal initialisées car vous n'avez pas mis à jour l'expression régulière que vous utilisez dans le constructeur de la classe Film.
Vous ne devriez pas avoir 2 "chaines de caractère/motifs" pour initialiser ces variables/constantes pour cette expression régulière "commune" mais utiliser la même chaine de caractère aussi bien dans le constructeur de la classe Film que dans la fonction "wmain".
Mettre ce motif en tant que constante statique de la classe Film me paraît l'endroit le plus logique.
Une fois correctement "synchronisé", je ne vois pas où est le problème avec cette expression régulière. :aie:
Pour 'const std::wstring racine = t + L"Azertyuiop - qsdfghjklm.[2021-2023 Netflix].Manga";', c'est "normal" que l'expression précédente ne la "capte" pas car elle utilise des [] car, si je ne me trompe pas, c'est une série, pas un film.
Il faut donc prendre (et corriger) l'expression régulière correspondant à une série, pas à celle des film.
(A moins que vous pensiez, qu'in fine, les motifs d'un répertoire d'un film ou d'une série seront identiques ???)
Il faut aussi faire en sorte que le constructeur de la classe Serie et la fonction "wmain" utilise le même motif.
Pouvez-vous expliquer ce qui ne va pas concrètement ???Citation:
Pouvez-vous expliquer ?
Il vaut mieux prendre une documentation plus spécifique à votre compilateur :Citation:
Sinon :
https://fr.wikipedia.org/wiki/Expres...A9guli%C3%A8re : Difficile à dire !!!
POSIX
et/ou
Unicode
https://learn.microsoft.com/fr-fr/cp...?view=msvc-170
Vous avez donc le choix. Mais je vous conseille de, d'abord, maitriser les réglages "de base".
Quel rapport avec votre projet actuel ???Citation:
Avec :
Ici : https://stackoverflow.com/questions/...r-linux-in-c-cCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */ #define OS_Windows 0 #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #elif defined(_WIN32) || defined(WIN32) /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */ #define OS_Windows 1 #include <windows.h> #include <stdio.h> #include <tchar.h> #define DIV 1048576 #define WIDTH 7 #endif
Ou :
https://learn.microsoft.com/fr-fr/cp...?view=msvc-170
https://www.boost.org/doc/libs/1_32_...ix_windows.cpp
Etc...
Quel est la question ???Citation:
Et exemple :
Exemple.h
et/ou
std::vector<std::wstring> extraire_Titres_Depuis_UneLigne(std::wstring& titre)
Pour savoir où déclarer et où définir une fonction, c'est dépendant du périmètre d'utilisation de cette fonction.
Si c'est très généraliste, dans une paire de fichier "util.h/util.cpp", c'est assez naturel. Mais c'est pas super car une fonction n'est jamais totalement "généraliste". (niveau d'abstraction, type de concepts/librairies elle utilise, découpage en module du projet, etc...)
Quel rapport avec votre projet actuel ???Citation:
Ou :
Projet CMake ?
Application de bureau Windows (int windmain(...) mais simple !!!
Du code portable ou avec une API graphique, c'est pas vraiment plus simple que du code pour une API console.
Un petit effort sur le nom des fonctions et des paramètres, SVP.Citation:
Code:void abc_Titres(std::vector<std::wstring>& m_titres, std::vector<std::wstring>& titres)...
Et votre implémentation me semble plutôt complexe.Code:std::vector<std::wstring> fusionner_Titres(std::vector<std::wstring>& vieux_titres, std::vector<std::wstring>& nouveaux_titres)...
Une simple boucle devrait faire le boulot.
De quel "pourcentage" parlez-vous ???Citation:
Pas fini ! Mais, titres.??? avec pourcentage ? (exemple : 80%)
Bof, ne modifiez pas le contenu de variables utilisées ailleurs, utilisez des variables dédiées (et utilisez les bonnes conditions dans les if).Citation:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... if (file_content.size() > 0 && file_content[0] != L"") { std::size_t pos = 0; if (m_NumeroEpisode != 0) { pos = file_content[0].find(L". "); file_content[0] = file_content[0].substr(pos + 2); } m_titres = ::extraire_Titres_Depuis_UneLigne(file_content[0]); } ... }
Code:
1
2
3
4
5
6
7
8
9
10
11 InfosVisionnage::InfosVisionnage(const Saison& saison, fs::path const& m_cheminFichier) : m_saison{ saison } { ... if (file_content.size() > 0) { std::size_t pos = file_content[0].find(c_separateur_numero_titre_dans_ligne_de_fichier); auto ligne_titres= (pos != std::wstring::npos) ? file_content[0].substr(pos + c_separateur_numero_titre_dans_ligne_de_fichier.length()) : L""; m_titres = ::extraire_Titres_Depuis_UneLigne(ligne_titres); } ... }
Pourquoi en faire une variable locale à la fonction "wmain", vu que c'est une constante.Citation:
Code:const std::size_t c_annee_size = 4;
Elle devrait être globale.
GitHub Desktop (mon client Git) n'arrive pas à m'indiquer les modifications dans "Exemple.cpp" parce qu'il ne gère pas des sources en UTF-8/16.
SIMPLIFIEZ votre code :
Et on ne gère même pas la taille des séparateurs ".(" et ")".Code:
1
2
3
4
5
6
7
8
9 const std::size_t c_annee_size = 4; const std::size_t c_mois_size = 2; const std::size_t c_jour_size = 2; const std::size_t c_tiret_size = 1; const std::size_t c_date_size = c_annee_size + c_tiret_size + c_mois_size + c_tiret_size + c_jour_size; ... if (!found && pos > 2 && pos2 > (pos + c_date_size) && pos != std::wstring::npos && pos2 != std::wstring::npos)
Je trouve que l'utilisation d'expressions régulières ici serait bien plus simple.
Quand je dis de "dégager tous ces "extern ...", c'est pas juste "extern", c'est toute la/les ligne(s).Citation:
void Print_Audiodescription(...) ===> void Print_CleValeur(...)
Merci
Vous avez changé la signature de la fonction "Film::initialiser_Duree(std::wstring& m)" pour qu'elle soit plus réutilisable.Citation:
Code:void Film::initialiser_Making_of(std::filesystem::path const& cheminFichier)
C'est très très bien.
Mais vous avez aussi changé la sémantique de la fonction. Il faut donc changer le nom de la fonction pour qu'il correspond à sa nouvelle utilité.
"Film::initialiser_Duree(std::wstring& m)" ===> "Film::recuperer_une_Duree(std::wstring& m)"
Non, le contenu du fichier n'est pas de la responsabilité du développeur de l'application, donc pas d'"assert".Citation:
Code:assert((contenu.size() != 0));
On peut avoir une durée de making of mais "m_making_of " à faux. C'est pas clair vos pléthores de booléens.Citation:
Code:m_making_of = true;
Utilisez plutôt des champs optionnels à la place de ces "champ valeur + champ booléen_" :
https://en.cppreference.com/w/cpp/utility/optional
Je ne comprends pas trop la question.Citation:
Donc :
Making-of.txt
0h 18min
Netflix a partagé un making-of de la fabrication du film Sous La Seine, avec un focus sur les effets visuels, avec les explications de Arnaud Fouquet.
Les assets CGI du requin ont été supervisés par Florian Wolff côté MPC Paris et Ryan Bardoul de MPC Liège.
et/ou
Making-of.txt
et/ou
Making-of.txt
0h 18min
et/ou
Making-of.txt
Netflix a partagé un making-of de la fabrication du film Sous La Seine, avec un focus sur les effets visuels, avec les explications de Arnaud Fouquet.
Les assets CGI du requin ont été supervisés par Florian Wolff côté MPC Paris et Ryan Bardoul de MPC Liège.
Que faire ?
Si c'est l'absence d'une durée, le plus simple, c'est de faire retourner une valeur négative par la fonction "Film::initialiser_Duree/Film::recuperer_une_Duree" car cela risque de ne plus être un cas "exceptionnel".
Modifiez votre code pour qu'il interprète correctement une valeur négative retournée par cette fonction.
Vous n'en avez pas besoin actuellement. Faites sans.Citation:
Expliquez-moi ! Mais simple !!!Code:auto NumeroSequenceVisionnage = m_episode.GetNumeroSequenceVisionnage(*this);
Arrêtez de préfixer le nom de paramètre de fonction avec "m_". BORDEL:furieux::furieux::furieux:Citation:
Si tout devient optionnel, c'est clair que cela complexifie beaucoup le travail.Citation:
Code:Serie::Serie(std::filesystem::path racine)
Vous êtes sûr que la partie entre [] est entièrement optionnelle ???
Sinon, faut juste supprimer le "?" en trop :
Vous pouvez aussi remplacer la dernière capture ("(?:\\.(.+))?") par une liste des sous-genres possibles, avec des "|" pour les séparer, mais il faut "escaper" caractères "spéciaux" comme +,.,(,), etc... .Code:std::wregex filename_pattern{ L"(.+?)(?:\\.\\[(\\d{4}\\-\\d{4}\\s|\\d{4}\\-\\d{4}|\\d{4}\\-\\s|\\d{4}\\s|\\d{4})?([^\\]]*)\\])
?(?:\\.(.+))?" };
Si vous voulez toujours "tout optionnel", vous devez "piloter" l'ordre dévaluation des alternatives :
https://regex101.com/r/dzh1TD/1
mais vous aurez plusieurs "sources" pour les titres (ici, match[1] et match[5]) ou pour les genres (ici, match[1] et match[6]).
Quelle est la question ???Citation:
Et attention (film_serie.cpp) :
Ben !!!Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 ... const std::vector<std::wstring> Sur { L"Apple TV+", L"Amazon Prime Video", L"Crunchyroll", L"Disney+", L"DVD", L"Netflix", L"SⱯLTO", L"VOD" }; ...
Bonjour,
Trot fatigué ou peu dormi : L'ORL 03/09/2024 ===> les acouphènes puissants ! J'en ai marre !
Alors :
Et : pas-à-pas et pas complexe !!!Citation:
Attention, je trouve que vous ajoutez/cherchez pas mal de choses sans fiabiliser avant correctement les fonctionnalités déjà implémentées. (projet CMake, code "portable", etc...)
...
...
Quelle est la question ???
Rien compris !!!
Mais : film.cpp
et m_date ??? (annees_str ???)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 const void Film::Print_Header() { if (affichage_titres_actif) { std::wstring titres_str; std::wstring annees_str; std::wstring sur_str; std::wstring sj_str; std::wstring duree_str; std::wstring note_str; titres_str = m_keyColor[0] + L"Titre : " + m_valuesColor + m_titres[0]; if (m_titres.size() > 1) titres_str += m_keyColor[1] + m_titres[1] + m_valuesColor + m_titres[2]; // Date /*if (affichage_date_actif) { date_str = format_Annees(); }*/ // sur /*if (affichage_sur_actif && m_sur != L"") { sur_str += keyColor[0] + L" (" + keyColor[1] + L"sur " + valuesColor + m_sur + keyColor[1] + L" : " + valuesColor; // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += m_disney_sj; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += m_netflix_sj; sur_str += keyColor[0] + L')' + valuesColor; } else { // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += keyColor[0] + L" (" + valuesColor + L"Disney+" + keyColor[1] + L" : " + m_disney_sj + keyColor[0] + L')' + valuesColor; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += keyColor[0] + L" (" + valuesColor + L"Netflix" + keyColor[1] + L" : " + m_netflix_sj + keyColor[0] + L')' + valuesColor; }*/ if (affichage_sur_actif && m_sur != L"" && m_sur != L"Disney+" && m_sur != L"Netflix") { sur_str += m_keyColor[0] + L" (" + m_keyColor[1] + L"en salle " + m_valuesColor + m_sur + m_keyColor[0] + L')' + m_valuesColor; } if (affichage_sur_actif && (m_sur == L"Disney+" || m_sur == L"Netflix")) { sur_str += m_keyColor[0] + L" (" + m_keyColor[1] + L"sur " + m_valuesColor + m_sur + m_keyColor[1] + L" : " + m_valuesColor; // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += m_disney_sj; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += m_netflix_sj; sur_str += m_keyColor[0] + L')' + m_valuesColor; } else { // Disney+ SJ if (affichage_disney_sj_actif && m_disney_sj.length() != 0) sur_str += m_keyColor[0] + L" (" + m_valuesColor + L"Disney+" + m_keyColor[1] + L" : " + m_valuesColor + m_disney_sj + m_keyColor[0] + L')' + m_valuesColor; // Netflix SJ if (affichage_netflix_sj_actif && m_netflix_sj.length() != 0) sur_str += m_keyColor[0] + L" (" + m_valuesColor + L"Netflix" + m_keyColor[1] + L" : " + m_valuesColor + m_netflix_sj + m_keyColor[0] + L')' + m_valuesColor; } // La signalétique jeunesse if (affichage_sj_actif && m_sj.length() != 0) sj_str += m_keyColor[0] + L" (" + m_valuesColor + L"SJ" + m_keyColor[1] + L" : " + m_valuesColor + m_sj + m_keyColor[0] + L')' + m_valuesColor; // Durée if (affichage_duree_actif) { duree_str = L' ' + std::to_wstring(m_duree / (60 * 60)) + m_keyColor[0] + L"h" + m_valuesColor + L' ' + std::to_wstring((m_duree - ((m_duree / (60 * 60)) * 60 * 60)) / 60) + m_keyColor[0] + L"min " + m_valuesColor; } // Note if (affichage_note_actif) note_str += Print_Note(); std::wcout << titres_str << annees_str << sur_str << sj_str << duree_str << note_str << std::endl; } }
Pas compris !!!
Pièce jointe 658432
Pourquoi ?
https://github.com/laurentbouleau/Exemple : Août 15 (21/08/2024)
Merci vraiment:aie::calim2::calim2:
Pouvez-vous être plus précis, SVP ?Citation:
Rien compris !!!
Les corrections aux difficultés "concrètes" actuelles ont déjà été répondues dans les posts précédents.
Si vous ne nous dite pas ce que vous ne comprenez pas, on va tourner en rond.
Prenez un peu de temps à expliciter les difficultés de compréhension qui VOUS semble les plus génératrices de blocage.
Dans le dernier post, vous avez pris l'initiative de changer la signature de la fonction "Film::initialiser_Duree" :
Ce qui indique que vous êtes assez à l'aise avec le codage, mais les "blocages" dans votre dernier post sont bien plus "simples/basiques".Citation:
"Film::initialiser_Duree(std::wstring& m)" ===> "Film::recuperer_une_Duree(std::wstring& m)"
La fatigue ?
On va essayer de faire du plus simple au plus "complexe".
Pourquoi "m_date" ne contient que des "0" : parce que vous n'avez jamais remplis les informations que ce champ est censé retenir.
Les "0" viennent ce cette ligne de déclaration :
Le fait que vous ayez déclaré plusieurs autres dates montre que "m_date" est un très mauvais nom. De quelle date on parle ?Code:std::tm m_date{ 0 }, m_date_de_reprise{ 0 }, m_date_de_sortie{ 0 };
En sachant de quelle date on parle, on pourra savoir où et comment initialiser ce champ correctement. (et accessoirement corriger le nom du champ)
Par exemple "m_date_de_reprise" et "m_date_de_sortie" sont initialisés par le contenu de 2 fichiers spécifiques : "Date de reprise.txt" et "Date de sortie.txt".
C'est quoi la source des données à mettre dans "m_date" ?
On a déjà eu ce type de "débat" avec la classe Serie, et la solution est la même. (Avoir des champs avec des noms plus pertinents, des types de champs plus pertinents, etc...)
Vous devriez avec un code très proche dans ces 2 classes (cf. ma proposition d'en faire des classes sœurs)
Mais comme vous avez "fuit" la fin de la correction/affinage de la classe Serie pour vouloir "mettre au point" la classe Film, vous allez vous prendre les mêmes problèmes que vous avez fuit de la classe Serie.
Moralité : Toujours "stabiliser" le code existant avant de vouloir étendre les "fonctionnalités" du code.
Mais comme le format des noms de répertoire de Film semble plus simple que le nom de répertoire de série, il semble plus simple de "corriger" la classe Film que la classe Serie sur le problème du décodage du nom du répertoire.
Code dans le constructeur "Film::Film(std::filesystem::path racine)" :
Bin, faut juste prendre la version en commentaire pour "correctement" décoder le nom du répertoire :Citation:
Code:
1
2 std::wregex filename_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s)?([^\\)]*)\\))?(?:\\.(.+))?" }; //std::wregex filename_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s?)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Vous devriez maintenant comprendre l'utilité des 2 différences et comprendre pourquoi cela corrige le problème pour un nom de répertoire de la forme : "Star Wars- The Clone Wars.(2008-08-27).Animation"Code:std::wregex filename_pattern{ L"(.+?)(?:\\.\\((\\d{4}\\-\\d{2}\\-\\d{2}\\s?)?([^\\)]*)\\))?(?:\\.(.+))?$" };
Mais si la seule chose qui doit apparaître entre les parenthèses, c'est la "date" au format "yyyy-MM-dd", on peut largement simplifier le constructeur :
Ici, "m_sur" ne peut pas être initialisé car l'information n'apparait pas dans le nom du répertoire.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 Film::Film(std::filesystem::path racine) { this->racine = racine; auto nomDossier = racine.filename().wstring(); assert(nomDossier.length() > 0 && L"Nom de dossier vide"); std::wregex filename_pattern{ L"(.+?)(?:\\.\\((?:(\\d{4})\\-(\\d{2})\\-(\\d{2})\\)))?(?:\\.(.+))?$" }; std::wsmatch match; if (std::regex_match(nomDossier, match, filename_pattern)) { std::wstring titres = match[1]; m_titres = Dossier_Titres(titres); if (match[2].matched) { std::wstring annees_str = match[2].str(); std::wstring mois_str = match[3].str(); std::wstring jours_str = match[4].str(); m_date.tm_year = stoi(annees_str) - 1900; //beurk!! m_date.tm_mon = stoi(mois_str) - 1; //beurk!! m_date.tm_mday = stoi(jours_str); } //m_sur = (match[3].matched) ? match[3].str() : L""; m_sous_genre = (match[5].matched) ? match[5].str() : L""; } else { assert(false == true && "Le nom du répertoire n'est pas un nom valide."); } }
("Dossier_Titres", encore un nom de fonction pas terrible, et l'implémentation est foireuse !!! "extraire_Titres_Depuis_UneLigne", c'est pour une ligne dans un fichier, pas pour un nom de fichier ou de répertoire !!! :furieux::furieux::furieux:)
Pour "annees_str ", c'est une repompe du code de la classe Serie, alors pourquoi ne pas repomper le reste du code de la classe Serie qui gère ces trucs (affichage des champs correspondants) ???
Vous ne faites rien pour l'initialiser correctement, contrairement au code dans la classe Serie, donc, c'est "normal" qu'il n'affiche rien.
Mais vous avez déjà "su" gérer l'affichage du champ "m_date_de_reprise", alors pourquoi repomper le code de la classe Serie qui n'utilise pas le même type de champ plutôt que le code de l'affichage du champ "m_date_de_reprise" ???
Explicitez vos difficultés SVP.