Appearance
字符串字符和字节
C语言没有专门的显式的字符串类型,常以字符串常量或者存储于字符数组,字符串常量适用于程序不会对他进行修改的情况,其他的字符串必须存储于字符数组或动态分配的内存之中
基础
就是一串字符,以一个全为0的NUL字节结尾,因此字符串不能包含NUL字节,NUL字节的长度不包括在字符串的长度之中
长度
库函数:size_t strlrn(char const *string);
size_t定义于stddef.h文件之中,代表无符号整形
**注:**返回值为无符号数
Cif(strlen(x) - strlen(y) >= 0);//错误,这个永远是大于零的结果
C1 #include <stdio.h> 2 #include <string.h> 3 int main(void) 4 { 5 char *a = "##########"; 6 char *b = "###############"; 7 if(strlen(a) - strlen(b) >= 0) 8 printf("longer\n"); 9 else 10 printf("short\n"); 11 return 0; 12 } result: longer
不受限制的字符串函数
常用的字符串函数都是不受限制的,就是说通过寻找NUL字节来判断它的长度。
char *strcpy(char *dst, char const *src);
字符串复制,把src字符串复制到dst字符串之中,目标参数的所有内容都会被覆盖或者丢失,因为复制的字符串最后是NUL字节**注:**程序员必须保证第一个参数的大小可以保存整个字符串被储存
char *strcat(char *dat,char const *src);
字符串链接。把第二个字符串添加到第一个字符串之后,要求dst原先已经有一个字符串
由于两个函数的返回值都是第一个字符串的地址
C
strcat(strcpy(dat, a), b);
int strcmp(char const *s1, char const *s2);
字符串比较,返回值是比较大小,相等的时候返回0**注:**相等的时候返回的0代表错误
长度受限制的字符串函数
C
char *strncpy(char *dst, char const *src, size_t len);
char *strncat(char *dat,char const *src, size_t len);
int strncmp(char const *s1, char const *s2, size_t len);
**注:**在进行复制的时候,如果长度<len会用NUL进行填充,反之着会就进行裁剪,不会以NUL结尾,必须人工添加NUL以免发生意外
追加函数会自动添加NUL,但是不检测溢出
字符串查找
查找一个字符
C
char *strchr(char const *str,int ch);//从左向右,返回指针,没有找到返回NULL
char *strrchr(char const *str,int ch);//从右向左,返回指针
查找几个字符
C
char *strpbrk(char const *str, char const *group);
查找子串
C
char *strstr(char const *s1, char const *s2);
C
1 #include <stdio.h>
2 #include <string.h>
3
4 int main(void)
5 {
6 char *str1 = "hello world\0";
7 char *str2 = "abcde\0";
8 char *str3 = "wor\0";
9 printf("-----strpbrk-----\n");
10 printf("%d\n", strpbrk(str1,str2));
11 printf("%d\n", strpbrk(str1,str3));
12 printf("-----strstr-----\n");
13 printf("%d\n", strstr(str1,str2));
14 printf("%d\n", strstr(str1,str3));
15 }
result:
-----strpbrk-----
2001022981
2001022984
-----strstr-----
0
2001022986
strpbrk查找不需要全部匹配,只要含有相同的内容就可以
strstr查找要求全部一样
高级字符串的查找
查找一个字符串前缀
C
size_t strspn(char const *str, char const *group);//返回字符串之开头和group中的字符匹配的字符个数
size_t strcspn(char const *str, char const *group);//返回字符串之开头和group中的字符不匹配的字符个数
使用:
C
int len1.len2;
char buffer[] = "25,142,330,Smith,J,223-4123"
len1 = strspn(buffer, "0123456789");//返回值为2
len2 = strspn(buffer, ",1234567890");//返回值为11
//查找空白字符的结束
ptr = buffer + strspn(buffer, '\n\r\f\t\v');
1 #include <stdio.h>
2 #include <string.h>
3
4 int main(void)
5 {
6 int len1,len2;
7 char buffer[] = "25,142,330,Smith,J,223-4123";
8
9 len1 = strspn(buffer, "0123456789");//返回值为2
10 len2 = strspn(buffer, ",1234567890");//返回值为11
11 printf("%d\n", len1);
12 printf("%d\n", len2);
13 return 0;
14 }
result
2
11
查找标记
C
char *strtok(char *str, char const *sep);
sep是一个字符串,定义了作为分隔符的字符合集,第一个参数中包含零个或多个sep中的一个或多个分隔符的标记,strtok找到下一个标记,并将其用NUL结尾返回
**注:**strtok会修改字符串,请提前做好备份,改变后的字符串是第一段
如果在第一个参数传入NULL则继续对上一个字符串查找,直到返回值为NULL
C
1 #include <stdio.h>
2 #include <string.h>
3
4 void print_tokens(char *line)
5 {
6 static char *whitespace = " \t\n\f\r\v";
7 char *token;
8 // printf("%s\n", line);
9 for(token = strtok(line, whitespace);
10 token != NULL;
11 token = strtok(NULL, whitespace))
12 printf("Next token is %s\n",token);
13
14 }
15
16 int main(void)
17 {
18 char *token;
19 char line[60] =" wocao2 666 zhesha\n gg";
20 print_tokens(line);
21 printf("----\n");
22 printf("%s", line);
23 }
result:
Next token is wocao2
Next token is 666
Next token is zhesha
Next token is gg
----
wocao2
**注:**不要使用
char *str = "abc"
形式的字符串,这是一个常量,不可以更改不可以同时解析两个字符串
还可以在每次提取的时候采用不同的标记符
打印错误信息
C
char *strerror(int error_number);//返回当前的错误信息, open() write() creat() 函数就会把错误原因放入errno
error_number
的值通常为``errno,
strerror实在
string.h这个头文件中的, 同样,
errno也是存放在
errno.h`头文件中.
C
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4
5 int main()
6 {
7 printf("%s\n", strerror(errno));
8
9 return 0;
10 }
字符操作
包含于ctype.h
中
字符分类
这些函数的可移植性比较好比如if(ch >= "A" && ch <= "Z");
只能在使用ASCII码的机器上使用
字符转换
C
int tolower(int ch);//转为小写
int toupper(int ch);//转为大写
内存操作
字符串在遇到NUL字节就进行结尾,但是在内存操作中这样的数据并不少
**注:**长度的单位是字节
C
//复制
void *memcpy(void *dst,void const *str, size_t length);
//复制但是原地址和目标可以重叠,会先进行备份然后复制
void *memmove(void *dst,void const *str, size_t length);
//比较
void *memcmp(void const *a, void const *b, size_t length);
//查找
void *memchr(void const *a, int ch, size_t length);
//全部设置为ch
void *memset(void *a,int ch, size_t length);