萌新的学习笔记,写错了恳请斧正。
目录
字符分类函数
字符转换函数
strlen
模拟实现
strcpy
模拟实现
strcat
模拟实现
strcmp
模拟实现
strncpy
模拟实现
strncat
模拟实现
strncmp
strstr
模拟实现
strtok
使用实例
strerror与perror
使用实例
字符分类函数
在ctype.h头文件中有一些用于字符分类的函数,用于判断字符属于哪种类型
其中常见的有:
这些函数如果判断为假,则返回0,否则返回非零
比方说可以写一个识别小写字母并转换为大写的函数:
#include
#include
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
#include
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;
}
其实并没有方便多少,感觉用处不大
#include
size_t strlen(const char* str);
strlen用于计算字符串的长度,其返回值size_t是无符号整数
strlen函数将会返回从传递给它的指针开始直到第一个“\0”为止的非零元素的数量
使用strlen函数需要先包含string.h头文件
最简单的就是循环计数了:
#include
#include
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;
}
#include
char* strcpy(char* dest, const char* src);
strcpy用于复制字符串,使用需要先包含string.h头文件
strcpy将从src指针头开始直到‘\0’结尾的部分复制到dest指针指向的地方
注意:
char* my_strcpy(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++);
return ret;
}
#include
char* strcat(char* dest, const char* src);
strcat用于字符串的追加,使用需要先包含string.h头文件
strcat将从dest指向的位置开始寻找,直到找到‘\0’,然后将从src指向的位置开始到第一个‘\0’为止的部分复制到‘\0’的位置(包括‘\0’)
注意:
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
char* ret = dest;
while (*++dest);
while (*dest++ = *src++);
return dest;
}
#include
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;
}
#include
char* strncpy(char* dest, const char* src, size_t n);
strncpy与strcpy功能一致,但是只复制前n个字符(如果位数足够最后不补0)
如果先碰到‘\0’则后续一直补0直到满足n个字符的要求
char* my_strncpy(char* dest, const char* src, size_t n)
{
assert(dest && src);
char* ret = dest;
while (n-- && *src)
*dest++ = *src++;
while (n--)
*dest++ = 0;
return ret;
}
#include
char* strncat(char* dest, const char* src, size_t n);
同样的,是拼接前n个字符,但是会追加一个‘/0’
如果先遇到‘\0’则停止拼接,不需要补0
char* my_strncat(char* dest, const char* src, size_t n)
{
assert(dest && src);
char* ret = dest;
while (*++dest);
while (n--)
{
if (0 == *src)
break;
else
*dest++ = *src++;
}
*dest = 0;
return ret;
}
#include
int strncmp(const char* str1, const char* str2, size_t n);
同样的,比较前n个字符,比较方法同strcmp
#include
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;
}
#include
char* strtok(char* str, const char* sep);
strtok用于分割字符串
sep参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的非空子串
注意!!!strtok会改变原字符串!!!
#include
#include
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;
}
#include
char* strerror(int errnum);
#include //or
void perror( const char *string );
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回
在不同的系统和C语言标准库的实现中都规定了一些错误码,一般在errno.h头文件中说明
程序启动的时候就会使用一个全局变量errno来记录程序的当前错误码(初始为0表示无错)
#include
#include
int main()
{
int i = 0;
for (i = 0; i < 44; i++)
printf("%s\n", strerror(i));
return 0;
}
而perror函数则进一步,可以直接打印“输入的字符串+冒号+错误信息”一条龙。