Code in C++?
-
Hi,
wie sähe dieser Code in C++ aus?
char* removeDir(char* pcFilename) { int iLastBackSlash; int iChar; // Letzten Back-Slash ("\") suchen iLastBackSlash = -1; iChar = 0; while(pcFilename[iChar] != 0) { if(pcFilename[iChar] == '\\') iLastBackSlash = iChar; iChar++; } // String ab dem letzten Back-Slash plus 1 zurückliefern return pcFilename + iLastBackSlash + 1; }
-
genauso?
-
ich als newb würde sagen das könnte auch c sein (oder? kann nur c++ und das ein bisschen). in c++ kannst du das selbe schreiben. baut auf c auf. wenn dein code kein c++ sein sollte...
-
string removeDir(string f) { return f.substr(f.find_last_of("\\")); }
[EDIT] Die Funktion würd ich auf jeden Fall anders benennen, weil sie nicht das tut, was man vermutet.
-
yhamm schrieb:
ich als newb würde sagen das könnte auch c sein (oder? kann nur c++ und das ein bisschen). in c++ kannst du das selbe schreiben. baut auf c auf. wenn dein code kein c++ sein sollte...
Das ist wirklich C-Stil. Geht zwar in C++ auch, ist aber nicht zu raten.
-
gibt viele möglichkeiten das zu schreiben.
zB wie Michael E mit einer Kopie.man könnte aber auch nur einen iterator liefern, oder ne eigene String Klasse verwenden um das kopieren zu sparen, etc.
der C code ist so wie er jtzt ist übrigens nicht ganz problem frei. dadurch dass der zeiger nur verschoben wird, kann man lustige subtile bugs einbauen.
eine genauere anforderung wäre daher recht praktisch um helfen zu können.
-
template<typename T> const inline std::basic_string<T> removeDir (const std::basic_string<T>& value) { throw "Datentyp wurde nicht implementiert!"; } template<char> const inline std::basic_string<char> removeDir (const std::basic_string<char>& value) { return (value.substr(value.find_last_of("\\"))); } template<wchar_t> const inline std::basic_string<wchar_t> removeDir (const std::basic_string<wchar_t>& value) { return (value.substr(value.find_last_of(L"\\"))); }
Habs nur aus dem Kopf gemacht.
-
Achja: KEINE Garantie auf richtigkeit! Volkard könnte das sicherlich besser hinkriegen
-
Patrick @ Kumpels schrieb:
template<typename T> const inline std::basic_string<T> removeDir (const std::basic_string<T>& value) { throw "Datentyp wurde nicht implementiert!"; } template<char> const inline std::basic_string<char> removeDir (const std::basic_string<char>& value) { return (value.substr(value.find_last_of("\\"))); } template<wchar_t> const inline std::basic_string<wchar_t> removeDir (const std::basic_string<wchar_t>& value) { return (value.substr(value.find_last_of(L"\\"))); }
Habs nur aus dem Kopf gemacht.
lol
-
Versuch Du mal ein Programm leicht von char auf wchar_t zu konvertieren ohne größere Probleme.
gibt zwar das TEXT-Makro aber das gehört zu Windows, auch wenn ich ein eigenes Benutze wollte ichs nicht noch zusätzlich posten, deshalb template-Lösung, vorallem da ich #define net besonders mag
-
Patrick @ Kumpels (sogar bei Kumpels schon im Forum) schrieb:
Versuch Du mal ein Programm leicht von char auf wchar_t zu konvertieren ohne größere Probleme.
Mein Ansatz wäre sowas:
template<class T> MichaelE_HelpFunctions { basic_string<T> find_last_of(basic_string<T> in, basic_string<T> toFind) { return in.find_last_of(toFind); } basic_string<T> substr(basic_string<T> s, basic_string<T>::size_type beg = s.begin(), basic_string<T>::size_type end = basic_string<T>::npos) { return s.substr(beg, end); } }
Wenn man eine Funktion nicht so verallgemeinern kann, muss man die einzelnen Templates spezialisieren.
-
Patrick @ Kumpels schrieb:
template<typename T> const inline std::basic_string<T> removeDir (const std::basic_string<T>& value) { throw "Datentyp wurde nicht implementiert!"; } template<char> const inline std::basic_string<char> removeDir (const std::basic_string<char>& value) { return (value.substr(value.find_last_of("\\"))); } template<wchar_t> const inline std::basic_string<wchar_t> removeDir (const std::basic_string<wchar_t>& value) { return (value.substr(value.find_last_of(L"\\"))); }
Habs nur aus dem Kopf gemacht.
man könnte doch stattdessen ne funktion schreiben, die char nach wchar_t konvertiert, oder? dann würde dieses wiederholte schreiben des codes unnötig
//keine garantie, dass folgendes richtig/sinnvoll ist, ich arbeite net oft mit locales #include <iostream> //für die locales von cout template<class T,class U> std::basic_string<T> convert(const std::basic_string<U>& str){ std::basic_string<T> output; output.reserve(str.size()); std::use_facet<std::ctype<T> > (std::cout.getloc()).widen(str.begin(),str.end(), output); return output; } //wenn start und zieltyp gleich sind, ist keine konvertierung erforderlich template<class T> const std::basic_string<T>& convert(const std::basic_string<T>& str){ return str; } template<class T> const inline std::basic_string<T> removeDir (const std::basic_string<T>& value) { return value.substr(value.find_last_of(convert<T>("\\"))); }
//edit wahrscheinlich gibts aber ne um einiges bessere funktion bei boost
-
@otze
du gehst aber nur auf folgende ein und vergisst eines!
OK: char -> char
OK: char -> wchar_t
OK: wchar_t -> wchar_t
??: wchar_t -> char
-
stimmt...widen geht ja nur in eine richtung
-
Michael E. schrieb:
string removeDir(string f) { return f.substr(f.find_last_of("\\")); }
leider falsch. das original liefert einen pointer in den eingabestring zurück. das hier kopiert einen teilstring raus.
-
Falsch! beide richtungen gehen, sieht man ja auch an der WinAPI:
inline std::wstring to_wstring(const std::string& s,const std::locale& loc = std::locale()) { std::vector<wchar_t> ret(s.size(),0); const char* pCC = s.c_str(); mbstate_t state; wchar_t* pW = &*ret.end(); const char* pC = pCC+s.size(); std::use_facet<std::codecvt<wchar_t,char,mbstate_t> >(loc).in(state,pCC,pCC+s.size(),pC,&*ret.begin(),&*ret.end(),pW); return std::wstring(&*ret.begin(),pW); } inline std::string to_string(const std::wstring& ws,const std::locale& loc = std::locale()) { std::vector<char> ret(ws.size()*6,0); const wchar_t* pCW = ws.c_str(); mbstate_t state; const wchar_t* pW = pCW+ws.size()*6; char* pC = &*ret.end(); std::use_facet<std::codecvt<wchar_t,char,mbstate_t> >(loc).out(state,pCW,pCW+ws.size()*6,pW,&*ret.begin(),&*ret.end(),pC); return std::string(&*ret.begin(),pC); }
Jetzt müsst ihr das nur noch in einen schonen cast basteln
habs mal versucht aber kenn mich mit templates leider 0 aus
-
Warum * 6? lol
-
Compilezeitfehler sind besser als Laufzeitfehler, was in diesem Fall bedeutet:
template<typename CharT> struct dir_delim { }; template<> struct dir_delim<char> { static const char val = '/'; }; template<> struct dir_delim<wchar_t> { static const char val = L'/'; }; template<typename StringT> StringT get_filename(StringT const &path) { return path.substr(path.find_last_of(dir_delim<typename StringT::value_type>::val) + 1); }
-
Uh...in dir_delim<wchar_t> muss val natürlich auch ein wchar_t sein.
-
net schrieb:
Michael E. schrieb:
string removeDir(string f) { return f.substr(f.find_last_of("\\")); }
leider falsch. das original liefert einen pointer in den eingabestring zurück. das hier kopiert einen teilstring raus.
Dann halt so:
void removeDir(string &f) { f.erase(f.find_last_of("\\")); // Zweiter Parameter optional?? }
-
Michael E. schrieb:
net schrieb:
Michael E. schrieb:
string removeDir(string f) { return f.substr(f.find_last_of("\\")); }
leider falsch. das original liefert einen pointer in den eingabestring zurück. das hier kopiert einen teilstring raus.
Dann halt so:
void removeDir(string &f) { f.erase(f.find_last_of("\\")); // Zweiter Parameter optional?? }
auch nicht richtig. das verändert das original. gar nicht so einfach, ne?