查询文档cplusplus.com 编码过程当中我们经常会遇到处理字符或者字符串的场景, 比如你现在看到的每一个字 字符和字符串
- 字符用
''引起(例如'a', 'b'), 单引号引起的单个字符 - 字符串用
""引起(例如"helloworld", "abcdef"), 双引号包裹的一个或者若干个字符
主要学习
- 操作字符的函数(例如大写字符变小写字符)
- 操作字符串的函数
字符函数
字符分类函数
c语言中有一系列的函数是专门做字符分类的, 也就是一个字符是属于什么类型的字符的 这些函数的使用都需要包含一个头文件ctype.h
| 函数 | 如果他的参数符合下列条件就返回真 |
|---|---|
| iscntrl | 任何控制字符 |
| isspace | 空白字符: 空格' ', 换页'\f', 换行'\n', 回车'\r', 制表符'\t'或者垂直制表符'\v' |
| isdigit | 十进制数字'0'~'9'字符 |
| isxdigit | 十六进制数字, 包括所有十进制数字字符, 小写字母a |
| islower | 小写字母a~z |
| isupper | 大写字母a~z |
| isalpha | 字母a |
| isalnum | 字母或者数字, a |
| ispunct | 标点符号, 任何不属于数字或者字母的图形字符(可打印) |
| isgraph | 任何图形字符 |
| isprint | 任何可打印字符, 包括图形字符和空白字符 |
这些函数的使用方法非常类似
int islower (int c)
islower是能够判断参数部分的c是否是小写字母 通过返回值来说明是否为小写字母, 如果是小写字母就返回非0的整数, 如果不是小写字母, 则返回0
示例1
#include <stdio.h>
#include <ctype.h>
int main() {
char ch = 'a'; //字符a
if(isdigit(ch)) { //如果参数符合条件就为真, a不是数字, 条件为假
printf("是数字字符\n"); //跳过
}
else {
printf("不是数字字符"); //打印
}
return 0;
}
示例2
#include <stdio.h>
#include <ctype.h>
int main() {
char ch = 'a'; //字符a
int ret = islower(ch); //如果条件为假返回值0
if(ret != 0) {
printf("是小写字符\n"); //打印
}
else {
printf("不是小写字符");
}
return 0;
}
示例3
#include <stdio.h>
#include <ctype.h>
int main() {
char ch = 'a'; //字符a
int ret = isupper(ch); //如果条件为假返回值0
if(ret != 0) {
printf("是大写字符\n");
}
else {
printf("不是大写字符"); //打印
}
return 0;
}
练习 写一个代码, 将字符串中的小写字母转为大写, 其他字符不变
#include <stdio.h>
#include <ctype.h>
int main() {
/*为什么写成char *str[] = {"abcdef}会报错?
因为char str[] = {"abcdef"}是创建一个str数组, 将"abcdef"字符串赋值给str数组
而*str是直接指向这个字符串的地址的, 但是这个字符串是常量, 常量是无法更改的
*/
char str[] = { "abcdef" };
int i = 0;
while (str[i] != '\0') {
if (islower(str[i])) {
str[i] -= 32;
}
i++;
}
printf("%s\n", str); //打印abcdef
return 0;
}
字符转换函数
c语言提供了两个字符转换函数
int tolower (int c); //将参数传进去的大写字母转小写 int toupper (int c); //将参数传进去的小写字母转大写
| 函数 | 功能 |
|---|---|
| tolower | 将大写字母转换为小写字母 |
| toupper | 将小写字母转换为大写字母 |
返回值 该值的返回值为int类型, 可以隐式转换为char类型
上面的代码, 我们将小写转大写, 是-32完成的效果, 有了转换函数, 就可以直接使用toupper函数
#include <stdio.h>
#include <ctype.h>
int main() {
char str[] = { "abcdef" };
int i = 0;
while (str[i] != '\0') {
if (islower(str[i])) {
str[i] = toupper(str[i]); //注意 转换后的值是单独一个值, 不会修改原来的值
}
i++;
}
printf("%s\n", str);
return 0;
}
如果传入非字母的字符呢
#include <stdio.h>
#include <ctype.h>
int main() {
char ch = ',';
char ch2 = toupper(ch);
printf("%c\n", ch); //输出',' 如果传入非字母的字符, 那么传入什么就输出什么
return 0;
}
字符串函数
| 函数 | 功能 |
|---|---|
| strlen | 统计字符串长度 |
| strcpy | 字符串拷贝 |
| strcat | 字符串追加/拼接 |
| strcmp | 字符串比较 |
| strncpy | 字符串拷贝n个字符 |
| strncat | 字符串追加/拼接n个字符 |
| strncmp | 字符串比较 |
| strerror | 错误码 |
| strstr | 字符串查找 |
strlen
size_t strlen ( const char * str );
功能: 统计参数str指向的字符串长度. 统计的是字符串中'\0'之前的字符的个数 参数: 指针, 指向了要统计长度的字符串 返回值: 返回了str指向的字符串的长度, 返回的长度不会是负数, 所以是size_t 使用注意事项:
- 字符串
'\0'作为结束标志, strlen函数返回的是再字符串中'\0'前面出现的字符个数(不包含'\0') - 参数指向的字符串必须要以
'\0'结束 - 注意函数的返回值为
size_t(unsigned int), 是无符号的(易错) strlen的使用需要包含头文件<string.h>
练习
#include <stdio.h>
#include <string.h>
int main() {
const char *str1 = "abcdef";
const char *str2 = "abc";
/*是3-6? 符合条件吗? 注意strlen的返回值类型为无符号整形
-3在内存中写入的是补码: (-3>源码(1000 0011)>反码(1111 1100)>补码(1111 1101)
因为是无符号, 转换为十进制就是(253), 所以253 > 0)
*/
if(strlen(str2) - strlen(str1) > 0) {
printf("str2 > str1");
}
else {
printf(str1 > str2);
}
return 0;
}
strcpy
char* strcpy(char* destination, const char* source);
功能: 字符串拷贝, 拷贝到源头字符串中的\0为止 参数: destination: 指针, 指向目的地空间 source: 指针, 指向源头数据 返回值: strcpy函数返回的目标空间的起始地址
strcpy的使用
#include <stdio.h>
#include <>
int main() {
char str_dest[10] = {0};
char* src = "abcd";
//将src字符串的值拷贝到str_dest字符串中, 使用ret获取返回值
char* ret = strcpy(str_dest, src);
printf("ret == %s\n", ret); //abcd
printf("str_dest == %s\n", str_dest); //abcd
return 0;
}
使用注意事项
- 源字符串必须以
\0结束 - 会将源字符串中的
\0拷贝到目标空间 - 目标空间必须足够大, 以确保能存放源字符串
- 目标空间必须可修改
strcpy函数的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcpy(char* destination, const char* source) {
assert(destination != null && source != null); //安全, 保证地址的合法性
char* ret = destination; //先记录一下destination的起始位置(内存地址)
while (*source != '\0') {
*destination = *source;
destination++;
source++;
}
/*也可以写成
//先赋值后++, 如果赋值了\0那么就返回0, while循环接收到0则跳出循环
while ((*destination++ = *source++)) {
;
}
*/
*destination = '\0'; //读取到\0的时候就退出while循环了, 需要手动为destination赋值\0
return ret; //由于复制完后的destination位置在\0, 所以使用ret(记录有起始位置)
}
int main() {
char str_dest[10] = {0};
char* src = "abcd";
my_strcpy(str_dest, src);
printf("ret == %s\n", src);
printf("str_dest == %s\n", str_dest);
return 0;
}
strcat
char* strcat(char* destination, const char* source);
功能:字符串追加/字符串拼接, 把source指向的源字符串中的所有字符串都追加/拼接到destination指向的空间中 参数: destination: 指针, 指向目的地的空间 source: 指针, 指向源头数据 返回值: strcat函数返回的目标空间的起始地址
#include <stdio.h>
#include <assert.h>
#include <string.h>
int main() {
char *str_src = "world";
//数组的空间要足够大, str_sest数组有6个字符, str_src有6个字符, 拼接在一起总共11个字符(hello后面的\0被替换为world)
char str_dest[20] = "hello"; //str_dest数组改变, 不能用指针
//将str_src中的world拼接到str_dest中的hello后面就可以使用strcat
char* ret = strcat(str_dest, str_src);
printf("%s", ret);
return 0;
}
strcat函数的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* str_dest, char* str_src) {
assert(str_dest != null && str_src != null);
char* ret = str_dest;
while (*str_dest != '\0') {
str_dest++;
}
while (*str_src != '\0') {
*str_dest = *str_src;
str_dest++;
str_src++;
}
*str_dest = '\0';
return ret;
}
int main() {
char* str_src = "world";
char str_dest[20] = "hello";
char* ret = my_strcat(str_dest, str_src);
printf("%s\n", ret);
return 0;
}
strcmp
int strcmp (const char* str1, const char* str2);
功能: 用来比较str1和str2指向的字符串, 从两个字符串的第一个字符开始比较, 如果两个字符的ascii码值相等, 就比较下一个字符. 直到遇到不相等的两个字符, 或者字符串结束. 参数: str1: 指针, 指向要比较的第一个字符串 str2: 指针, 指向要比较的第二个字符串 返回值:
标准规定:
- 第一个字符串大于第二个字符串, 则返回大于0的数字
- 第一个字符串等于第二个字符串, 则返回0
- 第一个字符串小于第二个字符串, 则返回小于0的数字
srtcmp的使用
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
const char* srt1 = "abcd";
const char* str2 = "abcde";
//第一个参数和第二个参数进行比较
//<0 第一个参数小于第二个参数
//== 0 第一个参数等于第二个参数
//>0 第一个参数大于第二个参数
int ret = strcmp(str1, str2);
printf("%d\n"ret);
return 0;
}
strcmp的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2) {
assert(str1 != null && str2 != null);
while(*str1 == *str2) {
if (*str1 == '\0') {
return 0;
}
str1++;
str2++;
}
return *str1 - *str2;
}
int main() {
char* str1 = "abay";
char* str2 = "abcd";
int ret = my_strcmp(str1, str2);
printf("%d\n", ret);
return 0;
}
strncpy
char* strncpy(char* destination, const char* source, size_t num);
功能: 字符串拷贝; 将source指向的字符串拷贝到destination指向的空间中, 最多拷贝num个字符 参数: destination: 指针, 指向目的地空间 source: 指针, 指向源头数据 num: 从source指向的字符串中最多拷贝的字符个数 返回值: strncpy函数返回的目标空间的起始地址
strerror
char* strerror(int errnum);
功能:
strerror函数可以通过参数部分的errnum表示错误码, 得到对应的错误信息, 并且返回这个错误信息字符串首字符的地址strerror函数只针对标准库中的函数发生错误后设置的错误码的转换strerror的使用需要包含<string.h>
在不同的系统和c语言标准库的实现中都规定了一些错误码, 一般是放在errno.h这个头文件中说明的, c语言程序启动的时候就会使用一个全局变量errno来记录程序的当前错误码, 只不过程序启动的时候errno是0, 表示没有错误, 当我们在使用标准库中的函数的时候发生了某种错误, 就会将对应的错误码, 存放在errno中, 而一个错误码的数字是整数, 很难理解是什么意思, 所以每一个错误码都是有对应的错误信息的. strerror函数就可以将错误码对应的错误信息字符串的地址返回
参数: errnum: 表示错误码 这个错误码一般传递的是errno这个变量的值, 在c语言有一个全局变量名叫: errno, 当库函数的调用发生错误的时候, 就会将本次错误的错误码存放在errno这个变量中, 使用这个全局变量需要包含一个头文件errno.h 返回值: 函数返回通过错误码得到的错误信息字符串的首字符地址
perror
也可以了解一下perror函数, perror函数直接将错误信息打印出来. perror函数打印完参数部分的字符串后, 再打印一个冒号和一个空格, 再打印错误信息
//注: 错误信息非固定信息, 使用这个错误信息只是为了演示
printf("错误信息是: %s\n", strerror(errno)); //输出 错误信息是: no such file or directory
perror("错误信息是"); //输出 错误信息是: no such file or directory
strstr
char* strstr(const char* str1, const char* str2);
功能: strstr函数, 查找str2指向的字符串在str1指向的字符串中第一次出现的位置 简而言之: 在一个字符串中查找子字符串
参数: str1: 指针, 指向了被查找的字符串 str2: 指针, 指向了要查找的字符串
返回值:
- 如果str1指向的字符串中存在str2指向的字符串, 那么返回第一次出现位置的指针
- 如果str1指向的字符串中不存在str2指向的字符串, 那么返回null
扩展: 如果对字符串查找感兴趣, 可以看看kmp算法, 效率特别高
以上就是c语言中字符函数和字符串函数的使用与实现详解的详细内容,更多关于c语言字符函数和字符串函数的资料请关注代码网其它相关文章!
发表评论