MervS
MervS

Reputation: 5902

Stripping characters of a wxString

I am working on an application written in C++ that primarily uses wxWidgets for its objects. Now, suppose I have the following wxString variable:

wxString path = "C:\\Program Files\\Some\\Path\\To\\A\\Directory\\";

Are there any ways to remove the trailing slashes? While wxString provides a Trim() method, it only applies to whitespace characters. I could think of converting the string to another string type and perform the stripping there and switch back to the wxString type (it is essential that I use the wxString type) but if there is a less convoluted way of doing things, I'd prefer that.

Upvotes: 3

Views: 3841

Answers (4)

catalin
catalin

Reputation: 1987

path.erase(path.end() - 1);

or

path.RemoveLast();

Upvotes: 2

bogdan
bogdan

Reputation: 9317

This is what I would use, if I had no proper path-parsing alternative:

wxString& remove_trailing_backslashes(wxString& path)
{
   auto inb = path.find_last_not_of(L'\\');
   if(inb != wxString::npos)
      path.erase(inb + 1); //inb + 1 <= size(), valid for erase()
   else //empty string or only backslashes
      path.clear();
   return path; //to allow chaining
}

Notes:

  • Unless you're doing something unusual, wxString stores wchar_ts internally, so it makes sense to use wide string and character literals (prefixed with L) to avoid unnecessary conversions.
  • Even in the unusual case when you'd have strings encoded in UTF-8, the code above still works, as \ is ASCII, so it cannot appear in the encoding of another code point (the L prefix wouldn't apply anymore in this case, of course).
  • Even if you're forced to use wxString, I suggest you try to use its std::basic_string-like interface whenever possible, instead of the wx-specific functions. The code above works fine if you replace wxString with std::wstring.
  • In support of what VZ. said in his answer, note that all these simplistic string-based solutions will strip C:\ to C:, and \ to the empty string, which may not be what you want. To avoid such issues, I would go for the Boost.Filesystem library, which is, as far as I know, the closest to the proposed standard library filesystem functionality (which is not formally part of the standard yet, but very close).

For completeness, here's what it would look like using Boost.Filesystem:

wxString remove_trailing_backslashes(const wxString& arg)
{
   using boost::filesystem::path;
   static const path dotp = L".";

   path p = arg.wc_str();
   if(p.filename() == dotp)
      p.remove_filename();
   return p.native();
}

It's not as efficient as the ad-hoc solution above, mainly because the string is not modified in-place, but more resilient to problems caused by special path formats.

Upvotes: 2

MervS
MervS

Reputation: 5902

My use case actually also considers scenarios without trailing slashes.

I came up with two solutions. The first makes use of regular expression:

wxRegEx StripRegex("(.+?)\\\\*$", wxRE_ADVANCED);
if (StripRegex.Matches(path))
{
  path = StripRegex.GetMatch(path,1);
}

The second, as @catalin suggested, uses RemoveLast:

while (path.EndsWith("\\"))
{
  path.RemoveLast();
}

Edit: Using @VZ's suggestion, I came up with the following:

// for some reason, the 'Program Files' part get's taken out in the resulting string
// so I have to first replace the double slashes
path.Replace("\\\\","\\");
path = wxFileName::DirName(path).GetPath();

Upvotes: 1

VZ.
VZ.

Reputation: 22688

The others have mentioned how this can be achieved using wxString methods, however I would strongly advise using an appropriate class, i.e. either wxFileName or, maybe, std::filesystem::path, for working with paths instead of raw strings. E.g. to get a canonical representation of the path in your case I would use wxFileName::DirName(path).GetFullPath().

Upvotes: 4

Related Questions