[Introducción a C++] Métodos comunes de la clase de cadena (explicación detallada de 10,000 caracteres)

1. Introducción a STL

1.1 ¿Qué es STL?

STL (biblioteca de plantillas estándar libaray-plantilla estándar): es una parte importante de la biblioteca estándar de C ++, no solo una biblioteca de componentes reutilizable, sino también un marco de software que incluye estructuras de datos y algoritmos.
inserte la descripción de la imagen aquí

Versión 1.2STL

  • Copia original

La versión original completada por Alexander Stepanov y Meng Lee en Hewlett-Packard Labs, en el espíritu del código abierto, declaran que permiten a cualquier persona usar, copiar, modificar, difundir y utilizar comercialmente estos códigos libremente sin pago. La única condición es que también debe utilizarse como código abierto como la versión original.
Versión HP: el abuelo de todas las implementaciones STL

  • versión pijama

Desarrollado por PJ Plauger, heredado de la versión HP, adoptado por Windows Visual C++, no se puede divulgar ni modificar, defecto: baja legibilidad, denominación de símbolos extraña.

  • versión RW

Desarrollado por Rouge Wage Company, heredado de la versión HP, adoptado por C++ Builder, no se puede divulgar ni modificar y su legibilidad es media.

  • versión SGI

Desarrollado por Silicon Graphics Computer Systems, Inc., heredado de la versión HP. Adoptado por GCC (Linux), tiene buena portabilidad, se puede hacer público, modificar e incluso vender, y desde el punto de vista del estilo de nomenclatura y estilo de programación, es muy legible.Cuando aprendamos STL más adelante, necesitaremos leer parte del código fuente, la referencia principal es esta versión.

1.3 Seis componentes principales de STL

Aquí está la cita
Comprenda los seis componentes principales primero y aprenda lentamente después.

1.4 Defectos de STL

  1. La actualización de la biblioteca STL es demasiado lenta. Esta es una queja seria: la versión anterior era C ++ 98 y el C ++ 03 intermedio fue básicamente revisado. Han pasado 13 años desde que salió C++ 11 y STL solo se actualizó más.
  2. Actualmente, STL no admite la seguridad de subprocesos. En un entorno concurrente, necesitamos encerrarnos. Y la granularidad de la cerradura es relativamente grande.
  3. La búsqueda extrema de eficiencia por parte de STL conduce a la complejidad interna. Como extracción de tipos, extracción de iteradores.
  4. El uso de STL tiene el problema de la expansión del código. Por ejemplo, el uso de vector/vector/vector generará múltiples copias de código. Por supuesto, esto se debe a la sintaxis de la plantilla en sí.

2. Uso de clase de cadena

2.1 Cadenas en lenguaje C

En lenguaje C, una cadena es una colección de algunos caracteres que terminan en '\0'. Para facilitar la operación, la biblioteca estándar de C proporciona algunas funciones de biblioteca de la serie str, pero estas funciones de biblioteca están separadas de la cadena y no Se ajusta a la idea de programación orientada a objetos (idea orientada a objetos), y el espacio subyacente debe ser administrado por el usuario, y se puede acceder a él fuera de los límites si no se tiene cuidado.

2.2 La clase de cadena en la biblioteca estándar

La clase de cadena es en realidad una clase de plantilla instanciada a partir de una plantilla de clase.
Introducción a la documentación de la clase de cadena.
inserte la descripción de la imagen aquí
Podemos ver que en realidad es basic_stringuna definición de tipo de la clase instanciada a partir de esta plantilla de clase.

Aquí, basic_stringademás de la cadena, se crean instancias de otras tres clases de plantilla.
inserte la descripción de la imagen aquí
Todas son clases de plantilla instanciadas a partir de la plantilla de clase basic_string, la diferencia es que los tipos de sus parámetros de plantilla correspondientes son diferentes.

Para la clase de cadena: de hecho, su capa inferior es una matriz de caracteres dinámica,
cadena es un chartipo de matriz de caracteres wstring es la matriz de caracteres
correspondiente u16string es la matriz de caracteres u32string es la matriz de caracteres Los tamaños correspondientes de estos diferentes tipos de caracteres son también diferente.wchar_t
char16_t
char32_t

Entonces, ¿por qué inventar tantos personajes?

En realidad, esto se debe a que
Por favor agregue una descripción de la imagen.
todos los símbolos y letras del código ASCII tienen un valor de código ASCII correspondiente.
De hecho, las letras en sí no se almacenan en la memoria, sino sus valores de código ASCII correspondientes (que se muestran aquí en hexadecimal).
Pero ASCII se usa principalmente para mostrar idiomas como el inglés, y hay muchos países e idiomas en el mundo. Por ejemplo, si queremos que las computadoras muestren chino, el código ASCII no funcionará.
Por esta razón, alguien inventó Unicode-Unicode (compatible con ASCII):
Unicode se divide en , UTF-8y UTF-16estos UTF-32.

Entonces, para manejar estas diferentes codificaciones, se producen estos diferentes tipos de caracteres, por lo que existe basic_stringesta plantilla de clase de cadena genérica, que podemos usar para crear instancias de diferentes tipos de clases de cadena.

Resumir:

  1. cadena es una clase de cadena que representa cadenas
  2. La interfaz de esta clase es básicamente la misma que la de los contenedores normales, y se agregan algunas operaciones regulares especialmente utilizadas para manipular cadenas.
  3. la cadena está en realidad en la parte inferior: basic_stringel alias de la clase de plantilla,typedef basic_string<char, char_traits, allocator> string;
  4. No se pueden manipular secuencias de caracteres multibyte o de longitud variable.
  5. Cuando utilice la clase de cadena, debe incluir archivos de encabezado #include y usar el espacio de nombres std;

2.3 Descripción de la interfaz común de la clase de cadena (explica solo la interfaz más utilizada)

2.3.1 Construcción común de objetos de clase de cadena

Aquí está la cita

(constructor) nombre de la función Función descriptiva
string() (enfoque del constructor predeterminado del constructor de cadena vacía) Construye una cadena vacía con caracteres de longitud cero
cadena (const char* s) (énfasis) Construye un objeto similar a una cadena a partir de una cadena constante
cadena (const string& str, size_t pos, size_t len ​​​​= npos) (no se usa con frecuencia) Copia la parte de str que comienza en la posición del carácter pos y abarca len caracteres (o hasta el final de str si str es demasiado corto o len es string::npos)
cadena (const char* s, size_t n) Tome s para apuntar a los primeros n caracteres de la cadena para construir un objeto de cadena
cadena (size_t n, char c) Tome n caracteres c para construir un objeto de cadena
cadena (cadena constante y cadena) (énfasis) copiar construcción
cadena de plantilla (InputIterator primero, InputIterator último) Después del iterador

Empecemos a explicar uno por uno:

  1. string()
    inserte la descripción de la imagen aquí
    Aquí construimos una cadena vacía.
  1. ** string (const char* s)**
    inserte la descripción de la imagen aquí
    Esto también se admite aquí:
    inserte la descripción de la imagen aquí
    esto es de lo que hablamos antesEl constructor de un solo parámetro admite la conversión de tipos implícita
    inserte la descripción de la imagen aquí
  1. string (const string& str, size_t pos, size_t len = npos)
    Aquí, se utiliza una subcadena en str para construir un objeto de cadena. Esta cadena comienza desde la posición pos del subíndice en str y tiene una longitud de len.
    inserte la descripción de la imagen aquí
    Si el de aquí stres más corto, o si se proporciona aquí len, string::nposentonces esta cadena va al strfinal de.
    Para dar un ejemplo simple:
    inserte la descripción de la imagen aquí
    La longitud aquí es 30, por lo que la longitud de la cadena aquí no es suficiente, es más corta que 30, pero no se informará ningún error aquí y la posición final de la cadena se tomará aquí.. Si se
    proporciona aquí , irá al final de str y el valor predeterminado se proporcionará aquí, que es el valor predeterminado . ¿ Qué hay aquí ?lenstring::nposlennpos
    inserte la descripción de la imagen aquí
    npos
    inserte la descripción de la imagen aquí
    Es una variable miembro estática con un valor de -1, pero aquí su tipo es size_t(entero sin signo), por lo que en realidad es el valor máximo del entero aquí.
  1. string (const char* s, size_t n)
    Utilice s para señalar los primeros n caracteres de la cadena para construir un objeto de cadena:
    inserte la descripción de la imagen aquí
  1. string (size_t n, char c)
    Utilice n caracteres c para construir un objeto de cadena
    inserte la descripción de la imagen aquí
  1. string (const string& str)
    Copiar construcción:
    inserte la descripción de la imagen aquí
2.3.2 Operación de capacidad de objetos de cadena

Aquí está la cita

  1. sizey lengh
    inserte la descripción de la imagen aquí
    ambos devuelven la longitud de la cadena.
    inserte la descripción de la imagen aquí
    Aquí quizás se pregunte por qué es necesario escribir dos interfaces para la misma función.
    De hecho, tiene algo que ver con algunas razones históricas.La cadena apareció antes que STL, estrictamente hablando, la cadena no pertenece a STL, es generada por la biblioteca estándar de C++ y existía antes de que apareciera STL..
    La cadena se diseñó originalmente como longitud, pero después de la aparición de STL, otras estructuras de datos en ella usaban tamaño, por lo que para mantener la coherencia, se agregó un tamaño a la cadena.
    por lo tantoEl principio de implementación subyacente de los métodos size() y length() es exactamente el mismo. La razón para introducir size() es ser consistente con las interfaces de otros contenedores. En general, size() se usa básicamente
  1. max_size
    inserte la descripción de la imagen aquí
    Lo que hace es devolver la longitud máxima que puede tener la cadena.
    inserte la descripción de la imagen aquí
    De hecho, la cadena no puede ser tan larga y el valor es diferente en diferentes plataformas.
  1. capacity
    inserte la descripción de la imagen aquí
    Aquí se devuelve la capacidad del objeto de cadena actual (es decir, cuánto espacio se le asigna actualmente, expresado en bytes)
    inserte la descripción de la imagen aquí
    ==Aquí no incluye el espacio para '\0', porque cree que '\0' no es un carácter válido.

Para otros veteranos, pueden verlo temporalmente junto con el documento y se lo explicaré más adelante.

2.3.3 Operación de modificación del objeto de clase de cadena

inserte la descripción de la imagen aquí

  1. push_back
    inserte la descripción de la imagen aquí
    Como su nombre lo indica, significa push_backinserción de cola ( añadir 1 carácter ).
    inserte la descripción de la imagen aquí
  1. append
    Si desea agregar una cadena, puede usarappend
    inserte la descripción de la imagen aquí
    Hay muchas versiones sobrecargadas aquí, pero la más utilizada es agregar directamente una cadena
    inserte la descripción de la imagen aquí
  1. operator+=
    De hecho, normalmente no nos gusta usar push_backy append. En lugar de eso, úsalo operator+=.
    La cadena está sobrecargada +=(como se menciona en el artículo antes de la sobrecarga del operador), lo cual es muy conveniente de usar.
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí
2.3.4 resizeyreserve

resizeCon el conocimiento anterior, volvamos a mirar la suma en la capacidad reserve.

Antes de eso, observemos cómo un objeto de cadena se expande en el proceso de inserción continua de datos.

int main()
{
    
    
	string s;
	size_t sz = s.capacity();
	cout << "capacity changed: " << sz << '\n';
	for (int i = 0; i < 100; ++i)
	{
    
    
		s.push_back('c');
		if (sz != s.capacity())
		{
    
    
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
	return 0;
}

inserte la descripción de la imagen aquí
Aquí, casi todas las expansiones del código VS son una expansión doble.

Después de comprender brevemente el mecanismo de expansión aquí, echemos un vistazo reserve.r eservepuede ayudarnos a cambiar la capacidad, de modo que si sabemos cuánto espacio necesitamos, podamos abrirlo en el lugar al mismo tiempo, para no tener que ampliar la capacidad una y otra vez..
inserte la descripción de la imagen aquí
Ahora especificamos la capacidad de reserva 100,No tiene que ser 100, tal vez por algunas razones como la alineación, te dará más espacio, pero definitivamente no será menor que 100.
inserte la descripción de la imagen aquí
Si sabemos cuánto espacio necesitamos, reservar puede ayudarnos a abrir espacio con anticipación y luego reducir la expansión y mejorar la eficiencia.

¿De qué sirve eso resize?

resizeNo solo se puede abrir el espacio, sino que también se puede inicializar el espacio abierto.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Aquí no especificamos el segundo parámetro, los caracteres a completar se proporcionan de forma predeterminada \0, por supuesto, también podemos especificar los caracteres a completar nosotros mismos:
inserte la descripción de la imagen aquí
>
Si el n que pasamos es menor que la longitud de la cadena actual, También puede ayudarnos a eliminar el contenido adicional :
inserte la descripción de la imagen aquí
Tenga en cuenta que sólo cambia aquí size, capacityno.
En circunstancias normales, no es fácil reducir la capacidad. Si se reduce la capacidad, generalmente no admite la reducción in situ. Debido a algunas razones de la gestión de memoria subyacente, no se puede reducir in situ.
Si se admite la contracción en el lugar, ¿es necesario admitir la liberación de una parte? Solicitamos un espacio y solo se libera una parte si no se utiliza.
Pero no admite solo una parte de forma gratuita, ya que no es necesario que pasemos el puntero de forma gratuita, sino que debe apuntar a la ubicación real.
Entonces, si realmente desea reducir, solo puede reducir en un lugar diferente, es decir, abrir un nuevo espacio pequeño, copiar los datos requeridos allí y luego liberar el espacio original. Por lo tanto, la reducción de la capacidad se produce a costa del rendimiento, que no es compatible con el sistema de forma nativa y debemos hacerlo nosotros mismos. Así que no te encojas fácilmente a menos que sea necesario.

2.3.5 Iterador (adelante)

Ahora queremos iterar sobre un objeto de cadena. Primero, podemos usar [ ]transversal porque la cadena está sobrecargada [ ], o puedo usar rango para. Además de estos métodos, también podemos utilizar iteradores.
inserte la descripción de la imagen aquí

Tomemos un ejemplo sencillo:

int main()
{
    
    
	string s1("hello world");
	string::iterator it = s1.begin();
	while (it != s1.end())
	{
    
    
		cout << *it << " ";
		it++;
	}
	return 0;
}

Aquí está la cita
El it aquí es un iterador de la clase de cadena que definimos ( string::iteratores un tipo). En esta etapa, puedes pensar en un iterador como algo así como un puntero (no necesariamente un puntero).
inserte la descripción de la imagen aquí
El inicio aquí devolverá un iterador que apunta al primer carácter de la cadena.
inserte la descripción de la imagen aquí
El final aquí devolverá un iterador que apunta a la posición después del último carácter..
Podemos entenderlo como un puntero a dos posiciones:
inserte la descripción de la imagen aquí

2.3.6 Iteradores inversos

Además de admitir el recorrido hacia adelante y hacia atrás como se indicó anteriormente, los iteradores también admiten el recorrido inverso, y el recorrido inverso se denomina iterador inverso.

Aquí está la cita

inserte la descripción de la imagen aquí
Aquí rbegin() devuelve un iterador inverso que apunta al último carácter de la cadena..
inserte la descripción de la imagen aquí
aquírend() devuelve un iterador inverso que apunta al carácter anterior de la cadena

Veamos nuevamente el ejemplo anterior:

int main()
{
    
    
	string s1("hello world");
	string::reverse_iterator it = s1.rbegin();
	while (it != s1.rend())
	{
    
    
		cout << *it << " ";
		it++;
	}
	return 0;
}

inserte la descripción de la imagen aquí

2.3.7 iterador constante (adelante y atrás)

Para objetos constantes que no se pueden modificar, los iteradores ordinarios pueden considerarlo como algo parecido a un puntero, luegoNo podemos modificarlo eliminando la referencia, por lo que no podemos usar iteradores ordinarios aquí, lo que provocará una amplificación de privilegios.
inserte la descripción de la imagen aquí
Vemos begin()que si comienzan las llamadas a un objeto constante, se devuelve el iterador constante const_iterator. Los iteradores ordinarios pueden leer y modificar datos, pero los iteradores constantes solo se pueden leer y no se pueden modificar.

El iterador inverso constante es el iterador que el objeto constante llama rbegin()y rend()devuelveconst_reverse_iterator
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
Aquí C++ 11 proporciona otro conjunto de iteradores cbegin cend crbegin crend, que solo devuelven iteradores constantes.

2.3.8 Acceso a elementos

Aquí está la cita

La cadena está sobrecargada [], podemos usarla directamente:
inserte la descripción de la imagen aquí

operator[]También hay una versión normal y una versión constante. El objeto normal llama a [] y devuelve char&el objeto constante const char&, que no se puede modificar.
inserte la descripción de la imagen aquí

atEl efecto []es el mismo. Sin embargo, todavía existe una diferencia entre los dos, la diferencia es:
Si []se accede fuera de los límites, informará directamente un error y utilizará aserciones para juzgar internamente. atestá lanzando una excepción
inserte la descripción de la imagen aquí

backLa función de y frontes devolver el último y el primer carácter, pero podemos usar esto []para hacerlo, para que puedas entenderlo fácilmente.

2.3.9 insertyerase

Al usarlo insert, podemos insertar caracteres y cadenas en el objeto de cadena:
inserte la descripción de la imagen aquí
aquí insert proporciona varias versiones, solo necesitamos dominar algunas de las más utilizadas.
inserte la descripción de la imagen aquí
Ahora queremos insertar una cadena hola delante del mundo, podemos considerar usar esto:
inserte la descripción de la imagen aquí
El primer parámetro es la posición a insertar, el segundo es la cadena insertada..
inserte la descripción de la imagen aquí
Ahora queremos insertar un espacio en la quinta posición, podemos usar esto:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

También podemos considerar el uso de iteradores:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Aviso:Para cuerdas, no recomendamos el uso frecuente del inserto. Debido a que la capa inferior de la cadena es una matriz de caracteres, hemos aprendido la estructura de los datos y sabemos que para insertar elementos en la tabla de secuencia es necesario mover los datos, y la eficiencia es relativamente baja.

Veámoslo de nuevo erase:
eraseEs eliminar los elementos en el objeto de cadena.
inserte la descripción de la imagen aquí

Para dar un ejemplo simple:

Aquí está la cita
Ahora podemos aprovechar la eraseeliminación de espacios finales:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

2.3.10 reemplazar, buscar, rfind, substr

Echemos un vistazo a reemplazar:
inserte la descripción de la imagen aquí
la función de reemplazar es en realidad reemplazar parte de la cadena con contenido nuevo. Aquí también elegimos explicaciones de uso común.

Tomemos un ejemplo:

Aquí está la cita
Ahora necesitamos reemplazar los espacios en s con "hhh":
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Veamos encontrar nuevamente:
inserte la descripción de la imagen aquí
find puede buscar una cadena o un carácter en una cadena y devolver el subíndice correspondiente. no encontrado devolver npos

Pongamos otro ejemplo:
inserte la descripción de la imagen aquí
ahora quiero encontrar "w" en s:
inserte la descripción de la imagen aquí

Veamos rfind nuevamente:
inserte la descripción de la imagen aquí
find es encontrar la primera coincidencia de adelante hacia atrás, rfind es encontrar la última coincidencia de atrás hacia adelante

Miremos substr nuevamente:
inserte la descripción de la imagen aquí
substrpuede ayudarnos a obtener una subcadena especificada en el objeto de cadena.
Por ejemplo:
inserte la descripción de la imagen aquí
aquí obtenemos la subcadena con una longitud de cinco a partir de la sexta posición.

2.3.11 cadena::intercambiar

inserte la descripción de la imagen aquí
A diferencia del intercambio en la biblioteca estándar, el intercambio aquí recibe un objeto de cadena y lo intercambia con el objeto actual.
inserte la descripción de la imagen aquí

2.3.12 cadena_c

Echemos un vistazo nuevamente c_str:
inserte la descripción de la imagen aquí
su función es devolver un puntero a la matriz de caracteres correspondiente al objeto de cadena actual, y el tipo es const char*.
inserte la descripción de la imagen aquí

2.3.13 obtener línea

Tomemos un ejemplo:

int main()
{
    
    
	string s;
	cin >> s;
	cout << s << endl;
	return 0;
}

Ahora quiero ingresar hola mundo, ¿puede salir normalmente?
inserte la descripción de la imagen aquí
El cin aquí, cuando los usamos para ingresar, es posible ingresar múltiples valores, luego, cuando ingresamos múltiples valores, usan espacios o nuevas líneas de forma predeterminada para distinguir los múltiples valores que ingresamos.
Entonces, lo que ingresamos aquí hello worldse considerará como dos valores separados por un espacio, por lo que el valor cin se lee hola antes del espacio y el siguiente mundo se deja en el búfer.

Podemos getlinesolucionar este problema con:
inserte la descripción de la imagen aquí
getline finaliza cuando lee un espacio y, por supuesto, también nos permite especificar el terminador. El primer parámetro es recibir cin y el segundo parámetro es recibir el objeto de cadena que queremos ingresar.
inserte la descripción de la imagen aquí

2.4 Resumen

Aquí se trata de la interfaz común de cadena. Hay muchas interfaces de cadena aquí. Si encuentra algo que no está claro más adelante, le sugiero que lea la cadena del documento oficial.

Supongo que te gusta

Origin blog.csdn.net/weixin_69423932/article/details/132584567
Recomendado
Clasificación