C语言字符函数和字符串函数(2)
目录
前言
一、strncpy函数
1.介绍
2.模拟实现:
二、使用步骤
二、strncat函数
1.介绍
2.模拟实现:
三、strncmp函数
1.介绍
2.模拟实现:
四、strstr函数
1.介绍
2.模拟实现:
函数 mystrstr 解析
功能:在 str1 中查找 str2,若找到返回子串起始地址,否则返回 NULL。
实现逻辑:
五、strtok 函数
介绍
总结
前言
在C语言字符函数和字符串函数(1)中,我们讲解了:
1. 字符分类函数
2. 字符转换函数
3. strlen的使用和模拟实现
4. strcpy的使用和模拟实现
5. strcat的使用和模拟实现
6. strcmp的使用和模拟实现
1~6的知识的相关内容,为上一章节知识的内容,本篇文章将讲解:
7. strncpy函数的使用
8. strncat函数的使用
9. strncmp函数的使用
10. strstr的使用和模拟实现
11. strtok函数的使用
7~11知识的相关内容,为本章节知识的内容。
一、strncpy函数
1.介绍
char * strncpy ( char * destination, const char * source, size_t num );
strncpy函数strcpy函数功能相同,字符串拷⻉,即将代码中source的字符拷贝至 destination中,但strncpy函数多出了一个参数,新增的参数含义为最多拷贝num个字符。
即:
destination :指针,指向⽬的地空间(目的字符串)。
source :指针,指向源头数据(源头字符串)。
num :从source指向的字符串中最多拷⻉的字符个数。
返回值:strcpy 函数返回的⽬标空间的起始地址。
使用例:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[] = "abcdefghi";
char* str = strncpy(arr1, arr2, 5);
printf("%s\n", arr1);
printf("%s\n", str);
return 0;
}
strncpy函数strcpy函数功能相同,但也有区别的地方:
1.strcpy 函数拷⻉到\0 为⽌,如果⽬标空间不够的话,容易出现越界⾏为。
2.strncpy 函数指定了拷⻉的⻓度,源字符串不⼀定要有'\0', 同时在设计参数的时候,就会多⼀层思考:⽬标空间的⼤⼩是否够⽤。注意:strncpy
- 结束条件:复制
n
个字符 或 遇到source 的'\0'
时停止(以先到者为准)。- 自动添加
'\0'
:否!仅当source 长度 <n
时,剩余部分用'\0'
填充至n
个字符;若 source 长度 ≥n
,则不添加'\0'。注意strncpy
手动补'\0'
的情况
。
2.模拟实现:
可用指针法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
char* mystrncpy(char* a1, char* a2,int n)
{
char* ret = a1;
while ( n-- &&*a2)
{
*a1 = *a2;
a1++, a2++;
}
while (n > 0)
{
a1++;
*a1 = '\0';
n--;
}
return ret;
}
int main()
{
char arr1[20] = { 0 };
char arr2[] = "abcdefghi";
char* str = mystrncpy(arr1, arr2, 5);
printf("%s\n", arr1);
printf("%s\n", str);
return 0;
}
运行结果一样的。
二、使用步骤
二、strncat函数
1.介绍
char * strncat ( char * destination, const char * source, size_t num );
strncat函数strcat函数功能相同,功能:字符串追加,将源头字符串中的字符,即将代码中source的字符追加至 destination结尾,但最多追加num个字符。
destination :指针,指向⽬的地空间
source :指针,指向源头数据
num :从source指向的字符串中最多追加的字符个数。
返回值strncat 函数返回的⽬标空间的起始地址
使用例:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
char* str = strncat(arr1, arr2, 5);
printf("%s\n", arr1);
printf("%s\n", str);
}
strncat函数strcat函数功能相同,但也有区别的地方:
1.strncat 多了⼀个参数,num;
2. strcat函数在追加的时候要将源字符串的所有内容,包含 \0 都追加过去,但是strncat 的num数指定了追加的⻓度,同时函数中源字符串中不⼀定要有‘\0’了,strncat函数更加灵活,也更加安全。
2.模拟实现:
可用指针法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
char* mystrncat(char* a1, char* a2,int num)
{
char* p = a1;
while (*a1)
{
a1++;
}
while (num--&&*a2)
{
*a1 = *a2;
a1++;
a2++;
}
*a1 = '\0';
return p;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
char* str = mystrncat(arr1, arr2, 5);
printf("%s\n", arr1);
printf("%s\n", str);
}
运行结果一样的。
三、strncmp函数
1.介绍
int strncmp ( const char * str1, const char * str2, size_t num );
strncmp函数strcmp函数功能相同,功能:用来比较str1 和str2 指向的字符串,从两个字符串的第⼀个字符开始⽐较,如果两个字符的ASCII码值相等,就比较下⼀个字符。直到遇到不相等的两个字符,或者字符串结束,但比较的字符对数要在num个字符以内。
str1 :指针,指向要⽐较的第⼀个字符串。
str2 :指针,指向要⽐较的第⼆个字符串。
num :最多⽐较的字符个数。
返回值:strncmp 函数返回的两个字符串比较的值。
返回值规定:
1.第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字。
2.第⼀个字符串等于第⼆个字符串,则返回0。
3.第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字。
4.如果到了num对且这num对字符均相等,则返回0,按相等来看。
使用例:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcqw";
int ret1 = strncmp(arr1, arr2, 3);
printf("%d\n", ret1);
int ret2 = strncmp(arr1, arr2, 4);
printf("%d\n", ret2);
return 0;
}
strncmp函数strcpy函数功能相同,但也有区别的地方:
关键区别
1.比较长度限制:strcmp:无长度限制,会一直比较到字符串结束(存在越界风险,若字符串未正确以'\0'结尾)。
strncmp:通过第三个参数n明确限制比较的最大字符数,更安全,可避免因字符串未结束导致的无限比较。
2.返回值逻辑:两者返回值规则相同:
若s1 < s2:返回负数(通常是ASCII差值)
若s1 == s2:返回0
若s1 > s2:返回正数(通常是ASCII差值)
但 strncmp 的“相等”可能仅指前n个字符相等,而非整个字符串相等。
2.模拟实现:
可用指针法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int mystrncmp(char* a, char* b,int num)
{
while (num&&*a == *b)
{
if (*a == '\0')
{
return 0;
}
a++;
b++;
num--;
}
if (num == 0)
{
return 0;
}
return *a - *b;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcqw";
int ret1 = mystrncmp(arr1, arr2, 3);
printf("%d\n", ret1);
int ret2 = mystrncmp(arr1, arr2, 4);
printf("%d\n", ret2);
return 0;
}
运行结果一样的。
四、strstr函数
1.介绍
char * strstr ( const char * str1, const char * str2);
1.介绍:strstr 函数,功能为查找 str2 指向的字符串在 str1 指向的字符串中第⼀次出现的位置。
2.简⽽⾔之:在⼀个字符串中查找⼦字符串。
3.strstr 的使⽤得包含 #include <string.h>头文件。
4.参数: str1 :指针,指向了被查找的字符串。
str2 :指针,指向了要查找的字符串。
5.返回值:
• 如果str1指向的字符串中存在str2指向的字符串,那么返回第⼀次出现位置的指针。
• 如果str1指向的字符串中不存在str2指向的字符串,那么返回NULL。
使用例:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "This is a simple string";
char* p;
p= strstr(str, "simple");
if (p != NULL)
printf("%s\n", p);
else
printf("查找的字符串不存在\n");
return 0;
}
2.模拟实现:
该函数的模拟实现较为复杂,需要建立三个指针,进行实现,分别为 1.指向被指向的字符串(被查找的字符串),该字符指针来代指该串、2.一个每次承接要查找的字符串的首地址,3.一个每次承接(1.)的指针的首地址。
可能有些模糊,先看代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
char* mystrstr(char* str1,char* str2)
{
char* s1 = str1;
char* s2, * s3;
while (*s1)
{
s2 = s1;
s3 = str2;
while (*s2 && *s3)
{
if ((*s2) != (*s3))
break;
s2++;
s3++;
}
if (*s3 == '\0')
return s1;
s1++;
}
return NULL;
}
int main()
{
char str[] = "This is a simple string";
char* p;
p= mystrstr(str, "simple");
if (p != NULL)
printf("%s\n", p);
else
printf("查找的字符串不存在\n");
return 0;
}
函数 mystrstr
解析
功能:在 str1
中查找 str2
,若找到返回子串起始地址,否则返回 NULL
。
实现逻辑:
-
初始化指针:
s1
指向str1
的当前比较起始位置(从首字符开始)。s2
和s3
作为临时指针,分别用于遍历str1
的子串和str2
本身。
-
外层循环:遍历
str1
的每个字符(while (*s1)
),作为子串匹配的起点。 -
内层循环:逐个字符比较
s1
起始的子串与str2
:- 若
*s2 == *s3
,则两者都后移一位(s2++
、s3++
)。 - 若不相等,跳出内层循环,
s1
后移一位(尝试下一个起始位置)。
- 若
-
匹配成功条件:当
s3
遍历到str2
的结束符'\0'
(即*s3 == '\0'
),说明str2
已完全匹配,返回此时的s1
(子串起始地址)。 -
未找到情况:若
str1
遍历结束仍未匹配,返回NULL
。
这是对应实现的讲解,运行结果一样的。
五、strtok 函数
介绍
char *strtok(char *str, const char *delim);
功能:
1.分割字符串:根据 delim 参数中指定的分隔符,将输⼊字符串 str 拆分成多个⼦字符串。
2.修改原始字符串: strtok 会直接在原始字符串中插⼊ '\0' 终⽌符,替换分隔符的位置,因 此原始字符串会被修改。
参数:
1. str :⾸次调⽤时传⼊待分割的字符串;后续调⽤传⼊NULL ,表⽰继续分割同⼀个字符串。
2. delim :包含所有可能分隔符的字符串(每个字符均视为独⽴的分隔符)。
返回值:
1.成功时返回指向当前⼦字符串的指针。
2.没有更多⼦字符串时返回NULL。
注意点:
使⽤步骤
1.⾸次调⽤:传⼊待分割字符串和分隔符。
2.后续调⽤:传⼊ NULL 和相同的分隔符,继续分割。
3.结束条件:当返回 NULL 时,表示分割完成。
通过使用例,解释一下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "192.168.6.111";
const char* sep = ".";
const char* str = NULL;
char buf[30] = { 0 };
strcpy(buf, arr);
for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s\n", str);
}
return 0;
}
strcpy(buf, arr); 是将arr的值拷贝到buf中,
for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep))
这句意为:在buf串中寻找sep的串,声明时可知,sep的串: const char* sep = ".";
- 首次调用:
strtok(buf, sep)
,传入原始字符串buf
和分隔符sep
,返回第一个子串地址。- 后续调用:
strtok(NULL, sep)
,传入NULL
表示继续处理上一次的字符串,返回下一个子串地址,直至返回NULL
(所有子串已拆分完毕)。
但使用本函数时也有些需要注意的点:
1.破坏性操作: strtok 会直接修改原始字符串,将其中的分隔符替换为 '\0' 。如果需要保留原 字符串,应先拷⻉⼀份原串。
2.连续分隔符:多个连续的分隔符会被视为单个分隔符,不会返回空字符串。
3.空指针处理:如果输⼊的str为NULL且没有前序调⽤,⾏为未定义。
总结
以上就是今天要讲的内容,本文简单介绍了:
7. strncpy函数的使用
8. strncat函数的使用
9. strncmp函数的使用
10. strstr的使用和模拟实现
11. strtok函数的使用
知识的相关内容,为本章节知识的内容,希望大家能喜欢我的文章,谢谢各位。