Espada se refiere a la cadena oferta-2.2

cadena

Cada cadena en C/C+ "\0termina con el carácter ", por lo que podemos encontrar fácilmente el último extremo de la cadena. Pero debido a esta característica, hay una sobrecarga de un carácter extra en cada cadena. Si no prestas atención , Esto hará que la cadena se salga de los límites. Por ejemplo, el siguiente código:

char str [10];
strcpy(str, "0123456789");

Primero declaramos una matriz de caracteres con una longitud de 10 y luego copiamos la cadena "0123456789" en la matriz. La cadena "0123456789" parece que solo tiene 10 caracteres, pero en realidad tiene un carácter "0" al final, por lo que su longitud real es de 11 bytes. Para copiar esta cadena correctamente, necesita al menos una matriz de 11 bytes de longitud.

Para ahorrar memoria, C/C++ coloca cadenas constantes en un área de memoria separada. Cuando se asignan varios punteros a la misma cadena constante, en realidad apuntan a la misma dirección de memoria. Pero al inicializar una matriz con memoria constante, la situación es diferente. Aprendamos este conocimiento a través de una pregunta de entrevista. ¿Cuál es el resultado de ejecutar el siguiente código?

int main(int argc, char* argv[])
{
    
    
     char str1[] = "hello world";
     char str2[] = "hello world";

     char* str3 = "hello world";
     char* str4 = "hello world";

     if(str1 == str2)
        printf("str1 and str2 are same.\n");
     else
        printf("str1 and str2 are not same.\n");

     if(str3 == str4)
        printf("str3 and str4 are same.\n");
     else
        printf("str3 and str4 are not same.\n");
        
     return 0;
}

str1 y str2 son dos matrices de cadenas, les asignaremos dos espacios con una longitud de 12 bytes y copiaremos el contenido de "hola mundo" en las matrices respectivamente. Estas son dos matrices con direcciones iniciales diferentes, por lo que los valores de strl y str2 también son diferentes, por lo que la primera línea de salida es "str1 y str2 no son iguales".

str3 y str4 son dos punteros, no necesitamos asignarles memoria para almacenar el contenido de la cadena, solo necesitamos señalarles la dirección de "hola mundo" en la memoria. Dado que "helloworld" es una cadena constante, solo tiene una copia en la memoria, por lo que str3 y str4 apuntan a la misma dirección. Entonces, el resultado de comparar los valores de str3 y str4 es el mismo, y la segunda línea de salida es "str3 y str4 son iguales".

reemplazar espacios

Pregunta: Implemente una función para reemplazar cada espacio en la cadena con "%20". Por ejemplo, si se ingresa "Estamos contentos", se generará "Estamos%20estamos%20felices".

En la programación de red, si los parámetros de URL contienen caracteres especiales, como espacios, '#', etc., es posible que el servidor no pueda obtener los valores de parámetro correctos. Necesitamos convertir estos símbolos especiales en caracteres que el servidor pueda reconocer. La regla de conversión es seguir '%' seguido de la representación hexadecimal de dos dígitos del código ASCII. Por ejemplo, el código ASCII de un espacio es 32, que es 0x20 en hexadecimal, por lo que el espacio se reemplaza por "%20". Para otro ejemplo, el código ASCI de '#' es 35, que es 0x23 en hexadecimal y se reemplaza por "%23" en la URL.

Cuando vemos esta pregunta, lo primero que debemos pensar es que el carácter de espacio original se convierte en '%', '2' y '0' después del reemplazo, por lo que la cadena se hará más larga. Si está reemplazando la cadena original, es posible sobrescribir y modificar la memoria detrás de la cadena. Si creamos una nueva cadena y realizamos sustituciones en la nueva cadena, podemos asignar suficiente memoria nosotros mismos. Dado que existen dos soluciones diferentes, debemos preguntarle claramente al entrevistador y dejar que nos diga claramente sus necesidades. Supongamos que el entrevistador nos pide que reemplacemos la cadena original y nos aseguremos de que haya suficiente memoria libre después de la cadena de entrada.

La solución con complejidad temporal de O(n 2 ) no es suficiente para obtener la Oferta

Ahora consideramos cómo realizar la operación de reemplazo. La forma más intuitiva es escanear la cadena de principio a fin y reemplazarla cada vez que encuentre un carácter de espacio. Dado que estamos reemplazando 1 carácter con 3 caracteres, debemos mover todos los caracteres después del espacio hacia atrás dos bytes; de lo contrario, se sobrescribirán dos caracteres.

Por ejemplo, reemplazamos cada espacio en "Estamos contentos" con "%20" de principio a fin. Por motivos de visualización, podemos usar una tabla para representar una cadena, y cada cuadrícula en la tabla representa un carácter (como se muestra en la Figura 2.3 (a)).
Insertar descripción de la imagen aquí
Nota: (a) La cadena "Estamos contentos". (b) Reemplace el primer espacio de la cadena con '%20'. Un fondo gris indica caracteres que deben moverse. ©Reemplace el segundo espacio en la cadena con '%20'. Un fondo gris claro indica caracteres que deben moverse una vez y un fondo gris oscuro indica caracteres que deben moverse dos veces.

Reemplazamos el primer espacio y la cadena se convierte en el contenido de la Figura 2.3 (b). La cuadrícula de fondo gris en la tabla indica el área que debe moverse. Luego reemplazamos el segundo espacio y el contenido después del reemplazo se muestra en la Figura 2.3©. Al mismo tiempo, notamos que la parte "feliz" marcada con un fondo gris oscuro se ha movido dos veces.

Supongamos que la longitud de la cuerda es n. Para cada carácter de espacio, es necesario mover los siguientes caracteres O(n), por lo que la eficiencia de tiempo total para una cadena que contiene O(n) caracteres de espacio es O(n 2 ) .

Cuando le explicamos esta idea al entrevistador, este no quedará satisfecho, nos pedirá que busquemos una manera más rápida. En el análisis anterior encontramos que muchos caracteres de la matriz se han movido muchas veces, ¿podemos reducir el número de movimientos? La respuesta es sí. Cambiemos nuestra forma de pensar y pasemos del reemplazo de adelante hacia atrás al reemplazo de atrás hacia adelante.

Solución O (n) de complejidad temporal, confíe en ella para obtener la oferta

Primero podemos atravesar la cadena una vez, de modo que podamos contar el número total de espacios en la cadena y calcular la longitud total de la cadena después del reemplazo. Cada vez que se reemplaza un espacio, la longitud aumenta en 2, por lo que la longitud de la cadena después del reemplazo es igual a la longitud original más 2 veces el número de espacios. Tomemos como ejemplo la cadena anterior "Estamos felices". La longitud de la cadena "Estamos felices" es 14 (incluido el símbolo final "0') y hay dos espacios en ella, por lo que la cadena después reemplazo La longitud es 18.

Empezamos a copiar y reemplazar desde el final de la cadena. Primero prepare dos punteros, P1 y P2. P1 apunta al final de la cadena original y P2 apunta al final de la cadena reemplazada (como se muestra en la Figura 2.4 (a)). A continuación, movemos el puntero P1 hacia adelante y copiamos los caracteres señalados por él a la posición señalada por P2 uno por uno hasta encontrar el primer espacio. En este momento, la cadena contiene como se muestra en la Figura 2.4 (b): el área con fondo gris es el área donde se copiaron (movieron) los caracteres. Después de encontrar el primer espacio, mueva P1 hacia adelante 1 espacio e inserte la cadena "%20" antes de P2. Dado que la longitud de "%20" es 3, P2 también debe avanzar 3 espacios, como se muestra en la Figura 2.4©.

Luego copiamos hacia adelante hasta encontrar el segundo espacio (como se muestra en la Figura 2.4(d)). Como la última vez, movemos P1 hacia adelante 1 espacio y P2 hacia adelante 3 espacios e insertamos "%20" (como se muestra en la Figura 2.4(e)). En este momento, P1 y P2 apuntan a la misma posición, lo que indica que todos los espacios han sido reemplazados.

Del análisis anterior, podemos ver que todos los caracteres se copian (mueven) solo una vez, por lo que la eficiencia temporal de este algoritmo es O (n), que es más rápida que la primera idea.
Insertar descripción de la imagen aquí
Nota: El área sombreada de la figura indica los caracteres movidos. (a) Apunte el primer puntero al final de la cadena y apunte el segundo puntero al final de la cadena reemplazada. (b) Copie el contenido de la cadena secuencialmente hasta que el primer puntero llegue al primer espacio. ©Reemplace el primer espacio con '%20', mueva el primer puntero 1 espacio hacia adelante y el segundo puntero 3 espacios hacia adelante. (d) Copie los caracteres de la cadena en secuencia hasta encontrar un espacio. ©Reemplaza el penúltimo espacio en la cadena, mueve el primer puntero hacia adelante 1 espacio y mueve el segundo puntero hacia adelante 3 espacios.

Durante el proceso de entrevista, también podemos dibujar uno o dos diagramas esquemáticos para explicar nuestras ideas como en el análisis anterior, lo que no solo puede ayudarnos a aclarar nuestras ideas, sino también hacer más eficiente nuestra comunicación con el entrevistador. Una vez que el entrevistador confirme nuestras ideas, podemos comenzar a escribir código. Aquí está el código de referencia:

ejemplo de código

#include <cstdio>
#include <cstring>

/*length 为字符数组str的总容量,大于或等于字符串str的实际长度*/
void ReplaceBlank(char str[], int length)
{
    
    
	if (str == nullptr && length <= 0)
		return;

	/*originalLength 为字符串str的实际长度*/
	int originalLength = 0;
	int numberOfBlank = 0;
	int i = 0;
	while (str[i] != '\0')
	{
    
    
		++originalLength;

		if (str[i] == ' ')
			++numberOfBlank;

		++i;
	}

	/*newLength 为把空格替换成'%20'之后的长度*/
	int newLength = originalLength + numberOfBlank * 2;
	if (newLength > length)
		return;

	int indexOfOriginal = originalLength;
	int indexOfNew = newLength;
	while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
	{
    
    
		if (str[indexOfOriginal] == ' ')
		{
    
    
			str[indexOfNew--] = '0';
			str[indexOfNew--] = '2';
			str[indexOfNew--] = '%';
		}
		else
		{
    
    
			str[indexOfNew--] = str[indexOfOriginal];
		}

		--indexOfOriginal;
	}
}

// ====================测试代码====================
void Test(const char* testName, char str[], int length, const char expected[])
{
    
    
	if (testName != nullptr)
		printf("%s begins: ", testName);

	ReplaceBlank(str, length);

	if (expected == nullptr && str == nullptr)
		printf("passed.\n");
	else if (expected == nullptr && str != nullptr)
		printf("failed.\n");
	else if (strcmp(str, expected) == 0)
		printf("passed.\n");
	else
		printf("failed.\n");
}

// 空格在句子中间
void Test1()
{
    
    
	const int length = 100;

	char str[length] = "hello world";
	Test("Test1", str, length, "hello%20world");
}

// 空格在句子开头
void Test2()
{
    
    
	const int length = 100;

	char str[length] = " helloworld";
	Test("Test2", str, length, "%20helloworld");
}

// 空格在句子末尾
void Test3()
{
    
    
	const int length = 100;

	char str[length] = "helloworld ";
	Test("Test3", str, length, "helloworld%20");
}

// 连续有两个空格
void Test4()
{
    
    
	const int length = 100;

	char str[length] = "hello  world";
	Test("Test4", str, length, "hello%20%20world");
}

// 传入nullptr
void Test5()
{
    
    
	Test("Test5", nullptr, 0, nullptr);
}

// 传入内容为空的字符串
void Test6()
{
    
    
	const int length = 100;

	char str[length] = "";
	Test("Test6", str, length, "");
}

//传入内容为一个空格的字符串
void Test7()
{
    
    
	const int length = 100;

	char str[length] = " ";
	Test("Test7", str, length, "%20");
}

// 传入的字符串没有空格
void Test8()
{
    
    
	const int length = 100;

	char str[length] = "helloworld";
	Test("Test8", str, length, "helloworld");
}

// 传入的字符串全是空格
void Test9()
{
    
    
	const int length = 100;

	char str[length] = "   ";
	Test("Test9", str, length, "%20%20%20");
}

int main(int argc, char* argv[])
{
    
    
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	Test7();
	Test8();
	Test9();

	return 0;
}

caso de prueba

1) La cadena de entrada contiene espacios (los espacios están al principio de la cadena, los espacios están al final de la cadena, los espacios están en el medio de la cadena y hay varios espacios consecutivos en la cadena).
2) No hay espacios en la cadena de entrada.
3) Prueba de entrada especial (la cadena es un puntero NULL, la cadena es una cadena vacía, la cadena tiene solo un carácter de espacio, la cadena solo tiene varios espacios consecutivos).

Supongo que te gusta

Origin blog.csdn.net/qq_36314864/article/details/132324949
Recomendado
Clasificación