字符串处理函数详细文章:
文章目录
1.10. atoi/atol/atof (字符串转数值 )
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数。
一. 字符串处理函数
1.1. strlen(求字符串长度)
参考文档:strlen - C++ Reference (cplusplus.com)
// 头文件<string.h>
size_t strlen(const char *s);
// s指 需要测量字符串的首元素地址
// 函数功能:
// 测字符指针 s 指向的字符串中字符的个数, 不包括’\0’
// 返回值:
// 字符串中字符个数
-
字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
-
参数指向的字符串必须要以 '\0' 结束。
-
注意函数的返回值为size_t,是无符号的( 易错 )。
-
学会strlen函数的模拟实现。
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
// 创建临时字符串:
// 该字符串在内存存放的是:a b c d e f g \0
char arr[] = { "abcdefg" };
// 调用库函数strlen.
size_t lenght = strlen(arr);
// 打印结果:
printf("%zu\n", lenght);
return 0;
}
1.2. strcpy (字符串拷贝)
参考文档:strcpy - C++ Reference (cplusplus.com)
// 头文件<string.h>
char *strcpy(char *dest, const char *src);
// 函数的说明:
// 拷贝 src 指向的字符串到 dest 指针指向的内存中, ’\0’也会拷贝
// 函数的返回值:
// 目的内存的地址
// 注意: 在使用此函数的时候, 必须保证 dest 指向的内存空间足够大, 否则会出现内存污染。
char *strncpy(char *dest, const char *src, size_t n);
// 函数的说明:
// 将 src 指向的字符串前 n 个字节, 拷贝到 dest 指向的内存中
// 返回值:
// 目的内存的首地址
// 注意:
// strncpy 不拷贝 ‘\0’
// 如果 n 大于 src 指向的字符串中的字符个数, 则在 dest 后面填充 n-strlen(src)个 ’\0’
// dest:目的空间地址
// src:原字符串的首元素地址
-
源字符串必须以 '\0' 结束。
-
会将源字符串中的 '\0' 拷贝到目标空间。
-
目标空间必须足够大,以确保能存放源字符串。
-
目标空间必须可变。
-
学会模拟实现 。
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
// 该字符串在内存存放的是:a b c d e f g \0
// 创建临时字符串:
char sourceArr[] = { "abcdefg" };
char destinationArr[20];
// 使用strcpy();
strcpy(destinationArr, sourceArr);
printf("sourceArr:= %s\n", destinationArr);
return 0;
}
1.3. strncpy (字符串拷贝带长度)
char * strncpy ( char * destination, const char * source, size_t num );
-
拷贝num个字符从源字符串到目标空间。
-
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
1.4. strcat (字符串追加)
参考文档:strcat - C++ Reference (cplusplus.com)
// 头文件<string.h>
char *strcat(char *dest, const char *src);
// 函数功能:
// strcat 函数追加 src 字符串到 dest 指向的字符串的后面。 追加的时候会追加’\0’
// 注意:
// 保证 dest 指向的内存空间足够大。
char *strncat(char *dest, const char *src, size_t n);
// 追加 src 指向的字符串的前 n 个字符, 到 dest 指向的字符串的后面。
// 注意如果 n 大于 src 的字符个数, 则只讲 src 字符串追加到 dest 指向的字符串的后面
// 追加的时候会追加’\0’
-
源字符串必须以 '\0' 结束。
-
目标空间必须有足够的大,能容纳
-
目标空间必须可修改。
-
字符串自己给自己追加,如何?
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
// 该字符串在内存存放的是:a b c d e f g \0
// 创建临时字符串:
char src[] = { "Word" };
char dest[20] = "Hello ";
// 调用strcat()函数.
strcat(dest, src);
printf("%s\n", dest);
return 0;
}
1.5. strncat (字符串追加带长度)
char * strncat ( char * destination, const char * source, size_t num );
1.6. strcmp (字符串比较)
参考文档:strcmp - C++ Reference (cplusplus.com)
// 头文件<string.h>
int strcmp(const char *s1, const char *s2);
// 函数说明:
// 比较 s1 和 s2 指向的字符串的大小,
// 比较的方法: 逐个字符去比较 ascII 码, 一旦比较出大小返回。
// 如过所有字符都一样, 则返回 0
// 返回值:
// 如果 s1 指向的字符串大于 s2 指向的字符串 返回 1
// 如果 s1 指向的字符串小于 s2 指向的字符串 返回-1
// 如果相等的话返回 0
int strncmp(const char *s1, const char *s2, size_t n);
// 函数说明:
// 比较 s1 和 s2 指向的字符串中的前 n 个字符
标准规定:
-
第一个字符串大于第二个字符串,则返回大于0的数字。
-
第一个字符串等于第二个字符串,则返回0。
-
第一个字符串小于第二个字符串,则返回小于0的数字。
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
// 创建临时字符串:
char arr1[20] = { "zhangsan" };
char arr2[20] = { "zhangsanfeng" };
// 比较规则:zz相等往下走.. nn相等往下走..f和\0不相等f大.
int ret = strcmp(arr1, arr2);
if (ret < 0)
printf("<\n");
else if (ret == 0)
printf("==\n");
else if (ret > 0)
printf(">\n");
return 0;
}
1.7. strncmp 库函数
int strncmp ( const char * str1, const char * str2, size_t num );
1.8. strchr (字符串查找字符)
参考文档:strchr - C++ Reference (cplusplus.com)
#include <string.h>
char *strchr(const char *s, int c);
// 函数说明:
// 在字符指针 s 指向的字符串中, 找 ascii 码为 c 的字符
// 注意, 是首次匹配, 如果过说 s 指向的字符串中有多个 ASCII 为 c 的字符, 则找的是第 1 个字符
// 返回值:
// 找到了返回找到的字符的地址,
// 找不到返回 NULL,
char *strrchr(const char *s, int c);
// 函数的说明:
// 末次匹配在 s 指向的字符串中, 找最后一次出现的 ASCII 为 c 的字符,
// 返回值:
// 末次匹配的字符的地址。
// strchr从前往后找 第一次出现c的地址,如果没找到 返回NULL
使用实例:
#include <stdio.h>
#include <string.h>
void StrchrTest()
{
char src[] = "Hello World!";
char *findRet = strchr(src, 'W');
if (findRet != NULL)
{
printf("%s\n", findRet);
}
}
int main()
{
StrchrTest();
return 0;
}
1.9. strstr (字符串查找字串)
参考文档:strstr - C++ Reference (cplusplus.com)
#include <string.h>
char * strstr ( const char *str1, const char * str2);
char * strstr ( const char *str1, const char * str2);
// 函数说明:
// 在 haystack 指向的字符串中查找 needle 指向的字符串, 也是首次匹配
// 返回值:
// 找到了: 找到的字符串的首地址
// 每找到: 返回 NULL
// 返回值:
// 找到返回找到的地址 失败 返回NULL
-
返回str2在str1中第一次出现的指针,如果str2不是str1的一部分,则返回空指针。
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
char arr1[] = { "bbbbcaasklfghsa" };
char arr2[] = { "bbc" };
// 调用strstr()函数.
char* ret = strstr(arr1, arr2);
if (ret == NULL)
printf("未找到相应的字串!\n");
else
printf("%s\n", ret);
return 0;
}
1.10. atoi/atol/atof (字符串转数值 )
// 头文件: #include <stdlib.h>
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
long long atoq(const char *nptr);
double atof(const char *nptr);
// 函数的功能:
// 将 nptr 指向的字符串转换成整数, 返回
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
void Ato_Test()
{
printf("%d\n", atoi("1234"));
printf("%ld\n", atol("12314123"));
printf("%lld\n", atoll("3245234"));
printf("%f\n", atof("3.2344"));
}
int main()
{
Ato_Test();
return 0;
}
1.11. strtok (字符串查找分割)
参考文档:strtok - C++ Reference (cplusplus.com)
char * strtok ( char * str, const char * sep );
// 第一次切割: str必须指向 待切割的字符串的首元素地址 delim指向分割符":"
// 后续切割: str传NULL delim指向分割符":"
// 返回值:
// 成功:返回值子串的首元素地址
// 失败:返回NULL
-
sep参数是个字符串,定义了用作分隔符的字符集合
-
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。
-
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
-
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。
-
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。
-
如果字符串中不存在更多的标记,则返回 NULL 指针。
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
char email[] = { "adasdsa@kgsdahgksldsajf.com" };
char cp[50] = {0};
strcpy(cp, email);
// 接下来测试strtok()函数.
char* ret = NULL;
for (ret = strtok(cp, "@."); ret != NULL; ret = strtok(NULL, "@.")) {
printf("%s\n", ret);
}
return 0;
}
-----------------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
void StrtokTest()
{
char str[] = "hehehe:xixixi:hahaha:lalala#heiheihei:henhenhen:wuwuwu";
char *buf[32]; // 存放每一次切割后切出来数据的首元素地址.
// 进行分割.
size_t i = 0;
buf[i] = strtok(str, ":");
while (buf[i] != NULL)
{
++i;
buf[i] = strtok(NULL, ":");
}
// 进行遍历打印
i = 0;
while (buf[i] != NULL)
{
printf("%s\n", buf[i++]);
}
}
int main()
{
StrtokTest();
return 0;
}
// 代码优化:
1.12. strerror (错误报告)
参考文档:strerror - C++ Reference (cplusplus.com)
char * strerror ( int errnum );
-
返回错误码,所对应的错误信息。
使用实例:
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main() {
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("%s\n", strerror(4));
return 0;
}
1.13. toupper (字符转大写)
参考文档:toupper - C++ Reference (cplusplus.com)
int toupper ( int c );
-
将字符转为大写.
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
int main() {
char ch = 'a';
int ich = toupper(ch);
printf("%c", ich);
return 0;
}
1.14. tolower (字符转小写)
参考文档:tolower - C++ Reference (cplusplus.com)
int tolower ( int c );
-
将字符转为小写.
使用实例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
int main() {
char ch = 'a';
int ich = tolower(ch);
printf("%c", ich);
return 0;
}
1.15. 其他常用(字符分类函数)
函数 | 如果他的参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,a~z,A~Z,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
二. 字符串处理函数模拟
2.1. strcpy 模拟实现
/* strcpy 模拟实现 */
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* destination, char* soure) {
// 断言:保护两个指针形参.
assert(destination && soure);
// 保留destination的指针位置,便于返回,形成链式访问.
char* pBegin = destination;
while (*destination++ = *soure++);
return pBegin;
}
int main() {
// 该字符串在内存存放的是:a b c d e f g \0
// 创建临时字符串:
char src[] = { "abcdefg" };
char dest[20];
// 使用strcpy();
my_strcpy(dest, src);
printf("sourceArr:= %s\n", dest);
return 0;
}
2.2. strlen 模拟实现
/*strlen 模式实现*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
// 计数器法:
// 所谓计数器方法,顾名思义,就是创建一个临时变量count用来计数,遍寻字符串直到找到字符串结束标志’\0’,每循环找一次就count + 1,最后返回count就可以得到字符串长度了。
size_t my_strlen_1(const char* str) {
// 断言指针变量不为NULL指针.
assert(str);
int count = 0;
while (*str != '\0') {
++count;
++str;
}
return count;
}
// 递归法:
size_t my_strlen_2(const char* str) {
// 断言指针变量不为NULL指针.
assert(str);
if (*str != '\0') {
return 1 + my_strlen_2(str + 1);
}
else {
return 0;
}
}
// 指针减去指针法
// 在一个数组中,指向两个元素的两个指针相减,得到的是这两个指针间的元素个数。
size_t my_strlen_3(const char* str) {
// 断言指针变量不为NULL指针.
assert(str);
const char* end = str;
while (*end != '\0')
++end;
return end - str; // 高地址-低地址.
}
int main() {
// 该字符串在内存存放的是:a b c d e f g \0
// 创建临时字符串:
char arr[] = { "abcdefg" };
// 调用库函数strlen.
size_t lenght = strlen(arr);
size_t lenght1 = my_strlen_1(arr);
size_t lenght2 = my_strlen_2(arr);
size_t lenght3 = my_strlen_3(arr);
// 打印结果:
printf("%zu %zu %zu %zu\n", lenght, lenght1, lenght2, lenght3);
return 0;
}
2.3. strcat 模拟实现
/* strcat 模拟实现 */
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* destination, const char* soure) {
// 断言:保护两个指针形参.
assert(destination && soure);
// 保留destination的指针位置,便于返回,形成链式访问.
char* pBegin = destination;
// 找到destination的\0的位置.
while (*destination != '\0')
++destination;
// 将soure的每一个字符存入destination中.
while (*destination++ = *soure++);
return pBegin;
}
int main() {
// 该字符串在内存存放的是:a b c d e f g \0
// 创建临时字符串:
char src[] = { "Word" };
char dest[20] = "Hello ";
// 调用strcat()函数.
my_strcat(dest, src);
printf("%s\n", dest);
return 0;
}
2.4. strcmp 模拟实现
/* strcmp 模拟实现 */
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2) {
// 断言:保护两个指针形参.
assert(str1 && str2);
// 比较原则:
// -第一个字符串大于第二个字符串,则返回大于0的数字。
// - 第一个字符串等于第二个字符串,则返回0。
// - 第一个字符串小于第二个字符串,则返回小于0的数字。
while (*str1 == *str2) {
if (str1 == '\0')
return 0;
++str1;
++str2;
}
// 程序走到这里说明是不等于的,要么是大于,要么是小于.
return(*str1 - *str2);
}
int main() {
// 创建临时字符串:
char arr1[20] = { "zhangsan" };
char arr2[20] = { "zhangsanfeng" };
// 比较规则:zz相等往下走.. nn相等往下走..f和\0不相等f大.
int ret = strcmp(arr1, arr2);
if (ret < 0)
printf("<\n");
else if (ret == 0)
printf("==\n");
else if (ret > 0)
printf(">\n");
return 0;
}
2.5. strchr 模拟实现
#pragma once
#include <stdio.h>
#include <assert.h>
/// <summary>
/// 字符串查找字符(模拟实现)
/// </summary>
/// <param name="s"></param>
/// <param name="c"></param>
/// <returns></returns>
char* my_strchr(char* s, int c)
{
assert(s);
char* p_begin = s;
while (*p_begin != c)
{
if (*p_begin == '\0')
return NULL;
p_begin++;
}
return p_begin;
}
/// <summary>
/// 字符串查找字符(模拟实现)
/// </summary>
/// <param name="s"></param>
/// <param name="c"></param>
/// <returns></returns>
const char* my_const_strchr(const char* s, int c)
{
assert(s);
const char* p_begin = s;
while (*p_begin != c)
{
if (*p_begin == '\0')
return NULL;
p_begin++;
}
return p_begin;
}
2.5. strstr 模拟实现
// str1 为字符串, str2 为子串.
char* my_strstr(const char* str1, const char* str2) {
assert(str1 && str2);
// 定义指向的指针.
const char* s1 = str1;
const char* s2 = str2;
const char* p = s1;
while (*s1 != '\0') {
s1 = p;
s2 = str2;
// 首个字母相同.
while (*s1 != '\0', *s2 != '\0' && *s1 == *s2) {
++s1;
++s2;
}
if (*s2 == '\0') {
return (char*)p;
}
// 上面循环没有对比成功.
++p;
}
return NULL;
}
int main() {
char arr1[] = { "bbbbcaasklfghsa" };
char arr2[] = { "bbc" };
// 调用strstr()函数.
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
printf("未找到相应的字串!\n");
else
printf("%s\n", ret);
return 0;
}
2.6. toupper 模拟实现
int my_toypper(int c) {
return c - 32;
}
int main() {
char ch = 'a';
int ich = my_toypper(ch);
printf("%c", ich);
return 0;
}
2.7. tolower 模拟实现
int my_tolower(int c) {
return c + 32;
}
int main() {
char ch = 'A';
int ich = my_tolower(ch);
printf("%c", ich);
return 0;
}