字符函数:
1.字符分类函数
C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。
这些函数的使用都需要包含一个头文件:<ctype.h>
函数 如果他返回下列条件就返回
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 任何可打印字符,包括图形字符和空白字符
islower 是能够判断参数部分的 c 是否是小写字母的。
通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。
//判断字母的大小写
int main()
{
int ch = getchar();//getchar()接受一个字符,直接返回来,会让我们输入一个值
if (ch >= 'a' && ch <= 'z')
{
printf("小写\n");
}
else if (ch >= 'A' && ch <= 'Z')
{
printf("大写\n");
}
//putchar(ch);//直接输出(打印)上面getchar输入的值
//在ASCII码中0-31这32个字符是不可打印字符
return 0;
}
#include<ctype.h>
int main()
{
int ch = getchar();
if (islower(ch))
{
printf("小写\n");
}
else if (isupper(ch))
{
printf("大写\n");
}
return 0;
}
2.字符转换函数
例子:将字符串中的小写字母转换成大写字母,其余的字符不变。
int tolower ( int c ); 将参数传进去的大写字母转为小写
int toupper ( int c ); 将参数传进去的小写字母转为大写
//将一个字符串转换全小写
int main()
{
char arr[] = "I Am A Student";
int i = 0;
while (arr[i])
{
if (isupper(arr[i]))
{
arr[i] = arr[i] + 32;
// a 对应的ASCII码值:97
// A 对应的ASCII码值:65
}
putchar(arr[i]);
i++;
}
return 0;
}
字符串函数:
3.strlen 的使用和模拟实现
size_t strlen ( const char * str );
- 字符串以 ' \0 ' 作为结束标志,strlen函数返回的是在字符串中 ' \0 ' 之前的字符的个数(不包含' \0 ')
- 参数指向的字符串必须以 ' \0 ' 结束
- 注意函数返回的类型是 size_t , 是无符号的(易错)
- strlen的头文件是<string.h>
#include<string.h>
//strlen() 函数 求字符串长度的函数
int main()
{
//char arr[] = "zxcvbn";// 数组内容:z x c v b n \0
//char arr[] = { 'z','x','c' };//随机值 没有找到 \0
char arr[] = { 'z','x','c','\0'};// 3
size_t len = strlen(arr);
printf("%zd\n", len);
return 0;
}
看个有趣的代码:
int main()
{ // 3-7=-4 ??
if (strlen("asd") - strlen("asdfghj") > 0)
{
printf("大于\n");
}
else
{
printf("小于等于");
}
return 0;
}
运行出的结果:
为什么上面显示的是 “大于”??
strlen 返回的值是 无符号类型的整数,无符号类型的整数的加减的结果也是无符号类型的整数,所以不会出现负数
strlen 函数的多种模拟实现方法:
#include<assert.h>
//方法1:
size_t my_strlen1(char * str)
{
assert(str);
size_t count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
//方法2:
size_t my_strlen2(char* str)
{
assert(str);
char *start = str;
while (*str)
{
str++;
}
return str-start;//指针减指针的应用
}
//方法3:
//不创建变量实现 strlen()函数的实现 ---- 递归的方法来实现
size_t my_strlen3(char* str)
{
assert(str);
if (*str == '\0')
return 0;
else
return 1 + my_strlen3(str + 1);
}
// ch arr[]="zxcvbn" --> [z x c v b n \0]
//1+my_srtrlen("xcvbn")
//1+1+my_srtrlen("cvbn")
//1+1+1+my_srtrlen("vbn")
//1+1+1+1+my_srtrlen("bn")
//1+1+1+1+1+my_srtrlen("n")
//1+1+1+1+1+1+my_srtrlen("")
int main()
{
char arr[] = "abc";
//size_t len = my_strlen1(arr);
//size_t len = my_strlen2(arr);
size_t len = my_strlen3(arr);
printf("%zd\n", len);
return 0;
}
4.strcpy 的使用和模拟实现
char* strcpy(char* destination, const char* source);
- 源字符串必须以 ' \0 ' 结束
- 会将源字符串中的 ' \0 ' 拷贝到目标空间
- 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须可以修改
int main()
{
char arr1[] = "xxxxxxxxxxxxxxxxxx";
char arr2[] = "hehehe";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
调试看看是否将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中??
确实是:将arr2的内容拷贝到了arr1中,同样也将arr2中的 '\0' 也拷贝到了arr1中
int main()
{
char arr1[3] = { 0 };//目标空间必须足够大,否则会出现错误
char arr2[] = "hello hello world";
strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
int main()
{
char* pch = "abcdefghiasdfg";//常量字符串是不可修改的
char arr[] = "hello world";
strcpy(pch, arr);
printf("%s\n", pch);//目标空间必须是可以修改的
return 0;
}
strcpy 的模拟实现:
char * my_strcpy(char* str1,const char* str2)
{
char* ret = str1;
while (*str2 !='\0')
{
*str1 = *str2;
str1++;
str2++;
}
*str1 = *str2;
return ret;
}
//优化如下:
#include <assert.h>
char* my_strcpy(char* str1, const char* str2)
{
assert(str1 && str2);
char* ret = str1;
while (*str1++ = *str2++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = {0};
char arr2[] = "hello world";
printf("%s\n",my_strcpy(arr1, arr2));
return 0;
}
5.strcat 的使用和模拟实现
char * strcat ( char * destination, const char * source );
- 源字符串必须以 ' \0 ' 结束
- 目标空字符串中也得有 ' \0 ',否则没办法知道从哪里开始追加
- 目标空间必须足够大,能容下源字符串的内容
- 目标空间必须可修改
- 字符串自己给自己追加,是什么情况??
int main()
{
char arr1[25] = "Hello ";
char arr2[] = "World";
char *ret=strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
模拟实现strcat函数:
char* my_strcat(char* dest, const char* sour)
{
char* ret = dest;
assert(dest && sour);
//1.找到目标空间中的\0
while (*dest)
{
dest++;
}
//2.拷贝sour中的内容到dest中
while (*dest++ = *sour++)
{
;
}
return ret;
}
int main()
{
char arr1[25] = "Hello ";
char arr2[] = "World";
char* ret = my_strcat(arr1, arr2);
printf("%s\n", ret);
return 0;
}
字符串自己给自己追加的情况:
#include <assert.h>
char* my_strcat(char* dest, const char* sour)
{
char* ret = dest;
assert(dest && sour);
//1.找到目标空间中的\0
while (*dest)
{
dest++;
}
//2.拷贝sour中的内容到dest中
while (*dest++ = *sour++)
{
;
}
return ret;
}
int main()
{
char arr1[25] = "Hello ";
char* ret = my_strcat(arr1, arr1);
printf("%s\n", ret);
return 0;
}
6.strcmp 函数的使用
int strcmp ( const char * str1, const char * str2 );
标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
- 是根据两个字符串上对应的字符ASCII码值的大小的比较
int main()
{
int ret = strcmp("bbq", "abcdef");
printf("%d\n", ret);
return 0;
}
int main()
{
int ret = strcmp("bbq", "abcdef");
if (ret > 0)
{
printf("大于\n");
}
else if (ret < 0)
{
printf("小于\n");
}
else
printf("等于\n");
return 0;
}
strcmp函数的模拟实现:
int my_strcmp(const char* dest, const char* sour)
{
while (*dest == *sour)
{
if (*dest == '\0')
return 0;
dest++;
sour++;
}
if (*dest - *sour > 0)
return 1;
else
return -1;
}
//方法二:
int my_strcmp(const char* dest, const char* sour)
{
while (*dest == *sour)
{
if (*dest == '\0')
return 0;
dest++;
sour++;
}
return *dest - *sour;
}
int main()
{
int ret = my_strcmp("bbq", "abcdef");
if (ret > 0)
{
printf("大于\n");
}
else if (ret < 0)
{
printf("小于\n");
}
else
printf("等于\n");
return 0;
}
7.strncpy 函数的使用
char * strncpy ( char * destination, const char * source, size_t num );
- Copies the first num characters of source to destination. If the end of the source C string(which is signaled by a null-character) is found before num characters have been copied,destination is padded with zeros until a total of num characters have been written to it.
- 拷⻉num个字符从源字符串到⽬标空间。
- 如果源字符串的⻓度⼩于num,则拷⻉完源字符串之后,在⽬标的后边追加0,直到num个。
8.strncat 函数的使用
char * strncat ( char * destination, const char * source, size_t num );
- Appends the first num characters of source to destination, plus a terminating null-character(将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符)。
- If the length of the C string in source is less than num, only the content up to the terminatingnull-character is copied.(如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到\0 的内容追加到destination指向的字符串末尾)。
//strncat 比strcat多了一个参数:可以限制追加的字符的个数
int main()
{
char arr1[20] = "xxxxxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 7);
//调试就会发现:看不出是否追加arr2的\0
return 0;
}
int main()
{
char arr1[20] = "hello\0xxxxxxxx";
char arr2[] = "world";
strncat(arr1, arr2, 7);
//将w o r l d \0拷贝到了arr1中,是从arr1中的第一个\0开始拷贝
//可以看出是要将arr2中的\0追加到arr1中的
return 0;
}
9.strncmp函数的使用
int strncmp ( const char * str1, const char * str2, size_t num );
比较str1和str2的前num个字符,如果相等就继续往后⽐较,最多比较num个字⺟,如果提前发现不⼀样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0。
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcq";
int ret = strncmp(arr1, arr2, 3);
//将arr1和arr2中的前3个字母进行比较,有字母长度的限制
printf("%d\n", ret);
return 0;
}
10.strstr 函数的使用
- Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.(函数返回字符串str2在字符串str1中第⼀次出现的位置)。
- The matching process does not include the terminating null-characters, but it stops there.(字符串的⽐较匹配不包含 \0 字符,以 \0 作为结束标志)。
int main()
{
char arr1[] = "abbbbcdebbehig";
char arr2[] = "bbe";
char* ret = strstr(arr1, arr2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("找不到\0");
return 0;
}
strstr函数的模拟实现:
//暴力求解
char* my_strstr(const char* str1, const char* str2)
{
const char* cur = str1;
char* s1 = NULL;
char* s2 = NULL;
assert(str1 && str2);
//特殊规定的处理:
if (*str2 == '\0')
return (char *)str1;
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1&&*s2&&*s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cur;
}
cur++;
}
return NULL;
}
//测试用例1
//abbbbcdebbehig
//bbe
//测试用例2
//abbbbcdebbehig
//abb
//测试用例3
//abbbbcdebbehig
//bbf
//测试用例4
//abbbbcdebbehig
//abbbbcdebbehig
//测试用例越多,功能越齐全,不容易漏掉其他的情况
//bug也不容易出现
int main()
{
char arr1[] = "abbbbcdebbehig";
char arr2[] = "bbe";
char* ret = my_strstr(arr1, arr2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("找不到\0");
return 0;
}
11.strtok 函数的使用
char * strtok ( char * str, const char * sep);
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
//strtok 函数
int main()
{
char arr1[] = "zhangsan@163.com#hehhe";
char arr2[30] = {0};
strcpy(arr2, arr1);
const char* p = "@.#";
char* s = NULL;
//for循环优点:初始化部分只执行一次
for (s = strtok(arr2, p); s != NULL; s = strtok(NULL, p))
{
printf("%s\n", s);
}
//char* s = strtok(arr2, p);
//printf("%s\n", s);
//s = strtok(NULL, p);
//printf("%s\n", s);
//s = strtok(NULL, p);
//printf("%s\n", s);
//s = strtok(NULL, p);
//printf("%s\n", s);
//繁琐、冗余
return 0;
}
12.strerror 函数的使用
- strerror 函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
- 在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址回。
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d:%s\n", i, strerror(i));
}
return 0;
}
在vs下输出结果为:
#include<errno.h>
//C语言是可以进行文件操作的
//打开文件:
//FILE* pf=fopen(...)
//如果文件打开成功,则返回一个地址
//如果文件打开失败,则返回一个NULL
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
//printf("Error opening file unexist.ent: %s\n", strerror(errno));
//strerror 头文件:<string.h>
//errno 头文件:<errno.h>
perror("Error opening file unexist.ent");
//perror 函数自动加上:和空一格
return 0;
}
输出结果: