4 votes

Aidez-moi à traduire le code Python qui remplace une extension dans le nom du fichier en C++.

Je m'excuse si vous n'avez aucune connaissance de Python, cependant, l'extrait suivant devrait être très lisible pour tout le monde. La seule astuce à laquelle il faut faire attention - indexer une liste à l'aide de [-1] vous donne le dernier élément s'il y en a un, ou lève une exception.

>>> fileName = 'TheFileName.Something.xMl'
>>> fileNameList = fileName.split('.')
>>> assert(len(fileNameList) > 1) # Must have at least one period in it
>>> assert(fileNameList[-1].lower() == 'xml')
>>> fileNameList[-1] = 'bak'
>>> fileName = '.'.join(fileNameList)
>>> print(fileName)
TheFileName.Something.bak

Je dois convertir cette logique en une fonction C++ (le langage que j'utilise actuellement, mais dans lequel je suis nul jusqu'à présent) avec la signature suivante : void PopulateBackupFileNameOrDie(CAtlString& strBackupFileName, CAtlString& strXmlFileName); . Ici strXmlFileName est "entrée", strBackupFileName est "sortie" (dois-je inverser l'ordre des deux ?). La partie délicate est que (corrigez-moi si je me trompe) je travaille avec une chaîne Unicode, donc je cherche ces caractères : .xmlXML n'est pas aussi simple. La dernière version de Python n'a pas ces problèmes car '.' y "." sont toutes deux des chaînes de caractères Unicode (pas de "char" ) de longueur 1, les deux contiennent juste un point.

Remarquez que le type de retour est void - ne vous inquiétez pas trop à ce sujet. Je ne veux pas vous ennuyer avec les détails de la façon dont nous communiquons une erreur à l'utilisateur. Dans mon exemple Python, j'ai simplement utilisé un assert. Vous pouvez faire quelque chose comme ça ou simplement inclure un commentaire tel que // ERROR: [REASON] .

Veuillez demander si quelque chose n'est pas clair. Suggestions d'utilisation std::string etc. au lieu de CAtlString pour les paramètres des fonctions ne sont pas ce que je recherche. Vous pouvez les convertir à l'intérieur de la fonction si vous le devez, mais je préférerais ne pas mélanger différents types de chaînes dans une même fonction. Je compile ce C++ sur Windows, en utilisant VS2010. Cela implique que je n'installerai PAS BOOST , QTString ou d'autres bibliothèques qui ne sont pas disponibles d'emblée. Voler un boost ou autre en-tête pour permettre une certaine magie n'est pas non plus la bonne solution.

Merci.

6voto

Praetorian Points 47122

Si vous utilisez ATL, pourquoi ne pas simplement utiliser CAtlString Les méthodes de l'UE ?

CAtlString filename = _T("TheFileName.Something.xMl");

//search for '.' from the end
int dotIdx = filename.ReverseFind( _T('.') );

if( dotIdx != -1 ) {
  //extract the file extension
  CAtlString ext = filename.Right( filename.GetLength() - dotIdx );

  if( ext.CompareNoCase( _T(".xml" ) ) == 0 ) {
    filename.Delete( dotIdx, ext.GetLength() ); //remove extension
    filename += _T(".bak");
  }
}

3voto

SoapBox Points 14183

Je n'ai pas divisé la chaîne de caractères comme le fait votre code parce que c'est un peu plus de travail en C++ pour un gain nul (c'est plus lent, et pour cette tâche vous n'avez vraiment pas besoin de le faire).

string filename = "TheFileName.Something.xMl";
size_t pos = filename.rfind('.');
assert(pos > 0 && pos == filename.length()-4); // the -4 here is for length of ".xml"
for(size_t i = pos+1; i < filename.length(); ++i)
    filename[i] = tolower(filename[i]);
assert(filename.substr(pos+1) == "xml");
filename = filename.substr(0,pos+1) + "bak";
std::cout << filename << std::endl;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X