8 min to read
椋鸟C语言笔记#23
字符函数、字符串函数
萌新的学习笔记,写错了恳请斧正。
字符分类函数
在 ctype.h 头文件中有一些用于字符分类的函数,用于判断字符属于哪种类型
其中常见的有:
- iscntrl:任意控制字符
- isspace:空白字符:空格、换页(\f)、换行(\n)、回车(\t、制表符 \ t\v
- isdigit:十进制数字 0~9
- isxdigit:十六进制数字 0~9、a~f、A~F
- islower:小写字母 a~z
- isupper:大写字母 A~Z
- isalpha:字母 a~z 或 A~Z
- isalnum:字母或数字
- ispunct:标点符号
- isgraph:图形字符
- isprint:任何可打印字符,包括图形字符和空白字符
这些函数如果判断为假,则返回 0,否则返回非零
比方说可以写一个识别小写字母并转换为大写的函数:
#include <stdio.h>
#include <ctype.h>
char* caps(char* s)
{
char* ret = s;
do
{
if (islower(*s))
*s -= 32;
} while (*s++);
return ret;
}
int main()
{
char s[] = "ajiofe";
printf("%s", caps(s));
return 0;
}
字符转换函数
其实 ctype.h 头文件中其实已经内置了可以用于大小写转换的函数,即字符转换函数
其中就包括 tolower 和 toupper,所以上述代码也可以改为:
#include <stdio.h>
#include <ctype.h>
char* caps(char* s)
{
char* ret = s;
do
{
if (islower(*s))
*s = toupper(*s);
} while (*s++);
return ret;
}
int main()
{
char s[] = "ajiofe";
printf("%s", caps(s));
return 0;
}
其实并没有方便多少,感觉用处不大
strlen
#include <string.h>
size_t strlen(const char* str);
strlen 用于计算字符串的长度,其返回值 size_t 是无符号整数
strlen 函数将会返回从传递给它的指针开始直到第一个 “\0” 为止的非零元素的数量
使用 strlen 函数需要先包含 string.h 头文件
模拟实现
最简单的就是循环计数了:
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char arr[])
{
assert(arr);
int i = 0;
while (*(arr + i))
i++;
return i;
}
当然如果使用递归也可以不用循环计数:
size_t my_strlen(const char arr[])
{
assert(arr);
return *(arr) ? 1 + my_strlen(arr + 1) : 0;
}
双指针也可以实现:
size_t my_strlen(const char arr[])
{
assert(arr);
char* p = arr;
while (*p)
p++;
return p - arr;
}
strcpy
#include <string.h>
char* strcpy(char* dest, const char* src);
strcpy 用于复制字符串,使用需要先包含 string.h 头文件
strcpy 将从 src 指针头开始直到‘\0’结尾的部分复制到 dest 指针指向的地方
注意:
- ‘\0’也会被复制过去
- 目标空间可用部分需要足够大
- 目标空间应当可修改
模拟实现
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++);
return ret;
}
strcat
#include <string.h>
char* strcat(char* dest, const char* src);
strcat 用于字符串的追加,使用需要先包含 string.h 头文件
strcat 将从 dest 指向的位置开始寻找,直到找到‘\0’,然后将从 src 指向的位置开始到第一个‘\0’为止的部分复制到‘\0’的位置(包括‘\0’)
注意:
- 目标字符串也需要有‘\0’
- 目标空间可用部分需要足够大
- 目标空间应当可修改
- 自己追加自己会造成死循环
模拟实现
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*++dest);
while (*dest++ = *src++);
return dest;
}
strcmp
#include <string.h>
int strcmp(const char* str1, const char* str2);
strcmp 用于字符串之间的比较(逐字符),使用需要先包含 string.h 头文件
strcmp 会分别从 str1 与 str2 指向的位置开始对比 ASCII 码值,如果有一方先出现不等情况。则按照规定输出(str1 大于 str2 输出正数,反正负数,如果直到两边都遇到‘\0’都没有不等的情况则输出 0)
常用于按字母排序
模拟实现
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (!*str1)
return 0;
str1++, str2++;
}
return *str1 - *str2;
}
strncpy
#include <string.h>
char* strncpy(char* dest, const char* src, size_t n);
strncpy 与 strcpy 功能一致,但是只复制前 n 个字符(如果位数足够最后不补 0)
如果先碰到‘\0’则后续一直补 0 直到满足 n 个字符的要求
strncat
#include <string.h>
char* strncat(char* dest, const char* src, size_t n);
同样的,是拼接前 n 个字符,但是会追加一个‘/0’
如果先遇到‘\0’则停止拼接,不需要补 0
strncmp
#include <string.h>
int strncmp(const char* str1, const char* str2, size_t n);
同样的,比较前 n 个字符,比较方法同 strcmp
strstr
#include <string.h>
char* strstr(const char* str1, const char* str2);
strstr 用于寻找字符串的子序列
strstr 会从 str1 指向的位置开始,寻找第一个与 str2 相同的序列,并返回找到的序列头的地址
如果没有与 str2 相同的子序列,则返回空指针 NULL
模拟实现
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
char* sign1 = (char*)str1;
char* sign2 = (char*)str1;
char* sign = (char*)str2;
while (*sign1)
{
if (!*sign)
return sign1;
sign1++;
sign2 = sign1;
sign = (char*)str2;
while (*sign2 && *sign && !(*sign2 - *sign))
sign2++, sign++;
}
return NULL;
}
strtok
#include <string.h>
char* strtok(char* str, const char* sep);
strtok 用于分割字符串
sep 参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的非空子串
- 如果 str 不为 NULL,strtok 函数找到 str 中的第一个被分割的子串,并将其用‘\0’结尾(覆盖后面的分隔符),返回一个指向这个子串头的指针
- 如果 str 为 NULL,strtok 函数会从上一次使用该函数分割的位置开始,寻找下一个被分割的子串,并将其用‘\0’结尾(覆盖后面的分隔符),返回一个指向这个子串头的指针
- 如果已经分割完了,没有什么能返回的了,就返回 NULL
注意!!!strtok 会改变原字符串!!!
使用实例
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "192.168.0.1:23333";
char* sep = ".:";
char* str = NULL;
for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
printf("%s\n", str);
return 0;
}
strerror
#include <string.h>
char* strerror(int errnum);
strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回
在不同的系统和 C 语言标准库的实现中都规定了一些错误码,一般在 errno.h 头文件中说明
程序启动的时候就会使用一个全局变量 errno 来记录程序的当前错误码(初始为 0 表示无错)
使用实例
#include <stdio.h>
#include <string.h>
int main()
{
int i = 0;
for (i = 0; i < 44; i++)
printf("%s\n", strerror(i));
return 0;
}
Comments