string::substr() -GELÖST-



  • redrew99 schrieb:

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main ()
    {
      string s="abc-efg";
      string t;
    
      t = s.substr(s.find('-'));
    
      cout<<t<<endl;
      return 0;
    }
    

    Substr() liefert mir hier wie gewünscht den Teilstring ("-efg") zurück.
    Falls der String aber kein '-' enthält, stürzt das Programm ab, was unschön ist. Besser wäre die Ausgabe eines Hinweises wie "kein - gefunden".
    Kann man das mit string::substr() bzw. string::find() umsetzen?

    Selbstverständlich. Aber leider biste viel zu faul um auf die Seiten im Netz zu gehen und zu lesen, was passiert, wenn basic_string::find() nix findet
    ...

    if(size_t pos = meinStr.find('-') != std::string::npos)
         //...
    else
         std::cout << "Nix gefunden! :(\n";
    

    (ungetestet)



  • Danke, da ich jetzt wußte was man sich anschauen muß(string::npos), habe ich selber auch eine Lösung gefunden.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
      string s=("abc-efg");
      string t;
    
      if(s.find("-")!=string::npos)
      {
          t=s.substr(s.find('-'));
          cout<<t;
      }
      else
      {
          cout<<"kein Treffer";
      }
    }
    


  • Hacker schrieb:

    if(size_t pos = meinStr.find('-') != std::string::npos)
         //...
    else
         std::cout << "Nix gefunden! :(\n";
    

    (ungetestet)

    Glaube, man braucht size_t pos gar nicht, oder?
    Der Compiler nimmt auch

    if(meinStr.find('-') != std::string::npos)
         //...
    else
         std::cout << "Nix gefunden! :(\n";
    

    anstandslos.



  • redrew99 schrieb:

    Danke, da ich jetzt wußte was man sich anschauen muß(string::npos), habe ich selber auch eine Lösung gefunden.

    Mit found hast du doch im Falle von ungleich string:npos den Index, kein Grund find ein zweites Mal zu bemühen.



  • Stimmt^^, also dann z.B.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
      string s=("abc-efg");
      string t;
      size_t found;
      found=s.find("-");
      if(found!=string::npos)
      {
          t=s.substr(found);
          cout<<t;
      }
      else
      {
          cout<<"kein Treffer";
      }
    }
    


  • Hacker schrieb:

    if(size_t pos = meinStr.find('-') != std::string::npos)
    

    Löl, ich liebe Code-Snippets von Hacker.



  • redrew99 schrieb:

    Hacker schrieb:

    if(size_t pos = meinStr.find('-') != std::string::npos)
         //...
    else
         std::cout << "Nix gefunden! :(\n";
    

    (ungetestet)

    Glaube, man braucht size_t pos gar nicht, oder?
    Der Compiler nimmt auch

    if(meinStr.find('-') != std::string::npos)
         //...
    else
         std::cout << "Nix gefunden! :(\n";
    

    anstandslos.

    Vielleicht willst du ja auch wissen, wo der Buchstabe gefunden wurde, oder? XD
    Ja, das war jetzt falsch, denn es muss so aussehen;

    size_t pos(meinStr.find('-'));
    if(pos != std::string::npos)
    

    Ach, noch ein paar kleine Design-Tipps:

    redrew99 schrieb:

    Stimmt^^, also dann z.B.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
      string s=("abc-efg");//Das sieht komisch aus, meintest du nicht eher std::string s("abc-efg"); ?
      string t;//Wieso hier? Mach es doch da, wo du es brauchst!
      size_t found;//Mach doch das
      found=s.find("-");//Und das in einer Anweisung!
      if(found!=string::npos)
      {
          t=s.substr(found);//So, hier könntest du jetzt t deklarieren!
          cout<<t;//Und das bräuchtest du eig. gar nicht, oder?
      }
      else
      {
          cout<<"kein Treffer";
      }
    }
    

    Die ganze main() könnte also so aussehen:

    string s("abc-efg");
      size_t found(s.find("-"));
    
      if(found != string::npos)
          cout << s.substr(found);
      else
          cout<<"kein Treffer";
    


  • Hacker schrieb:

    string s("abc-efg"); // Warum ein std::string, wenn wir ihn im ganzen Programm nie wieder bearbeiten wollen? Wie auch immer, auf jeden Fall consten. Außerdem ist ()-Initialisierung bei strings voll hässlich.
      size_t found(s.find("-")); // Auch found wird nicht mehr verändert, also auch const.
    // Des Weiteren suggeriert der Name "found", dass die Variable vom Typ bool ist, wir nennen sie also lieber "pos".
    // string::find ist außerdem uncool, weil es die Funktion schon in <algorithm> als std::find gibt.
    // Achja: ()-Initialisierungssytax bei Integern gefällt PI überhaupt nicht. Das sieht ihm zu zwanghaft aus.
    
      if(found != string::npos)
          cout << s.substr(found); // Näh. Vieeeeeeeeel zu ineffizient. Wozu extra Speicher allozieren, wenn wir nur von Position X bis Ende ausgeben wollen.
      else
          cout<<"kein Treffer"; // Und gewöhn dir bitte mal nen einheitlichen Leerzeichen-setzungs-Stil an. Ist ja grauenhaft.
    

    Mal alles Gesagte geändert:

    string const s = "abc-efg";
    auto const pos = find(s.begin(), s.end(), '-');
    
    if(pos != s.end())
        copy(pos, s.end(), ostream_iterator<char>(cout));
    else
        cout << "kein Treffer";
    

    Aber das ist doch viel zu umständlich!
    Also mal std::string durch char const* ersetzen.

    char const s[] = "abc-efg";
    auto const pos = find(begin(s), end(s), '-');
    
    cout << (pos != end(s) ? pos : "kein Treffer"); // höhö
    

    Win!



  • 314159265358979 schrieb:

    Also mal std::string durch char const* ersetzen.

    Ne, nicht Win. Der String ist dem OP offensichtlich nicht im Voraus bekannt, wie es bei diesem Minimalbeispiel der Fall ist. Du willst also das komplette Hantieren mit einer unbekannten Zeichenkette von std::string auf const char* umstellen, nur um ein if durch den ternären Operator zu ersetzen?



  • Nö. Man braucht hier nichts allozieren, deshalb ersetze ich. Dass das konstrukt kürzer wird, ist ein netter Nebeneffekt.



  • Naja, um ganz ehrlich zu sein, hab ich den Code vom OP nicht verändert, sondern nur geschnitten. 😉
    C++11 hat der auch nicht umbedingt, und das consten sehe ich hier als unnötig und damit übrflüssige 5 Buchstaben. Klammer-Initialisierung find ich sexy, und was den Ternären Operator angeht: Wenn wir hier einen auf so effizient wie möglich gemacht hätten, also so performant wie nur irgendmöglich - dann hätt' ich den Code auch modifiziert 😉



  • Klammer-Initialisierung sieht total behindert aus. Du machst das ja auch bei ints und so.

    int i(0);
    

    Das ist nicht nur mehr Tipparbeit, sondern verwirrt auch nur.



  • 314159265358979 schrieb:

    Das ist nicht nur mehr Tipparbeit [...]

    Wie das denn ? () gegen ' ' = ' ' .



  • Abstände Tippen sich leichter als Sonderzeichen, bei denen man die Umschalttaste braucht. 🙄



  • Ein '=' ist auch ein Sonderzeichen. () liegen direkt nebeneinander. Manche IDE's ergänzen sogar die ) automatisch zu ( und setzten den Cursor dazwischen.
    Die Zahlen liegen tatsächlich auch dort, wo die Sonderzeichen sind. Abstände sind also nicht leichter zu tippen 😉



  • Ich denke mal das Problem ist gelöst. Um Haarspaltereien und Geschmacksfragen braucht man sich hier nicht zu streiten.


Anmelden zum Antworten