String bearbeiten



  • Hey,
    ich steh vor einem Problem und habe keine große Lust dafü eine Funktion zu schreiben.
    Zu meinem Problem ich möchte einen String so bearbeiten das die Anfangsbuchstaben immer groß geschrieben werden und der rest des Wortes klein.
    Zum Bespiel so:

    "hAllO wElT" -> "Hallo Welt"

    Befor ich nun dafür eine Funktion schreibe wollte ich wissen ob es sowas schon gibt. Wäre gut wenn mir das jemand sagen könnte.



  • So eine Funktion kann gar nicht in einer Standard header Datei enthalten
    sein, da man sowas sehr selten bräuchte bzw sogut wie nie. Und keine
    weitere selbstdefinierte Funktion würde auf sowas bauen...
    Die wirst du dir selber schreiben müssen,
    ist aber auch gar nicht so schwer.

    Hab dazu was rumprobiert.
    Kann mir wer sagen, wieos das hier zum Absturz führt?

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    char* up_first_char(char* sentence)
    {
    	bool upped = false;
    
    	for (unsigned short int i = 0; i < strlen(sentence); i++)
    	{
    		if (sentence[i] == ' ')
    			// Nächstes Zeichen gilt als erstes Zeichen des nächsten Wortes
    			upped = false;
    		else if (!upped)
    		{
    			// Dieses Zeichen gilt als erster Buchstabe eines aktuellen Wortes
    			switch (sentence[i])
    			{
    				case 'a': sentence[i] = 'A'; break;
    				case 'b': sentence[i] = 'B'; break;
    				case 'c': sentence[i] = 'C'; break;
    				case 'd': sentence[i] = 'D'; break;
    				case 'e': sentence[i] = 'E'; break;
    				case 'f': sentence[i] = 'F'; break;
    				case 'g': sentence[i] = 'G'; break;
    				case 'h': sentence[i] = 'H'; break;
    				case 'i': sentence[i] = 'I'; break;
    				case 'j': sentence[i] = 'J'; break;
    				case 'k': sentence[i] = 'K'; break;
    				case 'l': sentence[i] = 'L'; break;
    				case 'm': sentence[i] = 'M'; break;
    				case 'n': sentence[i] = 'N'; break;
    				case 'o': sentence[i] = 'O'; break;
    				case 'p': sentence[i] = 'P'; break;
    			}
    
    			// Das erste Zeichen des aktuellen Wortes wurde geupt
    			upped = true;
    		}
    	}
    
    	return sentence;
    }
    
    int main(int argc, char *argv[])
    {
    	cout << up_first_char("hallo welt") << endl;
    
        system("PAUSE");
        return 0;
    }
    


  • Du hast die Umlaute vergessen... und natürlich hast Du vergessen die grossbuchstaben im Wort klein zu machen...

    PS: Einfacher geht es mit _toupper und _tolower ...



  • Jochen Kalmbach schrieb:

    und natürlich hast Du vergessen die grossbuchstaben im Wort klein zu machen...

    Ich habe seinen Wunsch als Übung genommen und wollte
    eigentlich nur wissen, woran der Absturz liegt...
    Meine Funktion soll den ersten Buchstaben jedes Wortes uppen.
    Sry, wenn ich einfach mal sein Thema benutzt habe. 😃

    // edit
    Das gibt's doch nicht!

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    char* up_first_chars(char* sentence)
    {
    	bool checked = false;
    	int temp;
    
    	for (unsigned short int i = 0; i < strlen(sentence); i++)
    	{
    		if (sentence[i] == ' ')
    			// Nächstes Zeichen gilt als erstes Zeichen des nächsten Wortes
    			checked = false;
    		else if (!checked)
    		{
    			// Dieses Zeichen gilt als erster Buchstabe eines aktuellen Wortes
    			sentence[i] = _toupper(sentence[i]);
    
    			// Für das aktuelle Wort erledigt.
    			checked = true;
    		}
    	}
    
    	return sentence;
    }
    
    int main(int argc, char *argv[])
    {
    	cout << up_first_chars("hallo welt") << endl;
    
        system("PAUSE");
        return 0;
    }
    

    Woran liegt der Programmabsturz!?!?
    Kompilieren tut Dev-C++ es ja!



  • ich glaub zwar nicht, dass das der Absturzgrund ist,
    aber das:

    for (unsigned short int i = 0; i < strlen(sentence); i++)
    

    sollte man besser so:

    for (unsigned short int i = 0, iLen = strlen(sentence); i < iLen; i++)
    

    machen, da der Teil bei for zwischen den beiden ; ; bei jeder Wiederholung
    erneut ausgeführt wird.
    Bei längeren Zeichenketten sind das große Performanceeinbußen!

    außerdem frage ich mich, wozu diese

    int temp;
    

    gut sein soll ???
    schließlich verwendest du es ja nicht.

    Es wäre vllt auch hilfreich, wenn du uns verraten würdest, an welcher Stelle der Absturz passiert.



  • Vielen Dank für deinen Performance-Tipp. Auf sowas leg ich besonders Wert 😉
    Die Variable temp war nach einer Überarbeitung nicht mehr nötig, ich habe
    lediglich vergessen, sie wieder zu entfernen.

    Hier der ganze source

    #include <cstdlib>
    #include <iostream>
    using namespace std;
    
    char* up_first_char(char* sentence)
    {
    	bool checked = false;
    
    	for (unsigned short int i = 0, iLen = strlen(sentence); i < iLen; i++)
    	{
    		if (sentence[i] == ' ')
    			// Nächstes Zeichen gilt als erstes Zeichen des nächsten Wortes
    			checked = false;
    		else if (!checked)
    		{
    			// Dieses Zeichen gilt als erster Buchstabe eines aktuellen Wortes
    			sentence[i] = _toupper(sentence[i]);
    
    			// Für das aktuelle Wort erledigt.
    			checked = true;
    		}
    	}
    
    	return sentence;
    }
    
    int main(int argc, char *argv[])
    {
    	cout << up_first_char("hallo welt") << endl;
    
        system("PAUSE");
        return 0;
    }
    

    Und hier der screenshot vom Übel
    http://img3.imagebanana.com/view/kcgxdnl6/prob.png
    Keine compile errors



  • Ach so...
    Dir sollte bewusst sein, dass Compiler i.d.R. String-Literale in einen "Read-Onyl" Bereich legen...

    Du übergibst hier direkt ein String-Literal einer Funktion, welche ein "char*" erwartet. Dies sollte IMHO eine Compiler-Warnung erzeugen...

    Verwende:

    cout << up_first_char(strdup("hallo welt")) << endl;
    

    und es sollte gehen... (PS: der SPeicher wird hier dann nicht mehr freigegen...; verwende am besten std::string).



  • Es funkt. Also lag es daran, dass die Funktion als Parameter einen Pointer
    zu einer char verlangt, aber es wird ein constantes string array der
    Größe 11 übergeben (10 + \0). Und strdup legt einen string in den heap
    und gibt den pointer zurück?

    Jochen Kalmbach schrieb:

    und es sollte gehen... (PS: der SPeicher wird hier dann nicht mehr freigegen...; verwende am besten std::string).

    Du meinst, das auf dem heap liegene char array, dessen Pointer
    der Funktion als Parameter übergeben wird, wird nach dem
    return nicht wieder aus dem Speicher entfernt?
    Wie wäre es denn damit? 😉

    int main(int argc, char *argv[])
    {
    	char * bla;
    	cout << up_first_char(bla = strdup("hallo welt")) << endl;
    	delete[] bla;
    
        system("PAUSE");
        return 0;
    }
    


  • Wenn Du was mit "strdup" allokiert hast, musst Du es mit "free" freigeben!



  • Wieso'n das? 😕



  • Hmm... die einfachste Erklärung ist immer:
    WEIL ES IN DER DOKU STEHT!



  • Danke erst mal für die genazen Antworten ich hab mir jetzt meine eigene Funktion geschrieben.

    #include <iostream>
    #include <stdio.h>
    
    using namespace std;
    
    string a;
    
    void down(int i,int L,bool inside)
    {
        if(inside==true)
        {i++;}
        else
        {i++;}
    
        for(int x=i;x<=L;x++)
        {
            if(a[x]!=' ')
            {
                if(a[x]<=90 && a[x]>=65)
                {
                    a[x]=a[x]+32;
                }
            }
        }
    }
    
    void charwork(char *letter)
    {
        a =letter;
        int L= a.length(),Zusatz=0;
        for(int i=0;i<=L;i++)
        {
            Zusatz=i;
            if(a[i]==' ')
            {
                Zusatz++;
                if(a[Zusatz]<=122 && a[Zusatz]>=97)
                {
                   a[Zusatz]=a[Zusatz]-32;
                   down(Zusatz,L,true);
                }
            }
            if(i==0 && a[i]<=122 && a[i]>=97)
            {
                 a[i]=a[i]-32;
                 down(i,L,false);
            }
        }
        cout <<a<<endl;
    }
    int main(int argc, char *argv[])
    {
         charwork("  hAllO du AAa");
    
        system("PAUSE");
        return 0;
    }
    


  • String Bearbeiten schrieb:

    if(inside==true)
    {i++;}
    else
    {i++;}
    

    Sehr sinnreich - eine if-else macht nur dann Sinn, wenn in beiden Blöcken etwas unterschiedliches steht. Und anstatt dir etwas eigenes zusammenzuschustern, solltest du lieber die vorgegebenen Funktionen toupper() und tolower() verwenden.



  • Ja vorher stand das noch was anderes drinn^^ und ich habs vergessen rauszunehmen



  • Jochen Kalmbach schrieb:

    Hmm... die einfachste Erklärung ist immer:
    WEIL ES IN DER DOKU STEHT!

    Hättest du mir einen Link oder Tip gegeben, wo sich diese Doku befindet,
    wäre folgende Bitte jetzt nicht extra gepostet worden: Gib mal Link pls.



  • http://msdn2.microsoft.com/en-us/library/y471khhc

    Because _strdup calls malloc to allocate storage space for the copy of strSource, it is good practice always to release this memory by calling the free routine on the pointer returned by the call to _strdup.



  • Generell sollte man sich merken bei der Speicherallokation niemals C und C++ zu mischen.

    #include <cctype>
    #include <algorithm>
    #include <string>
    
    void string_toupper(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), static_cast<int (*)(int)>(std::toupper)); }
    void string_tolower(std::string& str) { std::transform(str.begin(), str.end(), str.begin(), static_cast<int (*)(int)>(std::tolower)); }
    

    soll man so nicht machen ... aber nja was solls 😛
    So ... das direkt dann in unserer neuen, tollen Funktion nutzen um jeden Buchstaben im Satzanfang groß zu machen 🙂

    void string_first_upper(std::string& str)
    {
        string_tolower(str);
        for (std::size_t i(0); i < str.length(); ++i)
            if ((i == 0 || str[i - 1] == ' ') && str[i] >= 'a' && str[i] <= 'z') str[i] = 'A' + str[i] - 'a';
    }
    

    oh da war ich aber plemplem 😛 Die Funktion kann natürlich anders lauten:

    void string_first_upper(std::string& str)
    {
        string_tolower(str);
        for (std::size_t i(0); i < str.length(); ++i)
            if (i == 0 || str[i - 1] == ' ') std::toupper(str[i]);
    }
    


  • Meine Version

    void GeileFunktion(char *String)
    {
        bool bJetzt;
        String[0]=toupper(String[0]); //Sätze fangen ja groß an
        for(int i=0;i<(int)(strlen(String));i++)
        {
            if(String[i]==' ' || String[i]=='\n' || String[i]=='\t' || String[i]=='.' || String[i]=='?' || String[i]=='!')
                bJetzt=true;
            else
                bJetzt=false;
            String[i+1]= bJetzt?toupper(String[i+1]):tolower(String[i+1]);
        }
    }
    

    Ob die Wörter wirklich Substabtive sind ist eine andere Sache 😉


Anmelden zum Antworten