string in list vertauschen - verzweiflung...
-
Hallo,
ich bin gerade bei einer Funktion die string Einträge in einer List tauschen soll:
list<string> Lektion::swap_Lektion(int a, int b) { int i = 0; string tmp; if(a>b) { int swap = a; a = b; b = swap; } for(it=it2=lektion.begin(); it!=lektion.end(); ++it, ++it2, i++) { if(i == a) { tmp = *it; *it = *++it2; *it++ = tmp; system("pause"); } } return lektion; }Aber es funktioniert einfach nicht... ich verzweifle noch..
Für einen Rat wäre ich sehr dankbar.

Gruß
Gustl
-
also du willst nur 2 beliebige strings in irgend nem container tauschen!?
//edit: ach so - die header könnt ich dir mal noch geben, falls du es probieren willst^^ #include <algorithm> //std::swap, std::advance #include <cassert> //assert template <typename TInputIterator> void swap_item(TInputIterator swap1, TInputIterator swap2) { using std::swap; swap(*swap1, *swap2); } template <typename TContainer> void swap_item(TContainer &container, typename TContainer::size_type to_swap1, typename TContainer::size_type to_swap2) { assert(container.size() > std::max(to_swap1, to_swap2); typename TContainer::iterator s1 = container.begin(), s2 = container.begin(); std::advance(s1, to_swap1); std::advance(s2, to_swap2); swap_item(s1, s2); } //anwendung: #include <list> //std::list #include <string> //std::string int main() { std::list<std::string> lektionen; /* befüllen */ std::list<std::string>::size_type swap1, swap2; /* swap1 und swap2 einlesen */ swap_item(lektion, swap1, swap2); }man könnte die beiden to_swaps auch noch in nen pair packen...
vll ein bisschen overkill, wenn ich jz noch mal drüber nachdenke
hier noch mal so, dass du es auch verstehst^^
list<string> Lektion::swap_Lektion(int a, int b) { list<string>::iterator s1, s2; s1 = s2 = lektion.begin(); for(int i(0); i != a; ++i) ++s1; for(int i(0); i != b; ++i) ++s2; std::string tmp = *s1; *s1 = *s2; *s2 = tmp; return lektion; }bb
PS: wieso soll lektion zurückgegeben werden? bau dir doch noch nen getter für den fall, dass du doch mal alles wissen möchtest...
-
Jawoll, klasse, danke.
Nein, deine erste Lösung verstehe ich nicht komplett.... aber deine zweite ist sehr schön

Bist du da alleine darauf gekommen, oder hast du dir das auch nur irgendwo abgeschaut?

Ich gebe die list gleich zurück weil ich die im gleichen zuge nach dem swap immer brauche... aber eine getter funktion habe ich auch.
danke nochmal

grußEdit:
Aber was passiert wenn man eine stelle(zahl) der funktion übergibt die nicht in der list vorhanden ist? mhhhh
Edit2: nichts...
-
Wahrscheinlich trägt
std::iter_swap()zur Verkürzung des Codes bei.
-
Gustl schrieb:
Edit:
Aber was passiert wenn man eine stelle(zahl) der funktion übergibt die nicht in der list vorhanden ist? mhhhhMuss der Aufrufer testen...
Ich habs bei meiner Version mit nem assert geprüft(ist in meinen Augen nen Logikfehler), aber bei dir hab ichs der Übersichthalber weggelassen - oder vergessen, weiß ich nicht mehr ;D;D
du findest auch ne wunderbare dokumentation zu der gesamten standard lib im netz:
http://www.cplusplus.com/reference/Nexus schrieb:
Wahrscheinlich trägt
std::iter_swap()zur Verkürzung des Codes bei.Hmm... Richtig - mal wieder so ne Fkt., an die ich nie denke

Hat sich mittlerweile eigtl was am MSVC-swap geändert, oder wird immernoch jedes mal explizit std::swap verwendet?
In der 2008er ist es noch immer so ><template<class _FwdIt1, class _FwdIt2> inline void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right std::swap(*_Left, *_Right); }bb
-
unskilled schrieb:
Ja, die kenne ich schon, ich habe auch unter list eine funktion mit swap gesucht... aber die swap funktion vertauscht "nur" zwei listen...
Nochmals danke, funktioniert einwandfrei

Gruß
-
unskilled schrieb:
Hat sich mittlerweile eigtl was am MSVC-swap geändert, oder wird immernoch jedes mal explizit std::swap verwendet?
Spielst du auf ADL an? In der Tat, das wäre ein Grund,
std::iter_swap()nicht zu verwenden (für das Beispiel von Gustl spielt das natürlich keine Rolle).Hm, das ist nicht gut. Ich habe gesehen, dass STL-Algorithmen wie
std::random_shuffle()undstd::partition()die Funktionstd::iter_swap()aufrufen. Könnte bei gewissen Templates etwas ineffizient werden.Besser wäre eine Tauschfunktion, welche auf den Namensraum Rücksicht nimmt.
template <typename T> void adl_swap(T& left, T& right) { using std::swap; swap(left, right); }
-
Nexus schrieb:
Besser wäre eine Tauschfunktion, welche auf den Namensraum Rücksicht nimmt.
template <typename T> void adl_swap(T& left, T& right) { using std::swap; swap(left, right); }War auch nicht der eigtl Grund, weshalb ich es nicht genutzt habe. ADL ist mir nur erst dann eingefallen^^
Aber die MS-Leute haben doch vrmtl 999999999x mehr Ahnung als du oder ich - wieso meinst du also, nehmen die keine Rücksicht auf ADL?
Die Lösung wäre das hiertemplate<class _Ty> inline void swap(_Ty& _Left, _Ty& _Right) { // exchange values stored at _Left and _Right if (&_Left != &_Right) { // different, worth swapping _Ty _Tmp = _Left; _Left = _Right; _Right = _Tmp; } }durch das
namespace detail{ template<typename T> void swap(T &lhs, T &rhs) { if(&lhs == &rhs) return; T tmp(lhs); lhs = rhs; rhs = tmp; } } template<typename T> void swap(T &lhs, T &rhs) { using detail::swap; swap(lhs, rhs); }zu ersetzen...
Aber eben dummerweise immer nur lokal...
Wieso steht dort eigtl nen inline davor? ODR wird doch bei templates so und so nicht verletzt und das der MSVC sonst nicht auf die Idee kommt, die Fkt zu inlinen, ist ja nun auch nicht wahr^^bb
-
unskilled schrieb:
Aber die MS-Leute haben doch vrmtl 999999999x mehr Ahnung als du oder ich
Wie es mit deinen Kenntnissen aussieht, weiß ich zwar nicht, trotzdem wage ich zu bezweifeln, dass diese Aussage so zutreffend ist.
Und selbst wenn es stimmt, bedeutet das nicht, dass keine Fehler gemacht würden.
Nebenbei ist iter_swap nicht genau genug spezifiziert.unskilled schrieb:
namespace detail{ template<typename T> void swap(T &lhs, T &rhs) { if(&lhs == &rhs) return; T tmp(lhs); lhs = rhs; rhs = tmp; } }Eigentlich ist der Test &lhr==&rhs völlig überflüssig und kostet nur unnötig Performance. Schließlich wird swap mit sich selbst nur selten auftreten, die Kosten für das if bezahlt man aber immer. Insbesondere wenn die Kopierkosten gering sind (z.B. bei int), ist diese Prüfung Unfug.
-
camper schrieb:
Nebenbei ist iter_swap nicht genau genug spezifiziert.
imho aber ein wenig krümelkackerei - klar hätte man hinschreiben können: works like
swap(*lhs, *rhs)aber ich glaube nicht, dass es irgend eine vernünftige standard-lib-implementierung gibt, die das nicht auch so tut...camper schrieb:
Eigentlich ist der Test &lhr==&rhs völlig überflüssig und kostet nur unnötig Performance. Schließlich wird swap mit sich selbst nur selten auftreten, die Kosten für das if bezahlt man aber immer. Insbesondere wenn die Kopierkosten gering sind (z.B. bei int), ist diese Prüfung Unfug.
ok - überzeugt^^
bb
-
namespace detail{ template<typename T> void swap(T &lhs, T &rhs) { T tmp(lhs); lhs = rhs; rhs = tmp; } } template<typename T> void swap(T &lhs, T &rhs) { using detail::swap; swap(lhs, rhs); }Super Idee, die ich da wieder hatte xD
Ratet mal was passiert, wenn es kein spez. swap gibt : D
Kann man den ambigious call iwie verhindern(also das std::swap ausschließen?^^)bb
-
unskilled schrieb:
Kann man den ambigious call iwie verhindern(also das std::swap ausschließen?^^)
namespace detail{ template<typename T> void swap(T &lhs, T &rhs) { T tmp(lhs); lhs = rhs; rhs = tmp; } template<typename T> void swap_impl(T &lhs, T &rhs) { swap(lhs, rhs); } } template<typename T> void swap(T &lhs, T &rhs) { detail::swap_impl(lhs, rhs); }führt aber immer noch zu Mehrdeutigkeit, wenn std zufällig mal ein assozierter Namensraum ist, ohne dass gleichzeitig eine entsprechende Spezialisierung existiert.
-
hmm.. ok - scheint also nicht wirklich elegant zu gehen-.-
camper schrieb:
wenn std zufällig mal ein assozierter Namensraum ist
das versteh ich nicht ganz... hast du evtl nen bsp. oder ne andere erklärung?
ty, bb
-
#include <algorithm> #include <vector> template <typename> struct foo {}; int main() { static foo<std::vector<int> > a, b; std::swap( a, b ); // mehrdeutig, Kandidaten in std::detail::swap_impl: std::swap und std::detail::swap // lösbar, wenn man sämtliche Deklarationen in std nach std::detail verschiebt und in std nur using-Deklarationen benutzt // (abgesehen von swap) std::vector<int> c, d; std::swap( c, d ); // ok, da mit speziellerem template in std überladen }
-
hmm... schade^^
wäre direkt mal nen feature request wert - ich glaub zumindest nicht, dass es in der 2010er geändert ist...
ich hab zumindest keine lust, jedes mal auch noch (illegalerweise) std::swap zu überladen...
mir würde höchstens noch einfallen, mit enable_if/disable_if nen anderes swap anzubieten, wenn T ne Fktswap(T&)besitzt...
oder würde da noch iwas dagegen sprechen (außer das es an und für sich schon blödsinnig ist, ne standard-lib zu verändern)bb