1. strlen - encontre o comprimento de uma string
1.1 Declaração e uso de strlen
strlen, se tivermos um pouco de inglês básico, não é difícil saber para que serve essa função pelo significado literal, str significa string, o significado de string, len significa comprimento, o significado de comprimento. Ou seja, strlen é uma função que encontra o comprimento de uma string . Usamos o site cplusplus para observar a declaração da função strlen e o significado de cada parâmetro.
Podemos saber que o comprimento da string exigida por strlen é o número de caracteres antes do final da string . Ou seja, assumimos que existe uma string "hello world", então o comprimento da string necessária é o número de todos os caracteres antes de '\0', que é 11. Então o comprimento desta string é retornado pelo valor de retorno , então devemos definir uma variável para receber o valor de retorno se quisermos saber qual é o comprimento da string . Então a parte do parâmetro é, obviamente, o primeiro endereço da string .
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;
}
Uma coisa a notar é que o valor de retorno de strlen é do tipo size_t , que é um inteiro sem sinal. Seu significado é que é impossível encontrar números negativos ao encontrar o comprimento, então a memória é otimizada até certo ponto (usar números inteiros com sinal desperdiçará o espaço usado para armazenar números negativos).
1.3 Implementação de simulação de strlen
Analisamos o princípio do strlen acima, então agora usamos o que aprendemos para " criar " uma função strlen própria.
#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 - cópia de string
2.1 Declaração e uso de strcpy
Entendemos sua tradução literal, str table string, ou seja, string, cpy table copy, ou seja, copy. Ou seja, a função strcpy é usada para copiar strings . Em seguida, usamos o site cplusplus para observar a declaração de strcpy e o significado de cada parâmetro.
Podemos traduzi-lo para conhecer a função de strcpy, copiar a string apontada pelo ponteiro de origem para o array apontado pelo ponteiro de destino, e o conteúdo copiado contém o terminador de string . E o array apontado pelo ponteiro de destino deve ter espaço suficiente para conter o conteúdo após a cópia.
A partir disso, sabemos que strcpy requer dois parâmetros , um é um array e o outro é uma string. E o espaço da matriz deve ser grande o suficiente. O valor de retorno é o endereço antes de a matriz retornada ser copiada . O significado disso é evitar a perda do conteúdo antes da cópia.
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 é o uso mais comum do strcpy, só precisamos lembrar de uma coisa: o conteúdo copiado contém '\0' . Ou seja, mesmo que o comprimento da string que copiei não seja tão longo quanto a string original do array, mas inclua '\0', da perspectiva da linguagem C, o conteúdo após '\0' é não contado desde o início. o conteúdo da string .
2.3 Implementação de simulação 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 - comparação de strings
3.1 Declaração e Uso de strcmp
O mesmo é verdade, podemos entender mais ou menos para que essa função é usada através da tradução literal. str table string, ou seja, string, cmp table compare, ou seja, comparação . Também observamos a declaração desta função e o significado de cada parâmetro através do site cplusplus .
Podemos conhecer o princípio desta função traduzindo-o. O princípio é: a comparação começa a partir do primeiro caractere das duas strings. Se os dois caracteres forem iguais, as duas strings compararão o próximo par de caracteres até que os dois caracteres não sejam iguais e, em seguida, compare o tamanho . Retorna um inteiro menor que 0 se o primeiro caractere for menor que o segundo, 0 se for igual e um inteiro maior que 0 se for maior .
Ambos os argumentos são strings para comparar. Para facilitar o entendimento, entendemos na forma de desenho .
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 Implementação de simulação 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 - Anexar String
4.1 Declaração e Uso de strcat
Usamos o site cplusplus para observar a declaração de strcat e o significado de cada parâmetro.
Traduza até o uso da função strcat: anexe a string apontada pelo ponteiro de origem ao array apontado pelo ponteiro de destino e há espaço suficiente (tentei anexar à string, mas falhei) e o local anexado é o ponteiro de destino aponta para '\0' da string, ou seja, copie desta posição . Observe que a posição do '\0 ' anexado é a posição do primeiro '\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 Implementação de simulação 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 - cópia de string com comprimento limitado
5.1 Declaração e uso do strncpy
A diferença entre strncpy e strcpy é que strncpy tem mais um parâmetro . Esse parâmetro é um inteiro não assinado , ou seja, você pode personalizar quantos bytes de conteúdo copiar . Isso facilita muito nosso uso e melhora a flexibilidade da linguagem 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 a saída é muito estranha, pois quando copiamos apenas três bytes de conteúdo, strncpy não adicionará '\0' no final (ou seja, copiará tanto conteúdo quanto quisermos) , o que é Como resultado, podemos ver o conteúdo do array str1 antes de copiar.
5.3 Implementação de simulação 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 - Comparação de strings com comprimento limitado
6.1 Declaração e Uso de strncmp
As funções de strncmp e strcmp são exatamente as mesmas, e o princípio é exatamente o mesmo. Ou seja, se você dominar o strcmp, poderá dominar o strncmp. strncmp tem apenas mais um parâmetro que strcmp , que é um inteiro sem sinal representando bytes. Ou seja, quantos bytes queremos comparar. Podemos observar a declaração desta função e o significado de cada parâmetro através do site 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 Implementação de simulação 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 - Anexa uma string com comprimento limitado
7.1 Declaração e uso de strncat
Da mesma forma, se você dominar o strcat, poderá dominar o strncat. strncat tem um parâmetro adicional de inteiro sem sinal cujo significado representa o número de bytes. Ou seja, podemos personalizar quantos caracteres queremos anexar ao final de outra string. Podemos observar a declaração de strncat e o significado de cada parâmetro através do site 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;
}
Se prestarmos atenção aqui, encontraremos um problema. Os últimos 6 bytes de caracteres que acrescentamos não contêm '\0' , mas quando a saída final é impressa, parece que recebe um '\0' no final da string. Então isso tem que mencionar as características de strncat, ou seja, strncat adicionará '\0' após a string a ser anexada .
7.3 Implementação de simulação 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;
}
resumo
Cobrimos uma série de funções de string de comprimento irrestrito e funções de string de comprimento restrito acima. Então, qual é a diferença entre restrito e irrestrito? Em primeiro lugar , a flexibilidade das funções de string irrestritas é relativamente baixa , porque apenas a string inteira pode ser manipulada. No entanto , a flexibilidade da função de string restrita é relativamente alta e o número de caracteres a serem manipulados pode ser personalizado. Além disso, funções de string de comprimento limitado são mais seguras do que funções de string de comprimento irrestrito . Observe que restrito é mais seguro do que irrestrito.
8. strstr - pesquisa de strings
8.1 Declaração e uso de strstr
strstr é literalmente duas strings. Então seu significado é encontrar outra string em uma das strings . Podemos observar a declaração de strstr e o significado de cada parâmetro através do site cplusplus .
Podemos conhecer alguns princípios de strstr traduzindo-o. Se a string 2 for encontrada na string 1, o primeiro endereço da string 2 na string 1 será retornado. Se a string não for encontrada, um ponteiro nulo será retornado .
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;
}
Pode-se ver que o valor de retorno é o primeiro endereço da primeira ocorrência de str2 em str1.
8.3 Implementação 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;
}
Vamos explicar a ideia em detalhes desenhando uma imagem.
9. strtok - Fatiar String
9.1 Declaração e utilidade do strtok
Para esta função, precisamos apenas entender o uso básico. Usamos o site cplusplus para observar a declaração de strtok e o significado de cada parâmetro.
Este parágrafo em inglês é muito longo, deixe-me explicar a parte principal: fornecemos dois parâmetros para strtok, um é uma string e o outro é o token a ser cortado. Se o token aparecer na string, a posição será modificada para '\0' e o endereço da string antes que o token seja retornado . Se você quiser passar parâmetros duas vezes, você só precisa passar um ponteiro 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álise de código de erro
10.1 Declaração e uso de strerror
Um ponto que precisamos popularizar é que na linguagem C, quando ocorre um erro de programa, existe uma variável global oculta errno , que é um inteiro, como 0, 1, 2, 3, .... etc. representam diferentes mensagens de erro, e o papel de strerror é traduzir este código de erro . Podemos observar a declaração de strerror e o significado de cada parâmetro através do site 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;
}