it-swarm.com.de

Konvertieren Sie einen String in C++ in Großbuchstaben

Wie kann man einen String in Großbuchstaben umwandeln? Die Beispiele, die ich beim Googeln gefunden habe, haben nur mit Zeichen zu tun.

234

Boost-String-Algorithmen:

#include <boost/algorithm/string.hpp>
#include <string>

std::string str = "Hello World";

boost::to_upper(str);

std::string newstr = boost::to_upper_copy<std::string>("Hello World");
197
Tony Edgecombe
#include <algorithm>
#include <string>

std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);
434
Pierre

Kurze Lösung mit C++ 11 und toupper ().

for (auto & c: str) c = toupper(c);
struct convert {
   void operator()(char& c) { c = toupper((unsigned char)c); }
};

// ... 
string uc_str;
for_each(uc_str.begin(), uc_str.end(), convert());

Hinweis: Ein paar Probleme mit der Top-Lösung:

21.5 Null-terminierte Sequenzdienstprogramme

Der Inhalt dieser Header muss mit den Standard-C-Library-Headern <ctype.h>, <wctype.h>, <string.h>, <wchar.h> und <stdlib.h> identisch sein.

  • Dies bedeutet, dass es sich bei den cctype-Mitgliedern möglicherweise um Makros handeln kann, die nicht zur direkten Verwendung in Standardalgorithmen geeignet sind.

  • Ein weiteres Problem mit demselben Beispiel besteht darin, dass das Argument nicht umgewandelt oder überprüft wird, dass dies nicht negativ ist. Dies ist besonders gefährlich für Systeme, bei denen die Variable char signiert ist. (Der Grund ist: Wenn dies als Makro implementiert ist, wird wahrscheinlich eine Nachschlagetabelle verwendet, und Ihre Argumente werden in diese Tabelle aufgenommen. Ein negativer Index gibt Ihnen eine UB.)

27
dirkgently

Haben Sie ASCII oder internationale Zeichen in Zeichenfolgen? 

Im letzteren Fall ist "Uppercasing" nicht so einfach und hängt vom verwendeten Alphabet ab. Es gibt Zweikammer- und Einkammer-Alphabete. Nur Zwei-Kammer-Alphabete haben unterschiedliche Zeichen für Groß- und Kleinschreibung. Es gibt auch zusammengesetzte Zeichen wie den lateinischen Großbuchstaben 'DZ' (\ u01F1 'DZ'), die den sogenannten title-Fall verwenden. Dies bedeutet, dass nur das erste Zeichen (D) geändert wird.

Ich schlage vor, Sie schauen in ICU und unterscheiden zwischen einfachen und vollständigen Fallzuordnungen. Das könnte helfen:

 http://userguide.icu-project.org/transforms/casemappings

20
Milan Babuškov

Dieses Problem kann mit SIMD für den Zeichensatz ASCII vektorisiert werden. 


Beschleunigungsvergleiche:

Vorläufige Tests mit x86-64 gcc 5.2 -O3 -march=native an einem Core2Duo (Merom). Dieselbe Zeichenfolge aus 120 Zeichen (gemischt aus Kleinbuchstaben und nicht aus Kleinbuchstaben bestehendem ASCII-Code), die 40M-mal in einer Schleife konvertiert wurde (ohne Inlineing von Dateien, sodass der Compiler nichts davon wegoptimieren oder aus der Schleife heben kann). Gleiche Quell- und Zielpuffer, also kein Malloc-Overhead oder Speicher-/Cache-Effekt: Die Daten sind die ganze Zeit im L1-Cache, und wir sind rein an die CPU gebunden.

  • boost::to_upper_copy<char*, std::string>(): 198.0s. Ja, Boost 1.58 auf Ubuntu 15.10 ist wirklich so langsam. Ich habe den ASM in einem Debugger profiliert und schrittweise ausgeführt, und es ist wirklich wirklich schlecht: Es gibt einen dynamischen_cast einer Locale-Variablen, die pro Zeichen geschieht !!! (dynamic_cast erfordert mehrere Aufrufe von strcmp). Dies geschieht mit LANG=C und mit LANG=en_CA.UTF-8.

    Ich habe nicht mit einem anderen RangeT als std :: string getestet. Vielleicht optimiert die andere Form von to_upper_copy besser, aber ich denke, es wird immer new__ variablenPlatz für die Kopie sein, daher ist es schwieriger zu testen. Vielleicht unterscheidet sich etwas, das ich gemacht habe, von einem normalen Anwendungsfall, und normalerweise kann g ++ das Gebietsschema-Setup-Material aus der Per-Character-Schleife heben. Meine Schleife, die von einem std::string liest und in einen char dstbuf[4096] schreibt, ist zum Testen sinnvoll.

  • schleifenaufruf glibc malloc: _/6.67s (Das Ergebnis toupper wird jedoch nicht für potenzielles Multibyte-UTF-8 geprüft. Dies ist von Bedeutung für Türkisch.)

  • Nur-ASCII-Schleife: 8.79s (meine Basisversion für die Ergebnisse unten.) Anscheinend ist eine Tabellensuche schneller als eine int, wobei die Tabelle ohnehin in L1 heiß ist.
  • Nur autonome ASCII-Vektoren: 2.51s. (120 Zeichen liegen auf halbem Weg zwischen dem schlimmsten und dem besten Fall, siehe unten)
  • Nur vektorisierte ASCII-Vektoren: 1.35s

Siehe auch diese Frage, ob toupper() unter Windows langsam ist, wenn ein Gebietsschema gesetzt ist .


Ich war schockiert, dass Boost eine Größenordnung langsamer ist als die anderen Optionen. Ich überprüfte noch einmal, ob ich -O3 aktiviert hatte, und stellte sogar den asm in einem Schritt dar, um zu sehen, was er tat. Es ist fast genau die gleiche Geschwindigkeit wie bei clang ++ 3.8. Es hat einen riesigen Overhead innerhalb der Schleife pro Zeichen. Das Ergebnis perf recordcmov (für das Ereignis report perf) lautet:

  32.87%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNK10__cxxabiv121__vmi_class_type_info12__do_dyncastElNS_17__class_type_info10__sub_kindEPKS1_PKvS4_S6_RNS1_16
  21.90%  flipcase-clang-  libstdc++.so.6.0.21   [.] __dynamic_cast                                                                                                 
  16.06%  flipcase-clang-  libc-2.21.so          [.] __GI___strcmp_ssse3                                                                                            
   8.16%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale                                                                     
   7.84%  flipcase-clang-  flipcase-clang-boost  [.] _Z16strtoupper_boostPcRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE                                   
   2.20%  flipcase-clang-  libstdc++.so.6.0.21   [.] [email protected]plt                                                                                                     
   2.15%  flipcase-clang-  libstdc++.so.6.0.21   [.] [email protected]                                                                                             
   2.14%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNKSt6locale2id5_M_idEv                                                                                       
   2.11%  flipcase-clang-  libstdc++.so.6.0.21   [.] [email protected]                                                                                   
   2.08%  flipcase-clang-  libstdc++.so.6.0.21   [.] _ZNKSt5ctypeIcE10do_toupperEc                                                                                  
   2.03%  flipcase-clang-  flipcase-clang-boost  [.] [email protected]                                                                 
   0.08% ...

Autovektorisierung

Gcc und clang werden Schleifen nur dann automatisch vektorisiert, wenn die Anzahl der Iterationen vor der Schleife bekannt ist. (d. h. Suchschleifen wie die plain-C-Implementierung von cycles werden nicht automatisch erkannt.)

Für Zeichenfolgen, die klein genug sind, um in den Cache zu passen, wird die Zeichenfolge ~ 128 Zeichen lang, nachdem strlen zuerst ausgeführt wurde, erheblich beschleunigt. Dies ist für Zeichenfolgen mit expliziter Länge (wie C++ std::string) nicht erforderlich.

// char, not int, is essential: otherwise gcc unpacks to vectors of int!  Huge slowdown.
char ascii_toupper_char(char c) {
    return ('a' <= c && c <= 'z') ? c^0x20 : c;    // ^ autovectorizes to PXOR: runs on more ports than paddb
}

// gcc can only auto-vectorize loops when the number of iterations is known before the first iteration.  strlen gives us that
size_t strtoupper_autovec(char *dst, const char *src) {
    size_t len = strlen(src);
    for (size_t i=0 ; i<len ; ++i) {
        dst[i] = ascii_toupper_char(src[i]);  // gcc does the vector range check with psubusb / pcmpeqb instead of pcmpgtb
    }
    return len;
}

Jede anständige libc hat einen effizienten strlen, der viel schneller ist als das Schleifen eines Bytes, so dass separate vektorisierte Strlen- und Toupper-Schleifen schneller sind.

Baseline: Eine Schleife, die im laufenden Betrieb nach einer abschließenden 0 sucht.

Zeiten für 40M-Iterationen auf einem Core2 (Merom) 2,4GHz. gcc 5.2 -O3 -march=native. (Ubuntu 15.10). dst != src (also machen wir eine Kopie), aber sie überlappen sich nicht (und liegen nicht in der Nähe). Beide sind ausgerichtet.

  • 15 Zeichenfolge: Grundlinie: 1.08s. Autovec: 1,34 s
  • 16 Zeichenfolge: Grundlinie: 1.16s. Autovec: 1,52 s
  • 127 Zeichenfolge: Grundlinie: 8,91 s. autovec: 2.98s // Nicht-Vektor-Bereinigung hat 15 Zeichen, die verarbeitet werden müssen
  • 128 Zeichenfolge: Grundlinie: 9.00s. Autovec: 2,06 s
  • 129 Zeichenfolge: Grundlinie: 9.04s. autovec: 2.07s // Nicht-Vektor-Bereinigung hat 1 zu verarbeitendes Zeichen

Einige Ergebnisse sind etwas unterschiedlich.

Die Mikrobenchmarkierungsschleife, die die Funktion aufruft, befindet sich in einer separaten Datei. Andernfalls wird es inline und strlen() wird aus der Schleife gehoben, und es läuft erheblich schneller, insbesondere. für 16 Zeichenketten (0,187 s).

Dies hat den großen Vorteil, dass gcc es für jede Architektur automatisch vektorisieren kann. Der größte Nachteil besteht jedoch darin, dass es für den normalerweise üblichen Fall kleiner Strings langsamer ist.


Es gibt also große Beschleunigungen, aber die automatische Vektorisierung von Compilern ist nicht besonders gut für Code. für die Bereinigung der letzten bis zu 15 Zeichen.

Manuelle Vektorisierung mit SSE Intrinsics:

Basierend auf meiner Case-Flip-Funktion wird der Fall jedes alphabetischen Zeichens umgekehrt. Es nutzt den "Unsigned Compare Trick", bei dem Sie low < a && a <= high mit einem einzelnen vorzeichenlosen Vergleich durch Bereichsverschiebung durchführen können, sodass jeder Wert, der kleiner ist als strlen, zu einem Wert übersteigt, der größer als low ist. (Dies funktioniert, wenn high und low nicht zu weit voneinander entfernt sind.) 

SSE hat nur einen vorzeichenbehafteten Compare-Größer, aber wir können immer noch den Trick "unsignedcompare" verwenden, indem wir den Bereich unterhalb des signierten Bereichs verschieben: Ziehen Sie 'a' + 128 ab, so dass die alphabetischen Zeichen zwischen -128 liegen bis -128 + 25 (-128 + 'z' - 'a')

Beachten Sie, dass das Addieren von 128 und das Subtrahieren von 128 dasselbe für 8-Bit-Ganzzahlen sind. Es gibt keinen Ort, an dem Sie etwas mitnehmen können, also ist es nur Xor (Carryless Add), das hohe Bit wird umgedreht.#include <immintrin.h> __m128i upcase_si128(__m128i src) { // The above 2 paragraphs were comments here __m128i rangeshift = _mm_sub_epi8(src, _mm_set1_epi8('a'+128)); __m128i nomodify = _mm_cmpgt_epi8(rangeshift, _mm_set1_epi8(-128 + 25)); // 0:lower case -1:anything else (upper case or non-alphabetic). 25 = 'z' - 'a' __m128i flip = _mm_andnot_si128(nomodify, _mm_set1_epi8(0x20)); // 0x20:lcase 0:non-lcase // just mask the XOR-mask so elements are XORed with 0 instead of 0x20 return _mm_xor_si128(src, flip); // it's easier to xor with 0x20 or 0 than to AND with ~0x20 or 0xFF } .

dst=src, ist nicht-atomarer Lese-, Änderungs- und Schreibvorgang nicht dasselbe, als wenn einige Bytes überhaupt nicht berührt werden und können brechen Sie Multithread-Code.

Wir haben eine Skalarschleife dafür und auch, um high ausgerichtet zu bekommen. Da wir nicht wissen, wo die abschließende 0 sein wird, könnte eine nicht ausgerichtete Last von src auf die nächste Seite und den nächsten Segfault übergehen. Wenn wir Bytes in einem ausgerichteten 16B-Block benötigen, ist es immer sicher, den gesamten ausgerichteten 16B-Block zu laden.

Vollständige Quelle: in einem Github Gist .

// FIXME: doesn't always copy the terminating 0. // microbenchmarks are for this version of the code (with _mm_store in the loop, instead of storeu, for Merom). size_t strtoupper_sse2(char *dst, const char *src_begin) { const char *src = src_begin; // scalar until the src pointer is aligned while ( (0xf & (uintptr_t)src) && *src ) { *(dst++) = ascii_toupper(*(src++)); } if (!*src) return src - src_begin; // current position (p) is now 16B-aligned, and we're not at the end int zero_positions; do { __m128i sv = _mm_load_si128( (const __m128i*)src ); // TODO: SSE4.2 PCMPISTRI or PCMPISTRM version to combine the lower-case and '\0' detection? __m128i nullcheck = _mm_cmpeq_epi8(_mm_setzero_si128(), sv); zero_positions = _mm_movemask_epi8(nullcheck); // TODO: unroll so the null-byte check takes less overhead if (zero_positions) break; __m128i upcased = upcase_si128(sv); // doing this before the loop break lets gcc realize that the constants are still in registers for the unaligned cleanup version. But it leads to more wasted insns in the early-out case _mm_storeu_si128((__m128i*)dst, upcased); //_mm_store_si128((__m128i*)dst, upcased); // for testing on CPUs where storeu is slow src += 16; dst += 16; } while(1); // handle the last few bytes. Options: scalar loop, masked store, or unaligned 16B. // rewriting some bytes beyond the end of the string would be easy, // but doing a non-atomic read-modify-write outside of the string is not safe. // Upcasing is idempotent, so unaligned potentially-overlapping is a good option. unsigned int cleanup_bytes = ffs(zero_positions) - 1; // excluding the trailing null const char* last_byte = src + cleanup_bytes; // points at the terminating '\0' // FIXME: copy the terminating 0 when we end at an aligned vector boundary // optionally special-case cleanup_bytes == 15: final aligned vector can be used. if (cleanup_bytes > 0) { if (last_byte - src_begin >= 16) { // if src==dest, this load overlaps with the last store: store-forwarding stall. Hopefully OOO execution hides it __m128i sv = _mm_loadu_si128( (const __m128i*)(last_byte-15) ); // includes the \0 _mm_storeu_si128((__m128i*)(dst + cleanup_bytes - 15), upcase_si128(sv)); } else { // whole string less than 16B // if this is common, try 64b or even 32b cleanup with movq / movd and upcase_si128 #if 1 for (unsigned int i = 0 ; i <= cleanup_bytes ; ++i) { dst[i] = ascii_toupper(src[i]); } #else // gcc stupidly auto-vectorizes this, resulting in huge code bloat, but no measurable slowdown because it never runs for (int i = cleanup_bytes - 1 ; i >= 0 ; --i) { dst[i] = ascii_toupper(src[i]); } #endif } } return last_byte - src_begin; }

.

  • 16 Zeichenfolge: Grundlinie: 1.16s. Autovec: 1,52 s. Handbuch: 0.335s
  • 31 Zeichenkette: Handbuch: 0.479s
  • 127 Zeichenfolge: Grundlinie: 8,91 s. Autovec: 2,98 s. manuell: 0,925s
  • 128 Zeichenfolge: Grundlinie: 9.00s. Autovec: 2,06 s. manuell: 0.931s
  • 129 Zeichenfolge: Grundlinie: 9.04s. Autovec: 2.07s. Handbuch: 1.02s
  • (Eigentlich mit _mm_store in der Schleife, nicht _mm_storeu, weil Storeu bei Merom langsamer ist, selbst wenn die Adresse abgeglichen ist. Für Nehalem und später ist es in Ordnung. Ich habe den Code auch fürs Erste belassen, anstatt den Fehler zu beheben in einigen Fällen die abschließende 0 zu kopieren, da ich nicht alles neu einstellen möchte.)

Bei kurzen Strings, die länger als 16 B sind, ist dies also wesentlich schneller als die automatische Vektorisierung. Längen, die kleiner als ein Vektor sind, stellen kein Problem dar. Sie können ein Problem darstellen, wenn sie direkt vor Ort betrieben werden, weil der Speicher weitergeleitet wird. (Beachten Sie jedoch, dass es immer noch gut ist, unsere eigene Ausgabe zu verarbeiten, anstatt die ursprüngliche Eingabe, da toupper idempotent ist).

Es gibt viele Möglichkeiten, dies für verschiedene Anwendungsfälle festzulegen, je nachdem, was der umgebende Code und die Ziel-Mikroarchitektur wollen. Den Compiler dazu zu bringen, Nice-Code für den Bereinigungsabschnitt auszugeben, ist schwierig. Die Verwendung von ffs(3) (das auf x86 zu bsf oder tzcnt kompiliert wird) scheint gut zu sein, aber offensichtlich muss dieses Bit neu überdacht werden, da ich nach dem Schreiben dieser Antwort einen Fehler festgestellt habe (siehe FIXME-Kommentare).

_/Vektor-Beschleunigungen für noch kleinere Zeichenfolgen können mit src oder movq load/stores abgerufen werden. Passen Sie diese für Ihren Anwendungsfall an..


UTF-8:

Wir können feststellen, wann unser Vektor irgendwelche Bytes mit gesetztem High-Bit hat, und in diesem Fall auf eine skalare utf-8-fähige Schleife für diesen Vektor zurückgreifen. Der movd-Punkt kann um einen anderen Betrag vorrücken als der dst-Zeiger. Wenn wir jedoch wieder zu einem ausgerichteten src-Zeiger zurückkehren, werden noch ungeordnete Vektorspeicher in src ausgeführt.

Für Text, bei dem es sich um UTF-8 handelt, der meistens aus der ASCII -Untergruppe von UTF-8 besteht, kann dies gut sein: Hohe Leistung im Normalfall mit korrektem Verhalten in allen Fällen. Wenn es viele Nicht-ASCII-Werte gibt, wird es wahrscheinlich schlimmer sein, als die ganze Zeit in der skalaren UTF-8-Sensibilisierungsschleife zu bleiben.

Englisch schneller auf Kosten anderer Sprachen zu machen, ist keine zukunftssichere Entscheidung, wenn der Nachteil erheblich ist. 

.


Gebietsschema:

Im türkischen Gebietsschema (tr_TR) lautet das korrekte Ergebnis von toupper('i')'İ' (U0130), nicht 'I' (normales ASCII). Siehe Martin Bonners Kommentare zu einer Frage, ob tolower() unter Windows langsam ist.

Dort können wir auch nach einer Ausnahmeliste und einem Fallback auf den Skalar suchen, beispielsweise nach UTF8-Eingabezeichen mit mehreren Bytes.

Mit dieser Komplexität kann SSE4.2 dst oder etwas in der Lage sein, viele unserer Prüfungen in einem Zug durchzuführen.

With this much complexity, SSE4.2 PCMPISTRM or something might be able to do a lot of our checks in one go.

18
Peter Cordes
string StringToUpper(string strToConvert)
{
   for (std::string::iterator p = strToConvert.begin(); strToConvert.end() != p; ++p)
       *p = toupper(*p);

   return p;
}

Oder,

string StringToUpper(string strToConvert)
{
    std::transform(strToConvert.begin(), strToConvert.end(), strToConvert.begin(), ::toupper);

    return strToConvert;
}
18
user648545

Die schnellere wenn Sie nur ASCII Zeichen verwenden :

for(i=0;str[i]!=0;i++)
  if(str[i]<='z' && str[i]>='a')
    str[i]-=32;

Bitte beachten Sie, dass dieser Code schneller ausgeführt wird, jedoch nur unter ASCII funktioniert und keine "abstrakte" Lösung ist.

Wenn Sie UNICODE-Lösungen oder konventionellere und abstraktere Lösungen benötigen, finden Sie weitere Antworten und arbeiten Sie mit Methoden von C++ - Strings.

15
Luca C.

Verwenden Sie ein Lambda.

std::string s("change my case");

auto to_upper = [] (char_t ch) { return std::use_facet<std::ctype<char_t>>(std::locale()).toupper(ch); };

std::transform(s.begin(), s.end(), s.begin(), to_upper);
11
Byron

Folgendes funktioniert für mich.

#include <algorithm>
void  toUpperCase(std::string& str)
{
    std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}

int main()
{
   std::string str = "hello";
   toUpperCase(&str);
}
11
Pabitra Dash

Solange Sie mit ASCII nur auskommen und einen gültigen Zeiger auf den RW-Speicher angeben können, gibt es einen einfachen und sehr effektiven Einzeiler in C:

void strtoupper(char* str)
{ 
    while (*str) *(str++) = toupper((unsigned char)*str);
}

Dies ist besonders gut für einfache Zeichenfolgen wie ASCII - Bezeichner, die Sie in den gleichen Zeichenfall normalisieren möchten. Sie können dann den Puffer verwenden, um eine std: string-Instanz zu erstellen.

10
k3a
//works for ASCII -- no clear advantage over what is already posted...

std::string toupper(const std::string & s)
{
    std::string ret(s.size(), char());
    for(unsigned int i = 0; i < s.size(); ++i)
        ret[i] = (s[i] <= 'z' && s[i] >= 'a') ? s[i]-('a'-'A') : s[i];
    return ret;
}
10
David
#include <string>
#include <locale>

std::string str = "Hello World!";
auto & f = std::use_facet<std::ctype<char>>(std::locale());
f.toupper(str.data(), str.data() + str.size());

Dies wird bessere Ergebnisse erzielen als alle Antworten, die die globale toupper-Funktion verwenden. Dies ist vermutlich das, was boost :: to_upper darunter tut.

Dies liegt daran, dass :: toupper bei jedem Aufruf nach dem Gebietsschema suchen muss, weil es möglicherweise von einem anderen Thread geändert wurde, während hier nur der Aufruf von locale () diese Strafe hat. Um das Gebietsschema nachzuschlagen, muss man normalerweise sperren.

Dies funktioniert auch mit C++ 98, nachdem Sie das Auto ersetzt und die neue Nichtkonstante str.data () verwendet haben. Fügen Sie ein Leerzeichen hinzu, um die Schablone zu schließen (">>" bis ">>"):

std::use_facet<std::ctype<char> > & f = 
    std::use_facet<std::ctype<char> >(std::locale());
f.toupper(const_cast<char *>(str.data()), str.data() + str.size());
9
Glen Knowles
typedef std::string::value_type char_t;

char_t up_char( char_t ch )
{
    return std::use_facet< std::ctype< char_t > >( std::locale() ).toupper( ch );
}

std::string toupper( const std::string &src )
{
    std::string result;
    std::transform( src.begin(), src.end(), std::back_inserter( result ), up_char );
    return result;
}

const std::string src  = "test test TEST";

std::cout << toupper( src );
7
bayda
std::string value;
for (std::string::iterator p = value.begin(); value.end() != p; ++p)
    *p = toupper(*p);
4

Hier ist der neueste Code mit C++ 11

std::string cmd = "Hello World";
for_each(cmd.begin(), cmd.end(), [](char& in){ in = ::toupper(in); });
2
user2787620

probieren Sie die toupper()-Funktion (#include <ctype.h>). Es akzeptiert Zeichen als Argumente. Zeichenfolgen bestehen aus Zeichen. Sie müssen also jedes einzelne Zeichen durchlaufen, das die Zeichenfolge enthält

2
zmf

Meine Lösung (6. Bit für Alpha löschen):

#include <ctype.h>

inline void toupper(char* str)
{
    while (str[i]) {
        if (islower(str[i]))
            str[i] &= ~32; // Clear bit 6 as it is what differs (32) between Upper and Lowercases
        i++;
    }
}
0
Antonin GAVREL

nicht sicher, ob es eine eingebaute Funktion gibt. Versuche dies:

Fügen Sie entweder die ctype.h OR - Bibliotheken sowie die stdlib.h als Teil der Präprozessoranweisungen ein. 

string StringToUpper(string strToConvert)
{//change each element of the string to upper case
   for(unsigned int i=0;i<strToConvert.length();i++)
   {
      strToConvert[i] = toupper(strToConvert[i]);
   }
   return strToConvert;//return the converted string
}

string StringToLower(string strToConvert)
{//change each element of the string to lower case
   for(unsigned int i=0;i<strToConvert.length();i++)
   {
      strToConvert[i] = tolower(strToConvert[i]);
   }
   return strToConvert;//return the converted string
}
0
Brandon Stewart