Lenguaje C de alto nivel | Funciones de caracteres y funciones de cadenas: implementación analógica de funciones

El procesamiento de caracteres y cadenas en lenguaje C es muy frecuente, pero el lenguaje C en sí mismo no tiene un tipo de cadena, y las cadenas generalmente se colocan en cadenas constantes o matrices de caracteres . Las constantes de cadena se aplican a las funciones de cadena que no las modifican

1. Encuentra la longitud de la cuerda

estrellándose
size_t significa que la función strlen devuelve un entero sin signo, str apunta a una cadena y recibe la dirección de la cadena

  • La cadena ha terminado en '\0' y la función strlen devuelve el número de caracteres que aparecen antes de '\0' en la cadena (excluyendo '\0')
  • La cadena a la que apunta el parámetro debe terminar con '\0'
  • Tenga en cuenta que el valor de retorno de la función es size_t, que no está firmado (propenso a errores)

1.1 Uso de strlen

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if ((int)strlen(str2) - (int)strlen(str1) > 0)
	{
    
    
		printf("str2>str1\n");
	}
	else
	{
    
    
		printf("str1>str2\n");
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

Nota: Cuando se usa strlen para comparar el tamaño de dos cadenas, no se puede usar directamente para restar, porque strlen devuelve un número entero sin signo. Para bits binarios, el bit más alto es el bit de signo. Cuando es un bit sin signo, el bit más alto también se utilizará para el cálculo, que será un número grande, por lo que se puede convertir en tipo int durante el cálculo, o compararlos directamente (strlen(str2)>strlen(str1)), para que no se produzca ningún cálculo

1.2 Implementación de simulación de la función strlen

#include <stdio.h>
int my_strlen(const char* str1)
{
    
    
	int count = 0;
	while ( * str1!='\0')
	{
    
    
		str1++;
		count++;
	}
	return count;
}
int main()
{
    
    
	char* str1 = "abcdef";
	int count = my_strlen(str1);
	printf("%d", count);
	return 0;
}

Resultado de la ejecución:
inserte la descripción de la imagen aquí
por supuesto, también se puede simular mediante el método recursivo, puntero menos puntero

2. Funciones de cadena con longitud ilimitada

2.1 Uso de strcpy

inserte la descripción de la imagen aquí
Copie la cadena de origen a la que apunta el origen en la cadena de destino a la que apunta el destino y devuelva un puntero de tipo char*

  • La cadena de origen debe terminar con '\0'.
  • Copiará el '\0' en la cadena de origen al espacio de destino
  • el espacio de destino debe ser mutable
#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char* str1 = "abcdef";
	char str2[20] = {
    
     0 };
	strcpy(str2, str1);
	printf("str2=%s", str2);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

2.1.1 Implementación de simulación de la función strcpy

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* str2, const char* str1)
{
    
    
	char* ret = str2;
	assert(str1 && str2);
	while (*str2++ = *str1++)
	{
    
    
		;
	}
	return ret;
}
int main()
{
    
    
	char* str1 = "abcdef";
	char str2[20] = {
    
     0 };
	char* ret = my_strcpy(str2, str1);
	printf("str2=%s", ret);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

afirmar se usa para afirmar si es un puntero nulo, si lo es, se informará un error, de lo contrario, continúe la ejecución

2.2 Uso de strcat

inserte la descripción de la imagen aquí
Conecte la cadena de origen a la que apunta el origen al final de la cadena a la que apunta el destino, y el primer carácter de la cadena de origen se escribe en la posición final del carácter nulo de la cadena de destinoinserte la descripción de la imagen aquí

  • Tanto la cadena de origen como la cadena de destino deben terminar en '\0'
  • El espacio de destino debe ser lo suficientemente grande para albergar el contenido de la cadena de origen.
  • el espacio de destino debe ser modificable
#include <stdio.h>
#include <string.h>
int main()
{
    
    
    char str1[20] = "hello";
	char* str2 = "bit";
	strcat(str1, str2);
	printf("str1=%s", str1);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

2.2.1 Implementación de simulación de la función strcat

#include <stdio.h>
#include <assert.h>
char* my_strcat(char* str1, const char* str2)
{
    
    
	char* ret = str1;
	assert(str1 && str2);
	//寻找到'\0'的位置
	while (*str1)
	{
    
    
		str1++;
	}
	//开始拷贝
	while (*str1++ = *str2++)
	{
    
    
		;
	}
	return ret;
}
int main()
{
    
    
    char str1[20] = "hello";
	char* str2 = "bit";
	char* ret = my_strcat(str1, str2);
	printf("str1=%s", str1);
	return 0;
}

Resultado en ejecución:
inserte la descripción de la imagen aquí
entonces la pregunta es, ¿se puede agregar la cadena a sí misma? Usando el código simulado para analizar,
inserte la descripción de la imagen aquí
primero, el origen y el objetivo apuntan a la misma ubicación, y el objetivo encuentra la posición del carácter nulo de terminación, y luego lo copia, copiando h por primera vez, y se detiene hasta el '\ 0' se copia, pero la primera copia En este momento, el '\0' se sobrescribirá y el '\0' no se encontrará en las copias posteriores, y el bucle sin fin continuará. Entonces, la respuesta es que es mejor no agregar cadenas a usted mismo.

2.3 Uso de strcmp

inserte la descripción de la imagen aquí
Compare los caracteres en la misma posición, si son iguales, compare el siguiente par de caracteres, si no son iguales, determine cuál es más grande y devuelva el número correspondiente, el tipo de retorno es tipo int
inserte la descripción de la imagen aquí

  • Si la primera cadena es mayor que la segunda cadena, devuelve un número mayor que 0
  • Si la primera cadena es igual a la segunda cadena, devuelve 0
  • La primera cadena es menor que la segunda cadena, devuelve un número menor que 0
#include <stdio.h>
#include <string.h>
int main()
{
    
    
    char* str1= "hello";
	char* str2 = "bit";
	int ret = strcmp(str1, str2);
	printf("ret=%d", ret);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

2.3.1 Implementación de simulación de la función strcmp

#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
    
    
	assert(str1 && str2);
	//当比较到'\0'或者不相等时就可以停下来
	while (str1 && str2 && *str1++ == *str2++)
	{
    
    
		;
	}
	int ret=str1 - str2;
	if (ret > 0)
	{
    
    
		return 1;
	}
	else if (ret < 0)
	{
    
    
		return -1;
	}
	else
	{
    
    
		return 0;
	}
}
int main()
{
    
    
    char* str1= "hello";
	char* str2 = "bit";
	int ret = my_strcmp(str1, str2);	
	printf("ret=%d", ret);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

3. Introducción a las funciones de cadena de longitud limitada

3.1strncpy

inserte la descripción de la imagen aquí

  • Copia números de caracteres de la cadena de origen al espacio de destino.
  • Si la longitud de la cadena de origen es menor que num, después de copiar la cadena de origen, se agregará 0 después del destino, hasta que num.
#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char str1[20] = {
    
     0 };
	char* str2 = "bit";
	strncpy(str1, str2,5);	
	printf("str1=%s", str1);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

3.2strncat

inserte la descripción de la imagen aquí

  • Agrega los primeros números de caracteres de la cadena de origen al final de la cadena de destino, con un carácter nulo de terminación al final.
  • Si la longitud de la cadena de origen es inferior a num, solo se copia hasta el carácter nulo final.
#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char str1[20] = "hello";
	char* str2 = "bit";
	strncat(str1, str2,5);	
	printf("str1=%s", str1);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

3.3strncmp

inserte la descripción de la imagen aquí

Esta función comienza comparando el primer carácter de cada cadena y, si son iguales, continúa comparando los siguientes pares de caracteres hasta que se encuentra un carácter diferente, se encuentra un carácter nulo de terminación o ambas cadenas coinciden con números de caracteres. .

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char str[][5] = {
    
     "R2D2", "C3PO","R2A6" };
	int n;
	puts("Looking for R2 astromech droids...");
	for (n = 0; n < 3; n++)
	{
    
    
		if (strncmp(str[n], "R2xx", 2) == 0)
		{
    
    
			printf("found %s\n", str[n]);
		}
		
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

Cuatro, búsqueda de cadenas

4.1 Uso de strstr

inserte la descripción de la imagen aquí

Devuelve un puntero a la primera aparición de str2 en str1, o un puntero nulo si str2 no está en str1. Como dice el refrán, la función strstr() se usa para encontrar si una cadena contiene otra cadena y devolver la posición de la primera coincidencia.

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char str[] = "This is a simple string";
	char* pch;
	pch = strstr(str, "simple");
	strncpy(pch, "sample", 6);
	puts(str);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

4.1.1 Simulación de la función strstr

#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
    
    
	assert(str1 && str2);//断言str1和str2是否为空指针
	char* cp = (char*)str1;
	char* sstr1 ;
	char* sstr2 ;
	//*str2为'\0'返回str1的地址
	if (!*str2)
		return (char*)str1;
	while(*cp)
	{
    
    
		int count = 0;
		sstr1 = cp;
		sstr2 = (char*)str2;
		while (sstr1 && sstr2 && *sstr1++ == *sstr2++)
		{
    
    
			;
		}
		if (!*sstr2)
			return cp;
		cp++;
	}
	return NULL;
}
int main()
{
    
    
	char str[] = "This is a simple string";
	char* pch = my_strstr(str, "simple");	
	puts(pch);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

4.2 carrera

inserte la descripción de la imagen aquí

  • El parámetro sep es una cadena que define el conjunto de caracteres para el separador
  • El primer parámetro especifica una cadena que contiene cero o más tokens separados por uno o más delimitadores en la cadena de separación.
  • La función strtok encuentra la siguiente marca en str, la termina con '\0' y devuelve un puntero a esta marca. (Nota: la función strtok cambiará la cadena que se está manipulando, por lo que las cadenas divididas con la función strtok generalmente son contenido copiado temporalmente y se pueden modificar).
  • El primer parámetro de la función strtok no es NULL, la función encontrará la primera marca en str y la función strtok guardará su posición en la cadena.
  • Si un parámetro de la función strtok es NULL, la función comenzará en la posición guardada en la misma cadena y buscará el siguiente token.
  • Si no existen más tokens en la cadena, se devuelve un puntero NULL.
#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char str[] = "[email protected]#566&520";
	char sep[] = "@.# & ";//分隔符,strtok找到str中下一个标记就是分隔符,找到之后会将分隔符置为'\0',所以最好拷贝一下内容
	//返回指向该标记的指针,同时返回分隔符前面字段的第一个字符的地址
	char arr[30];
	strcpy(arr, str);
	char* p = NULL;
	//当第一个参数不为NULL时,找到第一个标记,strtok会保存该标记的位置
	//当第一个参数为NULL时,函数将在同一个字符串中被保存的位置开始查找,直到下一个标记
	//如果字符串没有标记了,则返回空指针
	for (p = strtok(arr, sep); p != NULL; p = strtok(NULL, sep))
	{
    
    
		printf("%s\n", p);
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

5. Informe de mensajes de error

error 5.1

inserte la descripción de la imagen aquí

  • El código de error se almacena en errnum, se interpreta el valor de errnum y se genera una cadena que describe la condición de error, al igual que una función de biblioteca establece errno.
  • Esta función devuelve un puntero a una cadena asignada estáticamente que el programa no debe modificar. Otras llamadas a esta función pueden sobrescribir su contenido (no requerido por una implementación de biblioteca particular para evitar carreras de datos).
  • La cadena de error producida por strerror puede variar entre las implementaciones del sistema y de la biblioteca.
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    
    
	FILE* pFile;
	pFile = fopen("test.txt", "r");
	if (pFile == NULL)
	{
    
    
		printf("Error opening file test.txt:%s\n", strerror(errno));
		//也可以用perror
		perror(pFile);
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

Seis, operación de caracteres

inserte la descripción de la imagen aquí
Conversión de personajes:

int tolower(int c);//de mayúsculas a minúsculas
int toupper(int c);//de minúsculas a mayúsculas

#include <stdio.h>
#include <ctype.h>
int main()
{
    
    
	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
    
    
		c = str[i];
		if (isupper(c))//是大写返回真
			c=tolower(c);//转小写
		putchar(c);
		i++;
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

Siete, función de operación de memoria

7.1 Uso de memcpy

inserte la descripción de la imagen aquí

  • La función memcpy copia números bytes de datos hacia atrás desde la ubicación de origen a la ubicación de memoria de destino. Debido a que el tipo de devolución del destino y la fuente es nulo*, puede recibir una copia de cualquier tipo de datos.
  • Esta función no se detiene cuando encuentra '\0'.
  • Si el origen y el destino se superponen de algún modo, el resultado de la copia no está definido.
#include <stdio.h>
#include <string.h>
struct {
    
    
	char name[40];
	int age;
}person;
int main()
{
    
    
	char myname[] = "Pierre de Fermat";
	memcpy(person.name, myname, strlen(myname) + 1);
	printf("%s\n", person.name);
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

7.1.1 Simulación de la función memcpy

#include <stdio.h>
#include <assert.h>
void* my_memcopy(void* str2, const void* str1, size_t num)
{
    
    
	void* ret = str2;
	assert(str2 && str1);
	while (num--)
	{
    
    
		//完成每一对字节的交换
		*(char*)str2 = *(char*)str1;
		str2 = (char*)str2 + 1;
		str1 = (char*)str1 + 1;
	}
	return ret;
}
int main()
{
    
    
	int str1[20] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	int str2[20] = {
    
     0 };
	int* pc = (int*)my_memcopy(str2, str1, 40);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", pc[i]);
	}
	return 0;
}

7.1.2 Superposición de origen y destino de memcpy

#include <stdio.h>
#include <assert.h>
void* my_memcopy(void* str2, const void* str1, size_t num)
{
    
    
	void* ret = str1;
	assert(str2 && str1);
	while (num--)
	{
    
    
		//完成每一对字节的交换
		*(char*)str2 = *(char*)str1;
		str2 = (char*)str2 + 1;
		str1 = (char*)str1 + 1;
	}
	return ret;
}
int main()
{
    
    
	int str1[20] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//int str2[20] = { 0 };
	int* pc = (int*)my_memcopy(str1+2, str1, 20);//将12345复制到34567这个位置
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", pc[i]);
	}
	return 0;
}

El resultado esperado es 12123458910, pero lo es:
inserte la descripción de la imagen aquí
esto se debe a que:
inserte la descripción de la imagen aquí
3 ha sido cubierto por 1, y cuando 3 se asigna a 5, también es 1, y lo mismo ocurre con 4. Por lo tanto, es mejor que la función memcpy no tenga superposiciones, es decir, memcpy solo necesita implementar copias que no se superpongan, pero las copias superpuestas se pueden implementar en VS, debido a la diferencia en los compiladores.

7.2 Uso de memmove

inserte la descripción de la imagen aquí

  • La diferencia con memcpy es que el bloque de memoria de origen y el bloque de memoria de destino procesados ​​por la función memmove pueden superponerse.
  • Si el espacio de origen y el espacio de destino se superponen, debe usar la función memmove para solucionarlo.
#include <stdio.h>
#include <string.h>
int main()
{
    
    
	int arr[20] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	return 0;
}

Resultado de la ejecución:
inserte la descripción de la imagen aquí
se puede ver a partir del resultado que memmove puede realizar la superposición, entonces, ¿cómo simular y realizar esta función?

7.2.1 Simulación de la función memmove

analizar:
inserte la descripción de la imagen aquí

#include <stdio.h>
#include <assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
    
    
	assert(dest && src);
	if (src < dest)
	{
    
    
		void* ret = src;
		//从后向前开始拷贝
		src = (char*)src + num-1;
		dest = (char*)dest + num-1;
		while (num--)
		{
    
    
			*(char*)dest = *(char*)src;
			src = (char*)src - 1;
			dest = (char*)dest - 1;
		}
		return ret;
	}
	else
	{
    
    
		void* ret = dest;
		while (num--)
		{
    
    
		//从前向后拷贝
			*(char*)dest = *(char*)src;
			src = (char*)src + 1;
			dest = (char*)dest + 1;
		}
		return ret;
	}
}
int main()
{
    
    
	int arr1[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = {
    
     0 };
	int* pc=(int*)my_memmove(arr1+2 , arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", pc[i]);
	}
	return 0;
}

resultado de la operación:
inserte la descripción de la imagen aquí

7.3memcmp

inserte la descripción de la imagen aquí

  • Compara los primeros num bytes del bloque de memoria al que apunta el puntero ptr1 con los primeros num bytes del bloque de memoria al que apunta el puntero ptr2 y devuelve 0 si ambos coinciden o un valor que indica cuál es mayor si no coinciden.
  • Tenga en cuenta que, a diferencia de strcmp, esta función no deja de comparar después de encontrar un carácter nulo.
#include <stdio.h>
int main()
{
    
    
	char* str1 = "alfjlkfafj";
	char* str2 = "alffljaoiogi";
	int n =memcmp(str1, str2, 8);
	if (n > 0)
		printf("str1>str2\n");
	else if (n < 0)
		printf("str2<str1\n");
	else
		printf("str1=str2\n");
	return 0;
}

Resultado actual:
inserte la descripción de la imagen aquí
fin~

Supongo que te gusta

Origin blog.csdn.net/weixin_68201503/article/details/131720009
Recomendado
Clasificación