对 C 语言的字符处理函数库、通用函数库、标准输入输出函数库、字符串处理函数库的学习笔记
目标
- 使用
字符处理函数库(ctype)
中的函数 - 使用
通用函数库 (stdlib)
中的字符串转换函数
- 使用
标准输入输出函数库 (stdio)
中的字符串
和字符输入输出函数
- 使用
字符串处理函数库
中的字符串处理函数
- 函数库的功能
重点
8.2 字符串和字符基础
char*
类型的变量用字符串初始化的时候,字符串是放在内存里无法改写的区域 ,如果要进行修改,要先储存到一个字符数组中scanf函数
读入字符知道遇到 空格、 tab 键、 换行符、EOF 为止格式转换说明符
%19s
:使 scanf 函数最多读入 19 个字符,并把\0 储存到数组中函数
readline (非标准)
可以读取任意长度的输入行调用函数是要注意区分 字符串 和 字符
8.3 字符处理函数库(ctype.h)
- 这一部分就是用里面各种函数判断是否为 数字、字母、 空格、小写、 大写,然后转下大小写 而已
8.4 字符串转换函数 (stdlib.h)
可以将字符串 转换为 各种类型的数字
函数 | 类型 |
---|---|
atof | double |
atoi | int |
atol | long |
strtod | double |
strtol | long |
strtoul | unsigned long |
- 注意 : 用下面三个函数的时候要注意参数不止一个
函数 | 参数 1(char *) | 参数 2(char **) | 参数 3(int) |
---|---|---|---|
strtod | 目标字符串 | 指向导致溢出的字符的地址 | 无 |
目标字符串 | 指向导致溢出的字符的地址 | 识别为几进制(2-36) | |
目标字符串 | 指向导致溢出的字符的地址 | 识别为几进制 |
注意:
- 如果要转换的字符串太长,超出了无符号长整型值的取值范围,strtoul()函数将返回 ULONG_MAX(4294967295),
- 参数 2 是一个指向 地址 的 地址 一般格式是
&指针名
值得注意的是 经过我的实验
在 Dev-C++
和 TDM-GCC 4.9.2
的环境下,
ato* 函数
如果字符串里面第一个字符不是数字的话 返回的是 null ,
如果第一个字符是数字 ,第二的不是的话 , 那么 程序就会 GG, 无响应
strto*函数
如果字符串里面第一个字符不是数字的话 返回的是 0 ,
如果第一个字符是数字 ,第二的不是的话 , 那么 函数就会 返回 直到第一个字母之前的数字,比如“13ab23” 就会 返回 “12”
然后参数二的地址的内容就会被返回 第一个字母开始的字符串 比如上面的就是 “ab23”
8.5 标准输入输出库函数(stdio.h)
看到一个很美妙的递归输出代码,分享一下
1 | void reverse (const char *const sPtr){ |
- 用 getchar() 的时候记得 字符串最后要加个
'\0'
(貌似以前都没有加 逃…) - 用 puts 的话会自动换行的
8.6 字符串处理函数库中的字符串处理函数(string.h)
- strcpy, strncpy, strcat, strncat 这些函数返回都是第一个参数
- 使用 strncpy 的时候可以利用第三个参数的值(比字符串长度多一) 决定 是否 复制
\0
8.7 字符串处理库中的比较函数(string.h)
strcmp , strncmp
- 按字典序(ascii 码)
- 注意 : 以上带 n 的函数第三个参数实际上的类型是
size_t
8.8 字符串处理函数库的查找函数(string.h)
- strcspn , strspn 返回值类型都是
size_t
8.9 字符串处理函数库的内存函数(string.h)
感觉和上面的差不多,就是基于内存的操作,都需要自己设置长度(是基于内存的长度,比如一个 int 就是 4)(还有对于任何数据类型都可以用)
补充一下指针知识
指向任意数据类型的指针都可以直接赋给类型为 void* 的指针变量,同时类型为 void* 的指针也可以直接赋给指向任意数据类型的指针变量(晚上有的说需要强制类型转换,但是尴尬的是我在 Dev-cpp 里面是不需要的,可能这是 Dev-cpp 的一个特性吧(更有可能是 GNU 的锅),真尴尬)
void 指针不能进行算法操作(尴尬的是 GNU 认定 void* 和 char* 的算法操作是一样的,是可以的,又尴尬起来了)
因此下列语句在 GNU 编译器中皆正确:
pvoid++; //GNU:正确
pvoid += 1; //GNU:正确
pvoid++的执行结果是其增大了 1。( 在 VC6.0 上测试是 sizeof(int)的倍数)
在实际的程序设计中,为迎合 ANSI 标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:
void * pvoid;
(char *)pvoid++; //ANSI:正确;GNU:正确
(char *)pvoid += 1; //ANSI:错误;GNU:正确
GNU 和 ANSI 还有一些区别,总体而言,GNU 较 ANSI 更“开放”,提供了对更多语法的支持。但是我们在真实设计时,还是应该尽可能地迎合 ANSI 标准。
memmove 的一个特性是把第二个实参先复制到一个临时的字符数组中,在从临时数组复制到第一个实参里面
(书本说只有这个函数能处理同一字符串的不同部分,但是我用 strncpy 也能实现相同的功能,那又很尴尬了)
8.10 字符串后处理函数库中的其他函数(string.h)
- strlen 返回的长度不算
\0