C语言学习之字符函数和字符串函数
在C语言前面的内容中,我们学习到的库函数主要还是针对输入输出以及数字相关的内容,今天我们来学习一下有关于字符相关的函数,来对字符和字符串进行操作。
目录
字符分类函数
字符转换函数
strlen函数的使用和模拟实现
模拟实现
strcpy函数的使用和模拟实现
模拟实现
strcat函数的使用和模拟实现
模拟实现:
strcmp函数的使用和模拟实现
模拟实现:
strncpy函数的使用
strncat函数的使用
strncmp函数的使用
strstr函数的使用和模拟实现
模拟实现
strtok函数的使用
strerror函数
perrior函数
ASCII值字符表
一、标准ASCII字符表(0-127)
二、控制字符和转义字符表(0-31 和 127)
字符分类函数
C语言中有一系列自带的函数专门处理字符分类,即处理一个字符属于什么类型的。使用这些函数需要包含头文件<ctype.h>
以下就是<ctype.h>头文件中所有函数的函数名及其返回为真的条件
函数名 | 返回真值的条件(参数满足) |
---|---|
isalnum(int c) | c 是字母(a-z /A-Z )或数字(0-9 ) |
isalpha(int c) | c 是字母(a-z /A-Z ) |
iscntrl(int c) | c 是控制字符(ASCII 0-31 或 127) |
isdigit(int c) | c 是十进制数字(0-9 ) |
isgraph(int c) | c 是除空格外的可打印字符(ASCII 33-126) |
islower(int c) | c 是小写字母(a-z ) |
isprint(int c) | c 是可打印字符(包括空格,ASCII 32-126) |
ispunct(int c) | c 是标点符号(即非空格、非字母数字的可打印字符,如 !@#$%^&*() 等) |
isspace(int c) | c 是空白字符(空格 ' ' 、换行符 '\n' 、制表符 '\t' 、回车 '\r' 、垂直制表符 '\v' 、换页符 '\f' ) |
isupper(int c) | c 是大写字母(A-Z ) |
isxdigit(int c) | c 是十六进制数字(0-9 /a-f /A-F ) |
注意:
所有函数的参数 c
应为 unsigned char
类型或 EOF
(通常定义为 -1
)。
直接传递 char
类型可能导致符号扩展问题(如 char
为负值时行为未定义)。
使用的方法十分简单,如下:
int islower(int c);
练习:挑出一段字符中所有的数字:
#include<stdio.h>
#include<ctype.h>
int main()
{char ch[] = "ABCcdfe123###26 qwe21w";int i = 0;while (ch [i] != '\0'){if (isdigit(ch[i]) !=0){printf("%c ",ch[i]);}i++;}return 0;
}
练习:将一段字符中所有的大写字母转化为小写字母:
#include<stdio.h>
#include<ctype.h>
int main()
{char ch[] = "ABCcdfe123###26 qwe21w";int i = 0;while (ch[i] != '\0'){if (islower(ch[i]) != 0){ch[i] = ch[i] - 32;}printf("%c", ch[i]);i++;}return 0;
}
字符转换函数
C语言有两个字符转换函数
int tolower(int c)//将参数传入进去的大写字母转化为小写
int toupper(int c)//将参数传入进去的小写字母转化为大写
以下的函数到strtok函数使用均需要包含头文件<string.h>
strlen函数的使用和模拟实现
使用的基本语法:
size_t strlen(const char* str);
字符串以’\0‘为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包括’\0‘)
但是参数str指向的字符串必须以'\0'为结束标识
注意函数的返回值为size_t,为无符号类型(注意!!!)
模拟实现
方案1(计数器):
int my_strlen(const char* str)
{int count = 0;assert(str!=NULL);while (*str){count++:str++;}return count;
}
方案2(递归):
int my_strlen(const char* str)
{assert(str);if (*str=='\0'){return 0;}else{return 1 + my_strlen(str + 1);}
}
方案3(指针—指针):
int my_strlen(const char* str)
{assert(str);char* p = str;while (*p != '\0'){p++;}return p - str;
}
strcpy函数的使用和模拟实现
strcpy函数是字符串拷贝函数。
在实际应用中如果我们要进行字符的赋值是不能这么做的
char st1[]="hello world";
char st2[] = "abcdfe";
st1[] = st2[];//这么写是绝对错误的
因为数组本质上是指针,是常量值,指针是不能改变的。
因此我们用strcpy函数来实现字符串的复制拷贝
基本语法如下:
char* strcpy(char *destination, const char *source);
其中destination为目标字符串,source为源头字符串
源字符串必须以’\0‘结束,并且会将源字符串的'\0'拷贝至目标空间
目标空间必须足够大,并且必须可以修改
模拟实现
主函数:
int main()
{char ch1 [] = "ABCDEFGHIKJHG";char ch2 [] = "hello world";my_strcpy(ch1, ch2);printf("%s\n", ch1);return 0;
}
方案1:
void my_strcpy(char *dest ,char *soc)
{char* ret = *soc;assert(dest!=NULL && soc!=NULL);while (*soc!='\0'){*dest = *soc;soc++;dest++;//可以简写为*dest++ = *soc++;}*dest = *soc;//拷贝'\0'
}
方案2:
char* my_strcpy(char *dest ,char *soc)
{char* ret = *soc;assert(dest!=NULL && soc!=NULL);while (*soc!='\0'){*dest = *soc;soc++;dest++;//可以简写为*dest++ = *soc++;}*dest = *soc;//拷贝'\0'return ret;//返回原字符串的地址
}
strcat函数的使用和模拟实现
strcat函数的作用就是将两个字符串函数拼接(追加)起来。
语法上与strcpy很类似:
char* strcat(char *destination, const char *source);
其中destination为目标字符串,source为源头字符串
源字符串和目标字符串都必须有’\0‘结束,如果目标字符串没有'\0'不知道从哪里开始
目标空间必须足够大,并且必须可以修改
应用举例:
int main()
{char ch1 [200] = "hello";char ch2 [] = " world";strcat(ch1, ch2);printf("%s\n", ch1);return 0;
}
模拟实现:
char* my_strcat(char* dest, const char* soc)
{assert(dest!=NULL && soc!=NULL);char* ret = dest;//找到*dest指向的'\0'while (*dest!='\0'){dest++;}//然后数据拷贝while (*dest++ = *soc++){;//空语句}return ret;//返回原字符串的地址
}
但是请注意,这么写运行不通过:
char* my_strcat(char* dest, const char* soc)
{assert(dest!=NULL && soc!=NULL);char* ret = dest;//找到*dest指向的'\0'while (*dest!='\0'){dest++;}//然后数据拷贝while (*dest++ = *soc++){;//空语句}return ret;//返回原字符串的地址
}
int main()
{char ch1 [200] = "hello";char ch2 [] = " world";my_strcat(ch1, ch1);printf("%s\n", ch1);return 0;
}
因为自己给自己追加会消除掉'\0',就会造成死循环,因此程序就会崩溃。
strcmp函数的使用和模拟实现
strcmp函数是用来比较字符串大小的函数。
比较标准:比较两个字符串中对应位置上字符ASCII码值的大小(一旦有一个字符比较出来了大小就停止不再进行下一个字符的比较大小,如果二者相等就继续比较下一个位置的字符)
如果第一个字符串大于第二个字符串,则返回一个大于0的数字
如果第一个字符串等于第二个字符串,则返回0
如果第一个字符串小于第二个字符串,则返回一个小于0的数字
对比辨析:
模拟实现:
int my_strcmp(const char* str1, const char* str2)
{int ret = 0;assert(str1!=NULL && str2!=NULL);while (*str1==*str2 ){if (*str1 == '\0'){return 0;}str1++;str2++;}return *str1 - *str2;
}
以上的三个字符函数是长度受限制的字符串函数,接下来我们要学习长度不受限制的字符串函数
strncpy函数的使用
strncpy函数语法如下:
char* strncpy(char *destination, const char *source,size_t num);
int main()
{char arr1[200] = "abcdfghijk";char arr2[20] = " ";strncpy(arr2, arr1,5);printf("%s\n",arr2);return 0;
}
当不够的时候,自动补齐“\0”。
strncat函数的使用
strncat函数的语法结构如下:
char* strncat(char *destination, const char *source,size_t num);
int main()
{char arr1[200] = "abcdfghijkxxxxxxxxxxxxxx";char arr2[20] = "xxx";strncat(arr2, arr1,5);printf("%s\n",arr2);return 0;
}
strncmp函数的使用
strcnmp函数的语法如下:
char* strncmp(char *destination, const char *source,size_t num);
strstr函数的使用和模拟实现
strstr函数主要是用于在一个字符串中找另外一个子字符串是否存在的函数。
strstr函数的语法类型:
char*strstr(const char*str1,char*str2)
如果找到了,返回起始地址;如果没找到返回NULL。
应用:str1中找str2第一次出现的位置,如果找到了返回起始位置的地址。
int main()
{char arr1[100] = "sgudusbvdugdabngfduedudhuidguadbefgbeudhidugauidufuegeuiw";char arr2[100] = "ab";const char *ret=strstr(arr1, arr2);if (ret == NULL){printf("找不到");}else{printf("%s\n",ret);}return 0;
}
模拟实现
方案1:
const char* my__strstr(const char* str1, const char* str2)
{const char* s1 = NULL;const char* s2 = NULL;const char* cur = str1;while (*cur){s1=cur;s2=str2;while (*s1 && *s2 && !(*s1 - *s2)){s1++;s2++;}if (!*s2){return cur;}cur++;}
}
方案2:
char* my_strstr(const char* str1, const char* str2)
{char* cp = (char*)str1;char* s1, * s2;if (!*str2){return (char*)str1;}while (*cp){s1 = cp;s2 = (char*)str2;while (*s1 && *s2 && !(*s1 - *s2)){s1++;s2++;}if (!*s2){return cp;}cp++;}return NULL;
}
strtok函数的使用
strtok函数是用来提取被分隔符分隔的字符串的函数。
如邮箱“loutianlizi@qq.com”
经过strtok函数后产生三段字符串“loutianlizi”,“qq”,“com”
strtok函数的语法形式为:
char*strtok(char*str,const char *sep);
sep参数指向一个字符串,定义了用作分隔符发字符集合
第一个参数指定一个字符串,它包含了0个或者多个sep参数中一个或者多个分隔符分隔的标记
strtok函数找到str中下一个标记,并将其用\0结尾,返回一个指向这个标记的指针(注:strtok函数会改变该被操作的字符串,所以被strtok切割的字符串一般都是临时拷贝内容且可以修改)
strtok第一个参数不为NULL,函数将找到str第一个标记,strtok函数将它保存在字符串中的位置; strtok第一个参数为NULL,函数将在同意字符串中被保存的位置开始,查找下一个标记
如果不存在更多标记则返回NULL指针
int main()
{char arr[] = "hello world";char* sep = " . ";char* str = NULL;for (str==strtok(arr,sep);str!=NULL;str=strtok(NULL,sep)){printf("%s\n",str);}return 0;
}
strerror函数
strerror函数的语法如下:
char*strerror(int errnum);
strerror可以将参数部分错误码对应的错误信息的字符串地址返回回来。
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明的,C语⾔程序启动的时候就会使⽤⼀个全局的变量 errno 来记录程序的当前错误码,只不过程序启动的时候errno是 0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会将对应的错误码,存放在 errno 中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
perrior函数
perroir函数功能同上,直接打印错误信息。打印完参数部分后,再打印“:”和空格,接着打印错误信息。
今天的内容就到这里了,谢谢各位读者朋友,求一个赞谢谢。
以下的内容仅供查询参考。
ASCII值字符表
一、标准ASCII字符表(0-127)
十进制 | 十六进制 | 字符/符号 | 描述 | |
---|---|---|---|---|
0-31 | 0x00-0x1F | 控制字符 | 不可打印,具体功能见下方表格 | |
32 | 0x20 | 空格(Space) | ||
33 | 0x21 | ! | 感叹号 | |
34 | 0x22 | " | 双引号 | |
35 | 0x23 | # | 井号 | |
36 | 0x24 | $ | 美元符号 | |
37 | 0x25 | % | 百分号 | |
38 | 0x26 | & | 与符号 | |
39 | 0x27 | ' | 单引号 | |
40 | 0x28 | ( | 左圆括号 | |
41 | 0x29 | ) | 右圆括号 | |
42 | 0x2A | * | 星号 | |
43 | 0x2B | + | 加号 | |
44 | 0x2C | , | 逗号 | |
45 | 0x2D | - | 减号/连字符 | |
46 | 0x2E | . | 句号 | |
47 | 0x2F | / | 斜杠 | |
48-57 | 0x30-0x39 | 0 -9 | 数字字符 | |
58 | 0x3A | : | 冒号 | |
59 | 0x3B | ; | 分号 | |
60 | 0x3C | < | 小于号 | |
61 | 0x3D | = | 等号 | |
62 | 0x3E | > | 大于号 | |
63 | 0x3F | ? | 问号 | |
64 | 0x40 | @ | at符号 | |
65-90 | 0x41-0x5A | A -Z | 大写字母 | |
91 | 0x5B | [ | 左方括号 | |
92 | 0x5C | \ | 反斜杠 | |
93 | 0x5D | ] | 右方括号 | |
94 | 0x5E | ^ | 脱字符 | |
95 | 0x5F | _ | 下划线 | |
96 | 0x60 | ``` | 反引号 | |
97-122 | 0x61-0x7A | a -z | 小写字母 | |
123 | 0x7B | { | 左花括号 | |
124 | 0x7C | ` | ` | 竖线 |
125 | 0x7D | } | 右花括号 | |
126 | 0x7E | ~ | 波浪号 | |
127 | 0x7F | DEL | 删除字符(不可打印) |
二、控制字符和转义字符表(0-31 和 127)
十进制 | 十六进制 | 转义序列 | 符号 | 功能 |
---|---|---|---|---|
0 | 0x00 | \0 | NUL | 空字符(字符串结束符) |
7 | 0x07 | \a | BEL | 响铃(终端提示音) |
8 | 0x08 | \b | BS | 退格(Backspace) |
9 | 0x09 | \t | HT | 水平制表符(Tab) |
10 | 0x0A | \n | LF | 换行(Line Feed) |
11 | 0x0B | \v | VT | 垂直制表符 |
12 | 0x0C | \f | FF | 换页符(Form Feed) |
13 | 0x0D | \r | CR | 回车(Carriage Return) |
27 | 0x1B | \e | ESC | 退出键(终端控制序列起始) |
127 | 0x7F | - | DEL | 删除字符(历史用途) |