String Literal mit Integer konkatenieren [gelöst]



  • @richard_wunsch sagte in Funktionsparameter durch std::string ergänzen:

    Ich freue mich über eure Ratschläge (Schlagwörter reichen auch ) und über Kritik an Stil und allgemeinen Sachen.

    • Leerzeilen ebenfalls mit einer Schleife ausgeben, dann kannst du auch größere Werte als 1,2,3 angeben.
    • übergib Text als const-Referenz
    • Deine Sleep-Funktion schläft nicht, sondern arbeitet heftig, sie fragt nämlich dauernd die Uhr ab und vergleicht die Zeit. Du wirst feststellen, dass du 100% CPU verbrauchst, obwohl du "nichts tust". Nimm std::this_thread::sleep_for(std::chrono::milliseconds(2000)); (ersetzte die Einheit und Dauer entsprechend) oder nutze sleep_until


  • Danke auch an dich @wob! Ich versuche deine Vorschläge umzusetzen und sie heute Abend zu posten.



  • @richard_wunsch Mit fällt gerade noch etwas auf: du kannst auch über Strings mit einer Range-for-Loop loopen:

    for (char ch : text) { 
        std::cout << ch << std::flush;
        ... 
    }
    


  • Hat doch nicht so lange gedauert, wie erwartet. Hier der Code nach den Lösungsvorschlägen von @Th69 und @wob.

    Ich bin mir nur nicht ganz sicher, wofür ich den Range-for-Loop einsetzen sollte...

    Freue mich weiterhin auf Ratschläge und Kritik!

    #include <iostream>
    #include <chrono>
    #include <thread>
    
    void sleep(unsigned int mseconds) {
         
            std::this_thread::sleep_for(std::chrono::milliseconds(mseconds));
        }
    
    
    void output_delayed ( std::string const &Text , int Leerzeile = 1 , int Delay = 1000 ) { 
       
            for ( int i = 0 ; i < Text.length () ; ++i ){
             
                std::cout << Text[i] << std::flush; 
                sleep ( 100 ); 
            } 
         
            for (int i = 0 ; i < Leerzeile ; i++){
             
                std::cout << std::endl;
            }    
         
            sleep (Delay); 
          
        }
    
    
    int main() {
         
            output_delayed("Wie ist dein Name? ",0);
            
            std::string Name;
          
            std::getline(std::cin, Name);
            
            output_delayed("Hallo " + Name);
            
            return 0;
         
        }
    
    
    


  • @richard_wunsch sagte in Funktionsparameter durch std::string ergänzen [gelöst]:

    Freue mich weiterhin auf Ratschläge und Kritik!

    Hallo,
    guter "Newbie"-code!
    Du solltest dir aber direkt einen einheitlichen Code-style angewöhnen!
    Du hast ein deutsch/englisch-Gemisch (nimm englisch!) und Parameter fangen mal klein, mal gross geschrieben an.



  • ...und um jetzt doch ein weiteres Detail anzusprechen:
    deine sleep-Funktion nimmt als Parameter einen unsigned int, also irgendeine Zahl - das ist nicht gut. Der Grund ist: du erkennst beim Aufrufen nicht sofort, welche Einheit du da reinfütten musst. Daher ist es oft keine gute Idee, für eine Dauer einfach eine einzelne Zahl zu nehmen. Du hebst damit die Typsicherheit wieder auf. Wenn du sleep(milliseconds(100)) liest, ist dagegen klar, dass 100ms geschlafen werden sollen. Genauso bei sleep(seconds(100)) oder mit using namespace std::chrono_literals; geht sogar sleep(100s) und es wäre klar, dass 100 Sekunden gemeint sind. Wenn du dagegen sleep(42) schreibst, muss man erst nachschauen, ob es 42 Sekunden, Millisekunden oder gar Mikro- oder Nanosekunden sind.

    Und zur Schleife: diese hier meinte ich:
    for ( int i = 0 ; i < Text.length () ; ++i ) .... -> ersetzte diese durch die range-for-Loop.

    Edit: da wir schon solche Detailkommentare geben, kann bist du schon ein deutlich fortgeschrittener "Newbie"!



  • Danke für die netten Worte und die konstruktive Kritik.

    @Jockelx Ich habe versucht den Code-style anzupassen - gerne Konventionsvorschläge dazu!

    @wob Die Range-for-Loop habe ich auch integriert, verstehe aber nicht so wirklich den Sinn. Im Endeffekt wird der Text doch nur in Chars unterteilt und dann verzögert ausgegeben. Wo ist die "Range"?

    Zur Sleep-Funktion: Wenn ich, wie in deinem Beispiel, Sleep(42)vorgebe, dann wird die Eingabe doch in die Funktion übergeben, sprich: std::this_thread::sleep_for(std::chrono::milliseconds(42)). Dadurch ist doch die Typsicherheit gegeben oder?

    Hier der angepasste Code:

    #include <iostream>
    #include <chrono>
    #include <thread>
    
    void Sleep (unsigned int mseconds) {
         
            std::this_thread::sleep_for(std::chrono::milliseconds(mseconds));
        }
    
    
    void OutputDelayed (std::string const &text , int blankrow = 1 , int delay = 1000) { 
       
            for (char ch:text) {
             
                std::cout << ch << std::flush; 
                Sleep (100); 
            } 
         
            for (int i = 0 ; i < blankrow ; i++){
             
                std::cout << std::endl;
            }    
         
            Sleep (delay); 
          
        }
    
    
    int main() {
         
            OutputDelayed ("Wie ist dein Name? ",0);
            
            std::string name;
          
            std::getline (std::cin, name);
            
            OutputDelayed ("Hallo " + name);
            
            return 0;
         
        }
    


  • @richard_wunsch sagte in Funktionsparameter durch std::string ergänzen [gelöst]:

    Wo ist die "Range"?

    Die Range ist in diesem Fall dein String text. Im C++ hast du für Container, die eine Liste von Elementen speichern jeweils immer einen Iterator bestimmten Typs. Mit diesem kannst du schrittweise über die Elemente wandern.



  • @spiri Ah, verstehe. Vielen Dank - das macht es etwas klarer!



  • Das nächste Problem lies natürlich nicht lange auf sich warten.

    Dieses Mal würde ich gerne das String-Literal, das ich durch OutputDelayed ausgebe, mit einem Integer ergänzen.

    Ich habe versucht, eine Funktion ToString zu erstellen, die mir den Integer als String ausgibt, um Sie dann mit dem String-Literal zu konkatenieren.

    Die anderen Funktionen von oben gelten noch, deshalb stelle ich nur die Funktion und die int main () ein.

    Ich freue mich auf eure Ideen!

    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <sstream>
    
    void ToString (int value) {
         
            std::stringstream convert;
            
            convert << value;
            
            std::string newString = convert.str();
            
            std::cout << newString;
        }
        
    int main() {
         
            OutputDelayed ("Wie alt bist du? ",0);
            
            int age;
          
            std::cin >> age;
            
            OutputDelayed ("Du bist " + ToString(age) + "Jahre alt");
            
            return 0;
         
        }
    

    Darauf wird folgender Fehler ausgegeben:

    main.cpp: In function ‘int main()’:
    main.cpp:48:49: error: invalid operands of types ‘const char [9]’ and ‘void’ to binary ‘operator+’
             OutputDelayed ("Du bist " + ToString(age) + "Jahre alt");
    


  • Die Funktion, die du suchst, heißt (Überraschung) std::to_string. Du brauchst also nicht selbst ein ToString zu schreiben. Deine Funktion gibt mit cout auf der Standardausgabe den String aus, du möchtest aber den String von der Funktion zurückgeben. Also ändere den return-Typ in deinem ToString von void auf std::string und ersetze das cout durch return newString;. (Edit2: C++ ist nicht wie shell, wo du etwas am Ende einer Funktion ausgibst und dann wieder einfängst - sondern du musst der Funktion schon mitteilen, dass sie einen String zurückgibt und diesen dann returnen)

    Oder eben einfacher: lösche deine ToString-Funktion vollständig und nimm to_string: OutputDelayed ("Du bist " + std::to_string(age) + "Jahre alt");

    Edit: wenn du mehr / komplizierter formatieren möchtest, schau dir mal https://github.com/fmtlib/fmt an.



  • @wob Vielen Dank für deine ausführliche (und auch geduldige) Antwort! Die Funktion std::to_string ist genau das, worauf ich hinaus wollte. Ich denke, ich muss unbedingt an meiner Suchmaschinenfähigkeit arbeiten.

    Jetzt, wo du mir erklärt hast, dass ToString den String übergeben muss und nicht die Standardausgabe, ist es natürlich logisch, wo der Fehler liegt. Ich werde mir auf jeden Fall die return-Anweisung nocheinmal genauer angucken!

    Vielen Dank auch für den weiterführenden Link. Ich werde es mir mal anschauen, muss aber definitiv erst die Basics verinnerlichen.



  • Dann solltest du als erstes mal in C++ Referenz stöbern.


Anmelden zum Antworten