una strupr saber pasar minusculas minuscula mayusculas mayuscula letra convertir como caracteres cambiar cadena c++ string

saber - strupr c++



Convertir una cadena en C++ a mayúsculas (26)

¿Tienes caracteres ASCII o internacionales en cadenas?

Si es el último caso, "mayúsculas" no es tan simple, y depende del alfabeto utilizado. Hay alfabetos bicamerales y unicamerales. Solo los alfabetos bicamerales tienen caracteres diferentes para mayúsculas y minúsculas. Además, hay caracteres compuestos, como la letra mayúscula latina ''DZ'' (/ u01F1 ''DZ'') que utilizan el llamado caso de título . Esto significa que solo se cambia el primer carácter (D).

Le sugiero que busque en la ICU , y la diferencia entre asignaciones de casos simples y completas. Esto podría ayudar:

¿Cómo se puede convertir una cadena a mayúsculas. Los ejemplos que he encontrado en Google solo tienen que ver con los caracteres.


Aquí está el último código con C ++ 11

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


Boost algoritmos de cadena:

#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");


La más rápida si usas solo caracteres ASCII :

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

Tenga en cuenta que este código se ejecuta más rápido, pero solo funciona en ASCII y no es una solución "abstracta".

Si necesita soluciones de UNICODE o soluciones más convencionales y abstractas, busque otras respuestas y trabaje con métodos de cadenas C ++.


Lo siguiente funciona para mí.

//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; }


Mi solución (borrando 6to bit para alfa):

#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++; } }


No estoy seguro de que haya una función incorporada. Prueba esto:

Incluya las bibliotecas ctype.h OR cctype, así como stdlib.h como parte de las directivas de preprocesador.

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 }


Siempre y cuando esté bien con ASCII solo y pueda proporcionar un puntero válido a la memoria RW, existe una línea simple y muy efectiva en C:

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

Esto es especialmente bueno para cadenas simples como los identificadores ASCII que desea normalizar en el mismo caso de caracteres. Luego puede usar el búfer para construir una instancia de std: string.


Solución corta utilizando C ++ 11 y toupper ().

for (auto & c: str) c = toupper(c);


TODAS estas soluciones en esta página son más difíciles de lo que deberían ser.

Hacer esto

RegName = "SomE StRing That you wAnt ConvErTed"; NameLength = RegName.Size(); for (int forLoop = 0; forLoop < NameLength; ++forLoop) { RegName[forLoop] = tolower(RegName[forLoop]); }

RegNamees tu string. Consiga que el tamaño de su cadena no se use string.size()como su probador real, es muy desordenado y puede causar problemas. entonces. El forbucle más básico .

recuerda que el tamaño de la cadena también devuelve el delimitador, así que usa <y no <= en tu prueba de bucle.

la salida será: alguna cadena que quieras convertir


Utilice una 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);


pruebe la función toupper() ( #include <ctype.h> ). acepta caracteres como argumentos, las cadenas se componen de caracteres, por lo que tendrás que recorrer cada carácter individual que, al juntarlos, forma la cadena


Este problema es vectorizable con SIMD para el conjunto de caracteres ASCII.

Comparaciones de aceleración:

Pruebas preliminares con x86-64 gcc 5.2 -O3 -march=native en un Core2Duo (Merom). La misma cadena de 120 caracteres (ASCII minúsculas y minúsculas mixtas), convertida en un bucle 40M veces (sin alineación de archivos cruzados, por lo que el compilador no puede optimizar ni sacar ninguno de ellos fuera del bucle). Los mismos búferes de origen y destino, por lo que no hay sobrecarga de malloc ni efectos de memoria / caché: los datos están activos en el caché L1 todo el tiempo, y estamos limitados a la CPU.

  • boost::to_upper_copy<char*, std::string>() : 198.0s . Sí, Boost 1.58 en Ubuntu 15.10 es realmente tan lento. Perfilaba y pisaba un solo paso el asm en un depurador, y es realmente muy malo: ¡¡¡hay un dinámico_cast de una variable de locale por personaje !!! (dynamic_cast toma múltiples llamadas a strcmp). Esto sucede con LANG=C y con LANG=en_CA.UTF-8 .

    No probé usando un RangeT que no sea std :: string. Tal vez la otra forma de to_upper_copy optimice mejor, pero creo que siempre será un espacio new / malloc para la copia, por lo que es más difícil de probar. Tal vez algo que hice difiere de un caso de uso normal, y tal vez normalmente se detiene g ++ puede levantar las cosas de configuración del entorno local fuera del bucle por carácter. Mi lectura de bucle de un std::string y escribir en un char dstbuf[4096] tiene sentido para la prueba.

  • bucle que llama a glibc toupper : 6.67s ( aunque no se comprueba el resultado int para el potencial UTF-8 de múltiples bytes. Esto es importante para el turco).

  • Bucle solo ASCII: 8.79s (mi versión de línea de base para los resultados a continuación) Aparentemente, una búsqueda en la tabla es más rápida que una cmov , con la tabla caliente en L1 de todos modos.
  • ASCII solo auto-vectorizado: 2.51s . (120 caracteres se encuentran a medio camino entre el peor y el mejor caso, ver más abajo)
  • ASCII solo vectorizado manualmente: 1.35 s

Vea también esta pregunta acerca de que toupper() es lento en Windows cuando se establece una configuración regional .

Me sorprendió que Boost fuera un orden de magnitud más lento que las otras opciones. Verifiqué dos veces que tenía habilitado -O3 , e incluso pisé el asm para ver lo que estaba haciendo. Es casi exactamente la misma velocidad con clang ++ 3.8. Tiene una gran sobrecarga dentro del bucle por carácter. El resultado del perf record / report perf record (para el evento de perf de cycles ) es:

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 [.] strcmp@plt 2.15% flipcase-clang- libstdc++.so.6.0.21 [.] __dynamic_cast@plt 2.14% flipcase-clang- libstdc++.so.6.0.21 [.] _ZNKSt6locale2id5_M_idEv 2.11% flipcase-clang- libstdc++.so.6.0.21 [.] _ZNKSt6locale2id5_M_idEv@plt 2.08% flipcase-clang- libstdc++.so.6.0.21 [.] _ZNKSt5ctypeIcE10do_toupperEc 2.03% flipcase-clang- flipcase-clang-boost [.] _ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale@plt 0.08% ...

Autovectorización

Gcc y clang solo vectorizarán automáticamente los bucles cuando se conozca el recuento de iteraciones antes del bucle. (Es decir, los bucles de búsqueda, como la implementación de strlen plano C, no se autovectorizarán).

Por lo tanto, para cadenas lo suficientemente pequeñas como para caber en la memoria caché, obtenemos una aceleración significativa para cadenas ~ 128 caracteres de hacer strlen primero. Esto no será necesario para las cadenas de longitud explícita (como C ++ std::string ).

// 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; }

Cualquier libc decente tendrá un strlen eficiente que es mucho más rápido que un byte en bucle a la vez, por lo que los strlen vectorizados separados y toupper son más rápidos.

Línea de base: un bucle que comprueba si hay un 0 que termina en la marcha.

Tiempos para 40M iteraciones, en un Core2 (Merom) de 2.4GHz. gcc 5.2 -O3 -march=native . (Ubuntu 15.10). dst != src (así que hacemos una copia), pero no se superponen (y no están cerca). Ambos están alineados.

  • Cadena de 15 caracteres: línea de base: 1.08s. autovec: 1.34s
  • Cadena de 16 caracteres: línea de base: 1.16s. autovec: 1.52s
  • Cadena de caracteres 127: línea de base: 8.91s. autovec: 2.98s // la limpieza no vectorial tiene 15 caracteres para procesar
  • Cadena de caracteres 128: línea de base: 9.00s. autovec: 2.06s
  • Cadena de caracteres 129: línea de base: 9.04s. autovec: 2.07s // la limpieza no vectorial tiene 1 carácter para procesar

Algunos resultados son un poco diferentes con clang.

El bucle de marca microbiológica que llama a la función está en un archivo separado. De lo contrario, se alinea y strlen() se echa fuera del bucle, y se ejecuta dramáticamente más rápido, especialmente. para 16 cadenas de caracteres (0.187s).

Esto tiene la gran ventaja de que gcc puede auto-vectorizarlo para cualquier arquitectura, pero la mayor desventaja es que es más lento para el caso generalmente común de cadenas pequeñas.

Así que hay grandes aceleraciones, pero la auto-vectorización del compilador no es un gran código, especialmente. Para la limpieza de los últimos hasta 15 caracteres.

Vectorización manual con intrínsecos SSE:

Basado en mi función de cambio de caso que invierte el caso de cada carácter alfabético. Aprovecha el "truco de comparación sin signo", donde puede hacer low < a && a <= high con una única comparación sin signo por cambio de rango, de modo que cualquier valor inferior a low wraps a un valor mayor que high . (Esto funciona si lo low y lo high no están muy separados).

SSE solo tiene un signo de comparación mayor, pero aún podemos usar el truco de "comparación sin signo" cambiando el rango al final del rango firmado: reste ''a'' + 128, por lo que los caracteres alfabéticos varían de -128 a -128 +25 (-128 + ''z'' - ''a'')

Tenga en cuenta que sumar 128 y restar 128 son lo mismo para enteros de 8 bits. No hay ningún lugar para el carry to go, así que es solo xor (add carryless), cambiando el bit alto.

#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 }

Dada esta función que funciona para un vector, podemos llamarla en un bucle para procesar una cadena completa. Como ya nos estamos enfocando en SSE2, podemos hacer una verificación vectorializada de fin de cadena al mismo tiempo.

También podemos hacer mucho mejor para la "limpieza" de los últimos hasta 15 bytes que quedan después de hacer vectores de 16B: la carcasa superior es idempotente, por lo que volver a procesar algunos bytes de entrada está bien. Hacemos una carga no alineada de los últimos 16B de la fuente, y los almacenamos en el búfer de destino superponiendo la última tienda de 16B del bucle.

La única vez que esto no funciona es cuando la cadena completa está por debajo de 16B: Incluso cuando dst=src , la lectura-modificación-escritura no atómica no es lo mismo que no tocar algunos bytes en absoluto, y puede romper el código de multiproceso.

Tenemos un bucle escalar para eso, y también para alinear src . Como no sabemos dónde estará el 0 de terminación, una carga no alineada de src podría pasar a la página siguiente y segfault. Si necesitamos bytes en un fragmento 16B alineado, siempre es seguro cargar todo el fragmento 16B alineado.

Fuente completa: en un 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; }

Tiempos para 40M iteraciones, en un Core2 (Merom) de 2.4GHz. gcc 5.2 -O3 -march=native . (Ubuntu 15.10). dst != src (así que hacemos una copia), pero no se superponen (y no están cerca). Ambos están alineados.

  • Cadena de 15 caracteres: línea de base: 1.08s. autovec: 1.34s. manual: 1.29s
  • Cadena de 16 caracteres: línea de base: 1.16s. autovec: 1.52s. manual: 0.335s
  • Cadena de 31 caracteres: manual: 0.479s
  • Cadena de caracteres 127: línea de base: 8.91s. autovec: 2.98s. manual: 0.925s
  • Cadena de caracteres 128: línea de base: 9.00s. autovec: 2.06s. manual: 0.931s
  • Cadena de caracteres 129: línea de base: 9.04s. autovec: 2.07s. manual: 1.02s

(Realmente cronometrado con _mm_store en el bucle, no _mm_storeu , porque storeu es más lento en Merom incluso cuando la dirección está alineada. Está bien en Nehalem y más tarde. También dejé el código como está por ahora, en lugar de corregir el error para copiar la terminación 0 en algunos casos, porque no quiero volver a cronometrar todo.)

Por lo tanto, para cadenas cortas más largas que 16B, esto es dramáticamente más rápido que auto-vectorizado. Las longitudes de un ancho menor que un vector no presentan un problema. Pueden ser un problema cuando se opera en el lugar, debido a un bloqueo de reenvío de la tienda. (Pero tenga en cuenta que todavía está bien procesar nuestra propia salida, en lugar de la entrada original, porque toupper es idempotente).

Hay mucho margen para ajustar esto para diferentes casos de uso, dependiendo de lo que quiera el código circundante y la microarquitectura objetivo. Conseguir que el compilador emita un código agradable para la parte de limpieza es complicado. El uso de ffs(3) (que compila a bsf o tzcnt en x86) parece ser bueno, pero obviamente eso necesita un replanteamiento ya que noté un error después de escribir la mayor parte de esta respuesta (vea los comentarios de FIXME).

Las aceleraciones de vectores para cadenas incluso más pequeñas se pueden obtener con movq o movd / stores. Personalizar según sea necesario para su caso de uso.

UTF-8:

Podemos detectar cuándo nuestro vector tiene bytes con el bit alto establecido y, en ese caso, retroceder a un bucle escalar con reconocimiento utf-8 para ese vector. El punto dst puede avanzar en una cantidad diferente a la del puntero src , pero una vez que regresemos a un puntero src alineado, haremos almacenes de vectores no alineados en dst .

Para el texto que es UTF-8, pero en su mayoría consiste en el subconjunto ASCII de UTF-8, esto puede ser bueno: alto rendimiento en el caso común con comportamiento correcto en todos los casos. Sin embargo, cuando hay una gran cantidad de personas que no son ASCII, probablemente será peor que permanecer todo el tiempo en el circuito escalar consciente de UTF-8.

Hacer el inglés más rápido a expensas de otros idiomas no es una decisión preparada para el futuro si la desventaja es significativa.

Locale-consciente:

En la configuración regional turca ( tr_TR ), el resultado correcto de toupper(''i'') es ''İ'' (U0130), no ''I'' (ASCII simple). Vea los comentarios de Martin Bonner sobre una pregunta acerca de que tolower() es lento en Windows.

También podemos comprobar si hay una lista de excepciones y un retroceso para escalar allí, como para los caracteres de entrada UTF8 de múltiples bytes.

Con esta gran complejidad, SSE4.2 PCMPISTRM o algo podría ser capaz de hacer muchos de nuestros controles de una sola vez.


Esta función c ++ siempre devuelve la cadena de mayúsculas ...

#include <locale> #include <string> using namespace std; string toUpper (string str){ locale loc; string n; for (string::size_type i=0; i<str.length(); ++i) n += toupper(str[i], loc); return n; }


Sin utilizar ninguna librería:

std::string YourClass::Uppercase(const std::string & Text) { std::string UppperCaseString; UppperCaseString.reserve(Text.size()); for (std::string::const_iterator it=Text.begin(); it<Text.end(); ++it) { UppperCaseString.push_back(((0x60 < *it) && (*it < 0x7B)) ? (*it - static_cast<char>(0x20)) : *it); } return UppperCaseString; }


En todas las máquinas que probé, fue más rápido. Tal vez porque no le preocupa una gran variedad de personajes. O porque al usar switch () hace una tabla de salto, no sé cómo funciona en el ensamblaje ... simplemente sepa que es más rápido:

string Utils::String::UpperCase(string CaseString) { for (unsigned short i = 0, tamanho = CaseString.length(); i < tamanho; i++) { switch (CaseString[i]) { case ''a'': CaseString[i] = ''A''; break; case ''b'': CaseString[i] = ''B''; break; case ''c'': CaseString[i] = ''C''; break; case ''d'': CaseString[i] = ''D''; break; case ''e'': CaseString[i] = ''E''; break; case ''f'': CaseString[i] = ''F''; break; case ''g'': CaseString[i] = ''G''; break; case ''h'': CaseString[i] = ''H''; break; case ''i'': CaseString[i] = ''I''; break; case ''j'': CaseString[i] = ''J''; break; case ''k'': CaseString[i] = ''K''; break; case ''l'': CaseString[i] = ''L''; break; case ''m'': CaseString[i] = ''M''; break; case ''n'': CaseString[i] = ''N''; break; case ''o'': CaseString[i] = ''O''; break; case ''p'': CaseString[i] = ''P''; break; case ''q'': CaseString[i] = ''Q''; break; case ''r'': CaseString[i] = ''R''; break; case ''s'': CaseString[i] = ''S''; break; case ''t'': CaseString[i] = ''T''; break; case ''u'': CaseString[i] = ''U''; break; case ''v'': CaseString[i] = ''V''; break; case ''w'': CaseString[i] = ''W''; break; case ''x'': CaseString[i] = ''X''; break; case ''y'': CaseString[i] = ''Y''; break; case ''z'': CaseString[i] = ''Z''; break; } } return CaseString; }


Si solo le preocupan los caracteres de 8 bits (que todas las demás respuestas, excepto Milan Babuškov suponen también), puede obtener la velocidad más rápida al generar una tabla de consulta en el momento de la compilación mediante metaprogramación. En ideone.com esto se ejecuta 7 veces más rápido que la función de biblioteca y 3 veces más rápido que una versión escrita a mano ( http://ideone.com/sb1Rup ). También es personalizable a través de rasgos sin ralentización.

template<int ...Is> struct IntVector{ using Type = IntVector<Is...>; }; template<typename T_Vector, int I_New> struct PushFront; template<int ...Is, int I_New> struct PushFront<IntVector<Is...>,I_New> : IntVector<I_New,Is...>{}; template<int I_Size, typename T_Vector = IntVector<>> struct Iota : Iota< I_Size-1, typename PushFront<T_Vector,I_Size-1>::Type> {}; template<typename T_Vector> struct Iota<0,T_Vector> : T_Vector{}; template<char C_In> struct ToUpperTraits { enum { value = (C_In >= ''a'' && C_In <=''z'') ? C_In - (''a''-''A''):C_In }; }; template<typename T> struct TableToUpper; template<int ...Is> struct TableToUpper<IntVector<Is...>>{ static char at(const char in){ static const char table[] = {ToUpperTraits<Is>::value...}; return table[in]; } }; int tableToUpper(const char c){ using Table = TableToUpper<typename Iota<256>::Type>; return Table::at(c); }

con caso de uso:

std::transform(in.begin(),in.end(),out.begin(),tableToUpper);

Para una descripción detallada (en muchas páginas) de cómo funciona, me permite conectar mi blog sin vergüenza: http://metaporky.blogspot.de/2014/07/part-4-generating-look-up-tables-at.html


Yo uso esta solución. Sé que no se supone que modifiques esa área de datos ... pero creo que eso se debe principalmente a errores de desbordamiento de búfer y caracteres nulos ... las cosas de mayúsculas no son lo mismo.

void to_upper(const std::string str) { std::string::iterator it; int i; for ( i=0;i<str.size();++i ) { ((char *)(void *)str.data())[i]=toupper(((char *)str.data())[i]); } }


#include <algorithm> #include <string> std::string str = "Hello World"; std::transform(str.begin(), str.end(),str.begin(), ::toupper);


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


#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());

Esto funcionará mejor que todas las respuestas que usan la función global toupper, y es presumiblemente lo que boost :: to_upper está haciendo debajo.

Esto se debe a que :: toupper tiene que buscar la configuración regional (porque puede haber sido cambiado por un hilo diferente) para cada invocación, mientras que aquí solo la llamada a la configuración regional () tiene esta penalización. Y buscar el lugar generalmente implica tomar un candado.

Esto también funciona con C ++ 98 después de reemplazar el auto, el uso de la nueva str.data no constante () y agregar un espacio para romper el cierre de la plantilla (">>" a ">>") de esta manera:

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());


std::string value; for (std::string::iterator p = value.begin(); value.end() != p; ++p) *p = toupper(*p);


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

O,

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


struct convert { void operator()(char& c) { c = toupper((unsigned char)c); } }; // ... string uc_str; for_each(uc_str.begin(), uc_str.end(), convert());

Nota: Un par de problemas con la solución superior:

21.5 Utilidades de secuencia terminadas en nulo

El contenido de estos encabezados será el mismo que los encabezados de la Biblioteca C estándar <ctype.h>, <wctype.h>, <string.h>, <wchar.h> y <stdlib.h> [...]

  • Lo que significa que los miembros de cctype pueden ser macros no adecuados para el consumo directo en algoritmos estándar.

  • Otro problema con el mismo ejemplo es que no emite el argumento ni verifica que esto no sea negativo; esto es especialmente peligroso para los sistemas donde está firmado el llano char . (La razón es: si esto se implementa como una macro, probablemente utilizará una tabla de búsqueda y los índices de sus argumentos en esa tabla. Un índice negativo le dará UB).


template<size_t size> char* toupper(char (&dst)[size], const char* src) { // generate mapping table once static char maptable[256]; static bool mapped; if (!mapped) { for (char c = 0; c < 256; c++) { if (c >= ''a'' && c <= ''z'') maptable[c] = c & 0xdf; else maptable[c] = c; } mapped = true; } // use mapping table to quickly transform text for (int i = 0; *src && i < size; i++) { dst[i] = maptable[*(src++)]; } return dst; }


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 );