Help me translate Python code that replaces extension in file name in C ++

Sorry if you don't know anything about Python, however the following snippet should be very readable for everyone. The only trick to pay attention to is that indexing the list with [-1] gives you the last item, if any, or throws an 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 

I need to convert this logic to C ++ (the language that I actually use, but still suck) with the following signature: void PopulateBackupFileNameOrDie(CAtlString& strBackupFileName, CAtlString& strXmlFileName); . Here strXmlFileName is "input", strBackupFileName "output" (should I undo a typo of two?). The tricky part is that (correct me if I'm wrong) I work with a Unicode string, so I am looking for these characters: .xmlXML not so straightforward. The latest Python does not have these problems because '.' and "." are Unicode strings (not "char" type) of length 1, both contain only a dot.

Note that the return type is void - don't worry about that. I do not want to tell you how we report the error to the user. In my Python example, I just used assert. You can do something similar or just include a comment, for example // ERROR: [REASON] .

Please ask if something is clear. Suggestions for using std::string , etc. Instead of a CAtlString for function parameters, this is not what I'm looking for. You can convert them inside a function if you need to, but I would prefer not to mix different types of strings in one function. I am compiling this C ++ on Windows using VS2010. This means that I do NOT install BOOST , QTString or other libraries that are not available out of the box. Stealing a BOOST or other heading to turn on some magic is also not the right solution.

Thanks.

+4
source share
2 answers

If you use ATL, why not just use the CAtlString methods?

 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"); } } 
+6
source

I didn’t split the line like your code, because it is a bit more work in C ++, because there really is no gain (this is slower, and for this task you really don't need to do this).

 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; 
+3
source

Source: https://habr.com/ru/post/1315245/


All Articles