Char* to lowercase



  • std::string lowercase (const std::string &v)
    	{
    		const size_t end (v.length ());
    		std::string R ("");
    		for (size_t i (0); i < end; ++i)
    			{
    				if ((v[i] >= 'A') && (v[i] <= 'Z'))
    					R.push_back (v[i] + 32);
    				else R.push_back (v[i]);
    			}
    		return R;
    	};
    
    //Aufruf:
    const char *_string ("dfghjklkjhgfghjkJHGFHJKjhgHJKLJHGhjkljhghjkJHGFG");
    std::string lower = lowercase (_string);
    /*vll musst du auch lowercase (std::string (_string)) schreiben oder
    du schreibst dir einfach noch ne fkt für char *... sollte nicht sooo sehr viel anders gehen, also... ^^
    

    Geht bestimmt noch iwie (sehr viel ^^) effektiver etc, aber es tut seinen Job ganz gut glaub ich : >

    Bye 😛



  • Und was ist mit ÄÖÜ? 🙂



  • hmm.. AÖÜ werden doch eh kaum verwendet! 😉

    std::string lowercase_mitumlauten (const std::string &v)
        {
            const size_t end (v.length ());
            std::string R ("");
            for (size_t i (0); i < end; ++i)
                {
                    if ((v[i] >= 'A') && (v[i] <= 'Z'))
                        R.push_back (v[i] + 32);
                    else if (v[i] == 'Ä') R.push_back ('ä'); //keine ascii-tabelle
                    else if (v[i] == 'Ö') R.push_back ('ö');
                    else if (v[i] == 'Ü') R.push_back ('ü');
                    else R.push_back (v[i]);
                }
            return R;
        };
    

    ;o)
    Wenn man es ein wenig performanter will, dann muss man das eben so anstellen:

    std::string R (""); //weiß nicht, obs hier nen reserve gibt...
    //...
    switch (v[i])
      case 'A':
        R.push_back ('a');
        break;
    /*
    B-Z, ÄÖÜ
    */
      default:
        R.push_back (v[i]);
    

    Naja - toll wird es auch dann noch nicht, aber reichen tuts jz jedenfalls ^^

    Bye



  • pff is murks sowas 😉 nimm einfach std::tolower ...



  • also ich mag in der beziehung die std-fkt trotzdem nicht 😛
    (mal von dem overhead durch locale abgesehen finde ich sie auch nicht gerad komfortabel 😛 )

    ich weiß, jz kommt gleich wieder einer mit dem satz: "oh - ein rad!" ^^ aber ab und an find ichs einfach vorteilhafter die fkt selbst zu schreiben...
    ich kenn mich zwar auch nicht sonderlich gut damit aus aber so kann man eben z.bsp. auch bei nem toupper bestimmen, was mit nem ß passieren soll...



  • Ich wollt das ganze jz ma probieren... Jz hab ich aber folgendes Prob:
    Die Fkt funtzt und so weiter - aber das reserve und die Kapazität stimmen nicht miteinander überein - wahrscheinlich bildet sich immer eine Differenz von 16, aber das weiß ich auch nicht so genau...

    std::string lowercase (const std::string &v)
    	{
    		const size_t end (v.length ());
    		std::string R ("");
    /*HIER*/	R.reserve (end+1); //end oder end +1 ?
    		for (size_t i (0); i < end; ++i)
    			{
    				switch (v[i])
    					{
    						case 'A':		R.push_back ('a');	break;
    /*B-Z, Ä, Ö, Ü*/
    						default:		R.push_back (v[i]);
    					}
    			}
    /*HIER*/	const size_t ASD = R.capacity ();
    		return R;
    	};
    

    die 2 relevanten Stellen habe ich jeweils gekennzeichnet, wie man sieht ^^
    Die erste Frage:
    std::string wird doch auch mit \0 terminiert. Ich muss also {Länge + 1} reservieren, genau wie bei char *, oder?!
    Die zweite Frage:
    Warum bildet sich da so ne große Differenz? Kann ich das irgendwie umgehen oder nutz ich womöglich einfach die falsche Fkt und man nimmt die fkt xyz dafür?

    Danke...



  • reserve reserviert auch immer nur mindestens soviel platz, wie benötigt wird. wenn der string noch wächst, dann geht das hinzufügen dafür schneller. wieviel genau ist aber implementationsspezifisch.
    std::string ist *nicht* nullterminiert (nur dann, wenn du einen C-String daraus machst, bekommst du einen nullterminierten string zurück) - std::string kann nämlich sogar '\0' beinhalten.

    im prinzip musst du aber gar nicht auf reserve achten, da std::string automatisch neuen speicher allokiert.



  • AD 1:
    Es ist std::basic_string überlassen, wie er sich die länge des Strings merkt. Das '\0' dient nur dazu, kenntlich zu machen, dass der String zu Ende ist, weil du sonst bei dynamisch (aufm Heap) angelegten Arrays keine Chance hast, die Länge des Arrays herrauszubekommen, es sei denn du schreibst diese immer mit.
    Bei std::basic_string wird aber auch die Länge mitgespeichert und somit ist das '\0' eigtl. überflüssig.

    Aber in diesem Fall ist es noch überflüssiger, da dich das nicht interessiert. Es gibt kein lower case zu '\0'. Und reservieren musst du dafür auch keinen Platz. Das kann std::basic_string entweder intern machen oder lassen. Es ist für dich egal!

    Warum so umständlich:

    const std::string lowercase (std::string const & data)
    {
        const std::size_t size(data.length());
        std::string result(size, 0); // string mit '\0' füllen.
        std::string::iterator it_result(result.begin());
        for (std::string::const_iterator it(data.begin()); it != data.end(); ++it)
        {
            if (*it >= 'A' && *it <= 'Z')
                *it_result++ = *it - 'A' + 'a';
            else
            {
                switch (*it)
                {
                case 'Ä':
                    *it_result++ = 'ä'; break;
                case 'Ö':
                    *it_result++ = 'ö'; break;
                case 'Ü':
                    *it_result++ = 'ü'; break;
                case 'Ô':
                    *it_result++ = 'ô'; break;
                default:
                    *it_result++ = *it;
                }
            }
        }
    }
    

    so musst du nicht ganz so viele case reinbauen 😉 Und Iteratoren sind wesentlich schneller als der Indexoperator!



  • Und reservieren musst du dafür auch keinen Platz. Das kann std::basic_string entweder intern machen oder lassen. Es ist für dich egal!

    Naja... Wenn ich nen string hab, der 20 Faszillionen Zeichen hat ^^ Dann wird der string (obwohl ich schon weiß, wie lang er sein muss erst leer erstellt, dann werden paar byte dazu allokiert und dann noch mal und so weiter und so fort - dann ist dort nicht genügend platz und er muss halt wo anders allokieren und umkopieren (ich glaube zumindest, dass das so gelöst ist ^^))
    Das ist der Sinn darin....
    Wobei sich das Problem jz eh geklärt hat weil deine Variante besser ist ^^

    Ich weiß, dass man auch - 'A' und + 'a' rechnen kann (oder +32 ^^) - aber dachte eben, dass es mit nur switch schneller ist.

    Und Iteratoren sind wesentlich schneller als der Indexoperator

    Hmmm - gerade das dachte ich, optimiert der Compiler eh raus - aber ok.
    Danke : >



  • Nein macht er nicht. Und operator[] wird immer vom anfang des Arrays erstmal nach hinten geschoben ... der zeiger ist direkt am richtigen ort 😉



  • Wusst ichs doch ;o)

    Danke : >


Anmelden zum Antworten