Funciones de cadena de uso común en lenguaje C: ¿qué hay exactamente en el archivo de encabezado <string.h>?

1. strlen - encuentra la longitud de una cadena

1.1 Declaración y uso de strlen

strlen, si tenemos algo de inglés básico, no es difícil saber para qué se usa esta función por el significado literal, str significa cadena, el significado de cadena, len significa longitud, el significado de longitud. Es decir, strlen es una función que encuentra la longitud de una cadena . Usamos el sitio web de cplusplus para observar la declaración de función de strlen y el significado de cada parámetro.

Podemos saber que la longitud de la cadena requerida por strlen es el número de caracteres antes del final de la cadena . Es decir, asumimos que hay una cadena "hola mundo", entonces la longitud requerida de la cadena es el número de todos los caracteres antes de '\0', que es 11. Luego, la longitud de esta cadena es devuelta por el valor de retorno , por lo que debemos definir una variable para recibir el valor de retorno si queremos saber cuál es la longitud de la cadena . Entonces, la parte del parámetro es, por supuesto, la primera dirección de la cadena .

1.2 Uso de strlen

#include <stdio.h>
#include <string.h>

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

	int len1 = strlen(str1);//数组名表首元素地址
	int len2 = strlen(str2);//str2 指针变量存放的也是首元素地址

	printf("%d\n", len1);
	printf("%d\n", len2);

	//这种写法也可以输出长度
	//printf("%d\n", strlen(str1));
	//printf("%d\n", strlen(str2));

	return 0;
}

Una cosa a tener en cuenta es que el valor de retorno de strlen es del tipo size_t , que es un número entero sin signo. Su significado es que es imposible encontrar números negativos al encontrar la longitud, por lo que la memoria está optimizada hasta cierto punto (el uso de números enteros con signo desperdiciará el espacio utilizado para almacenar números negativos).

 1.3 Implementación de simulación de strlen

Hemos analizado el principio de strlen arriba, así que ahora usamos lo que hemos aprendido para " crear " una función de strlen propia.

#include <stdio.h>
#include <assert.h>
unsigned int my_strlen(const char* str)//我们不改变字符串的内容,所以用 const 来进行修饰
{
	assert(str);//避免是一个空指针
	unsigned int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char str1[] = "hello world";
	char* str2 = "hello world";

	int ret1 = my_strlen(str1);
	int ret2 = my_strlen(str2);

	printf("%d\n", ret1);
	printf("%d\n", ret2);

	return 0;
}

2. strcpy - copia de cadena

2.1 Declaración y uso de strcpy

Entendemos su traducción literal, cadena de tabla str, es decir, cadena, copia de tabla cpy, es decir, copia. Es decir, la función strcpy se usa para copiar cadenas . Luego usamos el sitio web de cplusplus para observar la declaración de strcpy y el significado de cada parámetro.

 

Podemos traducirlo para conocer la función de strcpy, copiar la cadena a la que apunta el puntero de origen a la matriz a la que apunta el puntero de destino, y el contenido copiado contiene el terminador de cadena . Y la matriz a la que apunta el puntero de destino debe tener suficiente espacio para contener el contenido después de la copia. 

De esto sabemos que strcpy requiere dos parámetros , uno es una matriz y el otro es una cadena. Y el espacio de la matriz debe ser lo suficientemente grande. El valor devuelto es la dirección antes de que se copiara la matriz devuelta . El significado de esto es evitar la pérdida del contenido antes de la copia.

2.2 Uso de strcpy

#include <stdio.h>
#include <string.h>

int main()
{
	char dest[20] = "row your boat";
	char src[] = "hello world";
	strcpy(dest, src);
	printf("%s\n", dest);
	return 0;
}

Este es el uso más común de strcpy, solo debemos recordar una cosa: el contenido copiado contiene '\0' . Es decir, incluso si la longitud de la cadena que copié no es tan larga como la cadena original de la matriz, pero incluyo '\0', desde la perspectiva del lenguaje C, el contenido después de '\0' es no se cuenta desde el principio el contenido de la cadena .

2.3 Implementación de simulación de strcpy

#include <stdio.h>
#include <assert.h>

char* my_strcpy(char* dest, const char* src)//dest 指向的数组空间是要被改变的,但是 src 指向的字符串不需要改变
{
	assert(dest && src);//防止其中某个是无效指针
	char* ret = dest;
	while (*dest++ = *src++)
		;	//注意 while 循环执行了空语句

	return ret;
}
int main()
{
	char dest[30] = "gently down the stream";
	char src[] = "life is but a dream";

	my_strcpy(dest, src);
	printf("%s\n", dest);
	return 0;
}

3. strcmp - comparación de cadenas

3.1 Declaración y uso de strcmp

Lo mismo es cierto, podemos entender aproximadamente para qué se usa esta función a través de la traducción literal. cadena de tabla str, es decir, cadena, comparación de tabla cmp, es decir, comparación . También observamos la declaración de esta función y el significado de cada parámetro a través del sitio web de cplusplus .

Podemos conocer el principio de esta función traduciéndola. El principio es: la comparación comienza desde el primer carácter de las dos cadenas. Si los dos caracteres son iguales, entonces las dos cadenas compararán el siguiente par de caracteres hasta que los dos caracteres no sean iguales, y luego compararán el tamaño . Devuelve un entero menor que 0 si el primer carácter es menor que el segundo, 0 si es igual y un entero mayor que 0 si es mayor .

Ambos argumentos son cadenas para comparar. Para facilitar la comprensión, lo entendemos en forma de dibujo .

 

 

 3.2 Uso de strcmp

#include <stdio.h>
#include <string.h>

int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = strcmp(str1, str2);
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

 3.3 Implementación de simulación de strcmp

#include <stdio.h>
#include <assert.h>

int my_strcmp(const char* str1, const char* str2)//两个字符串的内容都不需要修改,用 const 修饰
{
	assert(str1 && str2);//防止是无效指针

	while (*str1 == *str2)//如果相等则进入循环
	{
		if (*str1 == '\0')//*str1 == '\0' 了并且进入循环了,说明两个字符串比较完成了,没有不相等的字符
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;//两个字符的差作为返回值
}
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = my_strcmp(str1, str2);
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

4. strcat - Agregar cadena

4.1 Declaración y uso de strcat

 Usamos el sitio web de cplusplus para observar la declaración de strcat y el significado de cada parámetro.

Tradúzcalo hasta el uso de la función strcat: agregue la cadena a la que apunta el puntero de origen a la matriz a la que apunta el puntero de destino y hay suficiente espacio (traté de agregar a la cadena, pero fallé), y la ubicación adjunta es el puntero de destino apunta a '\0' de la cadena, es decir, copia desde esta posición . Tenga en cuenta que la posición del '\0 ' adjunto es la posición del primer '\0' .

4.2 Uso de strcat 

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[50] = "row row row your boat,";
	char* str2 = "gently down the stream";
	strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

4.3 Implementación de simulación de strcat 

#include <stdio.h>
#include <assert.h>

char* my_strcat(char* dest, const char* src)//src 指向的字符串是不改变内容的,所以用 const 修饰
{
	assert(dest && src);//确保两个指针有效
	char* ret = dest;
	while (*dest)
		dest++;//先找到 dest 指向的数组的第一个 '\0' 的位置
	while (*dest++ = *src++)//拷贝
		;
	return ret;
}
int main()
{
	char str1[50] = "row row row your boat,";
	char* str2 = "gently down the stream";
	my_strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

5. strncpy - copia de cadena de longitud limitada

5.1 Declaración y uso de strncpy

La diferencia entre strncpy y strcpy es que strncpy tiene un parámetro más . Este parámetro es un entero sin signo , es decir, puedes personalizar cuántos bytes de contenido copiar . Esto facilita mucho nuestro uso y mejora la flexibilidad del lenguaje C.

5.2 Uso de strncpy

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[20] = "row your boat";
	char str2[] = "hello world";
	strncpy(str1, str2, 3);//我们从 str2 中拷贝三个字节的内容到 str1 去
	printf("%s\n", str1);
	return 0;
}

 

 Podemos ver que la salida es muy extraña, porque cuando solo copiamos tres bytes de contenido, strncpy no agregará '\0' al final (es decir, copiará todo el contenido que queramos) , lo cual es como resultado, podemos ver el contenido de la matriz str1 antes de copiar.

5.3 Implementación de simulación de strncpy

#include <stdio.h>
#include <assert.h>

char* my_strncpy(char* dest, const char* src, unsigned int num)
{
	assert(dest && src);//确保两个指针有效
	char* ret = dest;

	while (num--)//拷贝几个字节
	{
		*dest = *src;
		dest++;
		src++;
	}

	return ret;
}
int main()
{
	char str1[20] = "row your boat";
	char str2[] = "hello world";
	my_strncpy(str1, str2, 3);
	printf("%s\n", str1);
	return 0;
}

6. strncmp - Comparación de cadenas de longitud limitada

6.1 Declaración y uso de strncmp

Las funciones de strncmp y strcmp son exactamente las mismas, y el principio es exactamente el mismo. Es decir, si dominas strcmp, puedes dominar strncmp. strncmp solo tiene un parámetro más que strcmp , que es un número entero sin signo que representa bytes. Es decir, cuántos bytes queremos comparar. Podemos observar la declaración de esta función y el significado de cada parámetro a través del sitio web de cplusplus .

6.2 Uso de strncmp

#include <stdio.h>
#include <string.h>

int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret=strncmp(str1, str2,3);//我们只想比较字符串的前三个字节
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

 

6.3 Implementación de simulación de strncmp

#include <stdio.h>
#include <assert.h>

int my_strncmp(const char* str1, const char* str2, unsigned int num)//两个字符串的内容都不需要变,所以用 const 修饰
{
	assert(str1 && str2);
	while (num-- && *str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = my_strncmp(str1, str2, 3);//我们只想比较字符串的前三个字节
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

7. strncat - Agrega una cadena con longitud limitada

7.1 Declaración y uso de strncat

De la misma manera, si domina strcat, puede dominar strncat. strncat tiene un parámetro adicional de entero sin signo cuyo significado representa el número de bytes. Es decir, podemos personalizar cuántos caracteres queremos agregar al final de otra cadena. Podemos observar la declaración de strncat y el significado de cada parámetro a través del sitio web de cplusplus .

 

7.2 Uso de strncat

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[50] = "row row row your boat,";
	char str2[] = "gently down the stream";
	strncat(str1, str2, 6);//我们只想追加 6 个字节的字符到 str1 中
	printf("%s\n", str1);
	return 0;
}

 Si prestamos atención aquí, encontraremos un problema. Los últimos 6 bytes de caracteres que agregamos no contienen '\0' , pero cuando se imprime el resultado final, parece que se le da un '\0' al final de la cadena. Entonces esto tiene que mencionar las características de strncat, es decir, strncat agregará '\0' después de la cadena que se agregará .

 7.3 Implementación de simulación de strncat

#include <stdio.h>
#include <assert.h>

char* my_strncat(char* dest, const char* src, unsigned int num)//str2 中的字符串不需要被修改,所以用 const 修饰
{
	assert(dest && src);//确保两个指针是有效指针
	char* ret = dest;//记录返回值

	while (*dest)//先找到 dest 指向的 '\0' 的位置
		dest++;
	while (num-- && (*dest++ = *src++) )//拷贝限制的字节数
		;
	*dest = '\0';

	return ret;

}
int main()
{
	char str1[50] = "row row row your boat,";
	char str2[] = "gently down the stream";
	my_strncat(str1, str2, 8);
	printf("%s\n", str1);
	return 0;
}

resumen

Cubrimos una serie de funciones de cadena de longitud no restringida y funciones de cadena de longitud restringida arriba. Entonces, ¿cuál es la diferencia entre restringido y no restringido? En primer lugar , la flexibilidad de las funciones de cadena sin restricciones es relativamente baja , porque solo se puede manipular la cadena completa. Sin embargo , la flexibilidad de la función de cadena restringida es relativamente alta y la cantidad de caracteres que se manipularán se puede personalizar. Además, las funciones de cadena de longitud limitada son más seguras que las funciones de cadena de longitud no restringida . Tenga en cuenta que restringido es más seguro que no restringido.

8. strstr - búsqueda de cadenas

8.1 Declaración y uso de strstr

strstr es literalmente dos cadenas. Entonces su significado es encontrar otra cadena en una de las cadenas . Podemos observar la declaración de strstr y el significado de cada parámetro a través del sitio web de cplusplus .

Podemos conocer algunos principios de strstr traduciéndolo. Si la cadena 2 se encuentra en la cadena 1, se devuelve la primera dirección de la cadena 2 en la cadena 1. Si no se encuentra la cadena, se devuelve un puntero nulo .

8.2 Uso de strstr

#include <stdio.h>
#include <string.h>

int main()
{
	char* str1 = "row row row your boat,gently down the stream";
	char* str2 = "row your boat";
	char* ret = strstr(str1, str2);//在 str1 中查找 str2 
	printf("%s\n", ret);
	return 0;
}

Se puede ver que el valor devuelto es la primera dirección de la  primera aparición de str2 en str1.

8.3 Implementación simulada de strstr

#include <stdio.h>
#include <assert.h>

char* my_strstr(const char* str1, const char* str2)//不需要改变其内容,用 const 修饰
{
	assert(str1 && str2);//避免是无效指针
	const char* s1 = str1;
	const char* s2 = str2;
	const char* cp = str1;//这个指针变量是至关重要的
	while (*cp)
	{
		s1 = cp;
		s2 = str2;

		//在 str1 中查找 str2 的核心循环
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')//查找完成
			return (char*)cp;

		cp++;
	}
	return NULL;
}
int main()
{
	char* str1 = "row row row your boat,gently down the stream";
	char* str2 = "row your boat";
	char* ret = my_strstr(str1, str2);
	printf("%s\n", ret);
	return 0;
}

Expliquemos la idea en detalle  haciendo un dibujo .

 

 

 

 9. strtok - Cortar cuerdas

9.1 Declaración y utilidad de strtok

Para esta función, solo necesitamos entender el uso básico. Usamos el sitio web de cplusplus para observar la declaración de strtok y el significado de cada parámetro.

Este párrafo en inglés es demasiado largo, permítanme explicar la parte central: proporcionamos dos parámetros para strtok, uno es una cadena y el otro es el token que se cortará. Si el token aparece en la cadena, la posición se modificará a '\0' y se devolverá la dirección de la cadena antes del token . Si desea pasar parámetros dos veces, solo necesita pasar un puntero nulo.

9.2 Uso de strtok

#include <stdio.h>
#include <string.h>

int main()
{
	char* str1 = "row@row~row%your^boat,gently@down~the^stream";
	char* str2 = "@~%^";

	//将 str1 拷贝至 tmp 数组,这样不会丢失 str1 的原始数据
	char tmp[50] = { 0 };
	strcpy(tmp, str1);

	char* ret = NULL;
	for (ret = strtok(tmp, str2); ret != NULL; ret = strtok(NULL, str2))
	{
		printf("%s ", ret);
	}
	return 0;
}

10. strerror - análisis de código de error

10.1 Declaración y uso de strerror

Un punto que necesitamos popularizar es que en el lenguaje C, cuando ocurre un error de programa, hay una variable global oculta errno , que es un número entero, como 0, 1, 2, 3, .... etc. Todos ellos representan diferentes mensajes de error, y la función de strerror es traducir este código de error . Podemos observar la declaración de strerror y el significado de cada parámetro  a través del sitio web de cplusplus .

10.2 Uso de strerror

#include <stdio.h>
#include <string.h>

int main()
{
	FILE* p;
	p = fopen("test.txt", "r");//在我们的工程目录下并没有 test.txt 这个文件
	if (p == NULL)//那么打不开 p 就是一个空指针
	{
		printf("%s\n", strerror(errno));//这里就会解释为什么是空指针的原因
	}
	return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_59913110/article/details/125657140
Recomendado
Clasificación