Skip to content

字符串字符和字节

C语言没有专门的显式的字符串类型,常以字符串常量或者存储于字符数组,字符串常量适用于程序不会对他进行修改的情况,其他的字符串必须存储于字符数组或动态分配的内存之中

基础

就是一串字符,以一个全为0的NUL字节结尾,因此字符串不能包含NUL字节,NUL字节的长度不包括在字符串的长度之中

长度

库函数:size_t strlrn(char const *string); size_t定义于stddef.h文件之中,代表无符号整形

**注:**返回值为无符号数

C
if(strlen(x) - strlen(y) >= 0);//错误,这个永远是大于零的结果
C
  1 #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

字符分类

QQ图片20220727134007

这些函数的可移植性比较好比如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);