Spezielle Auslese Frage...
-
Hallo,
danke euch beiden für eure Antworten. Dann mach ich es so.
@CStoll: Es ist eine eigene String implementation, die aber der std::string klasse eher ähnelt. (Und wenn würde ich auch eher die std::string verwenden)

Vielen Dank!
Gruß
DesiP.S.: Falls jemand noch Lösungsansätze kennt, bin ich nicht abgeneigt diese zu hören/lesen

-
Designer schrieb:
P.S.: Falls jemand noch Lösungsansätze kennt, bin ich nicht abgeneigt diese zu hören/lesen

Es wird dir nichts übrig bleiben als tatsächlich nachzusehen bis wohin die Zahl geht.
Du könntest höchstens, falls du sie auch als int benötigst, sofort konvertieren.
-
Ich glaube nicht das es bereits eine funktion für genau diese aufgabe gibt
Anscheinend hast du dich noch nicht mit der STL und der generischen Programmierung beschäftigt!?
Genauso wie die Container der STL wie z.B. der Vector auf beliebigen Datentypen operiert, lassen sich die Algorithmen mit verschiedenen Parametern aufrufen. Hierbei werden Funktionsobjekte übergeben. So lässt sich die Funktion find_if mit verschiedenen Prädikaten aufrufen.
-
Im Prinzip sehe Ich hier auch keine andere Lösung als die bereits vorgeschlagene. Die Frage ist evt. wie setzt man das um?
In C++ gibt es genau eine empfohlene Methode, um aus einer Folge von Zeichen eine Zahl zu lesen; und das ist std::istream >> int
Die Zeichen stehen in einem String, müssen aber erst gesucht werdem. Hört sich nach find_if und Iteratoren an - wie von CStoll schon beschrieben.Verbindet man beides konsequent miteinander, so kommt zwangsläufig so etwas heraus
#include <iostream> #include <streambuf> #include <algorithm> // find_if #include <string> #include <functional> // not1, ptr_fun #include <cctype> // isdigit template< typename I > class IIterStreambuf : public std::streambuf { public: typedef std::streambuf base_type; typedef base_type::traits_type traits_type; typedef base_type::int_type int_type; IIterStreambuf( I first, I last ) : base_type() , m_c() , m_cur( first ) , m_last( last ) {} protected: virtual int_type underflow() { if( m_cur != m_last ) { m_c = *m_cur++; setg( &m_c, &m_c, &m_c + 1 ); return traits_type::to_int_type( m_c ); } return traits_type::eof(); } private: char m_c; I m_cur; I m_last; }; class IIterStream : public std::istream { public: typedef std::istream base_type; template< typename IIter > IIterStream( IIter first, IIter last ) : base_type( new IIterStreambuf< IIter >( first, last ) ) {} ~IIterStream() { delete rdbuf(); } private: IIterStream( const IIterStream& ); IIterStream& operator=( const IIterStream& ); };Mal wieder ist es so, dass es in C++ zwar nicht für alles DIE Funktion gibt, die man benötigt, aber es läßt sich oft etwas mit wenigen Zeilen zusammenstellen.
Die Anwendung dieses IIterStream's für das von Designer beschriebene Problem geht dann wie folgt
void test_test( const std::string& txt ) { using namespace std; cout << "\"" << txt << "\" - "; IIterStream in( find_if( txt.rbegin(), txt.rend(), not1( ptr_fun( &isdigit ) ) ).base(), txt.end() ); int i; if( in >> i ) cout << "Nr. = " << i << endl; else cout << "keine Zahl am Ende enthalten" << endl; } int main() { const char* txt[] = { "Name_0123", "DateiOhne", "", "Name_0123.xxx", "Datei0" }; std::for_each( txt, txt + sizeof( txt )/sizeof(*txt), &test_test ); return 0; }.. ob das jetzt 'elegant' ist, mögen andere beurteilen
Gruß
Werner@Edit underflow: to_char_type durch to_int_type ersetzt
-
ein wenig umständlich oder?
schau dir mal folgende lösung an
die kommentare lassen den quelltext ein wenig aufquellen ...#include <iostream> #include <string> #include <sstream> #include <iterator> using namespace std; /** * Prädikat liefert wahr wenn es sich bei dem übergebenen Zeichen um * eine Zahl handel **/ struct is_num : unary_function<char, bool> { /** * @param x Zeichen dessen Wert überprüft werden soll **/ bool operator()(char x) const { return isdigit(x); } }; int main() { string str = "test123"; /** * Erstes Vorkommen eines Zeichen welches keine Zahl ist * ermitteln. Hierzu oben definiertes Funktionsobjekt is_num * negieren **/ reverse_iterator<string::iterator> i= find_if(str.rbegin(), str.rend(), not1(is_num())); /** * nun kann bequem per Iterator auf das Ergebnis zugegriffen * werden. Z.B. lässt sich das Ergebnis mit folgendem Befehl auf die * Standardausgabe schreiben. Natüröich kann auch jeder andere * beliebige ostream verwendet werden **/ copy(i.base(), str.end(), ostream_iterator<char>(cout)); /** * ... oder das Ergebnis kann per stringstream in ein Zahlentyp * umgewandelt werden **/ stringstream tmp; copy(i.base(), str.end(), ostream_iterator<char>(tmp)); int n; tmp >> n; cout << n; }
-
anstatt das Prädikat selbst zu definieren kannst du natürlich auch ptr_fun(&isdigit) verwenden funktioniert auch.

-
Und mit "i.base()-str.begin()" kannst du den Index des Zahlenblocks bestimmen und diesen z.B. per substr() raustrennen.
-
@lucky_tux guter Vorschlag

da setze ich jetzt noch einen drauf. Allerdings mit einer Anleihe bei boost
#include <iostream> #include <algorithm> // find_if #include <string> #include <functional> // not1, ptr_fun #include <cctype> // isdigit #include <boost/lexical_cast.hpp> // wer boost nicht kennt, hat C++ verpennt :sunglasses: void test_test( const std::string& txt ) { using namespace std; cout << "\"" << txt << "\" - Nr. = " << boost::lexical_cast< int >( string( find_if( txt.rbegin(), txt.rend(), not1( ptr_fun( &isdigit ) ) ).base(), txt.end() ) ) << endl; } int main() { const char* txt[] = { "Name_0123", "Datei33", "567", "Datei0", "NameOhneZahl" }; try { std::for_each( txt, txt + sizeof( txt )/sizeof(*txt), &test_test ); } catch( const std::exception& err ) { using namespace std; cerr << "\nUups: " << err.what() << endl; } return 0; }langsam könnte sich Designer mal wieder melden; er war doch an weiteren Lösungen interessiert....
Gruß
Werner
-
Hm.. sieht immer noch alles ziemlich nach CStolls Lösung aus, cf Post #2.
-
finix schrieb:
Hm.. sieht immer noch alles ziemlich nach CStolls Lösung aus, cf Post #2.
Hat ja auch keiner gesagt, dass das grundsätzlich neu wäre
Werner Salomon schrieb:
Im Prinzip sehe Ich hier auch keine andere Lösung als die bereits vorgeschlagene. Die Frage ist evt. wie setzt man das um?
Gruß
Werner
-
Werner Salomon schrieb:
Hat ja auch keiner gesagt, dass das grundsätzlich neu wäre
Hab ja auch nur angemerkt dass noch keine grundsätzlich neue Lösung aufgetaucht ist
