C语言中包含了很多对字符串处理的函数,要使用这些函数,
首先需要导入头文件#include <string.h>
1. strlen() -- 计算字符串长度
原型: size_t strlen(char const *string);
例: char *str = "abcde";size_t len = strlen(str); // 结果为5
注意: strlen()计算的结果是字符串所占有的字节数。
2. 不受限制的字符串函数
2.1 strcpy() -- 字符串拷贝
原型: char *strcpy(char *dst, char const *src);
将src的数据拷贝到dst中,覆盖dst对应位置的数据,返回指向dst的指针
例: char* str = "abcdef";char arr[10];
char* ret = strcpy(arr,str); // 将str中的元素拷贝到arr中,并且覆盖其原来的元素,并 且返回指向arr的指针
注意:
1. 如果拷贝的两个字符串的内存有重叠,那么结果是未定义的,所以应该避免这种操作。
2. 将src的字符串拷贝到dst的字符串,具体操作就是,将src对应的字符拷贝到dst对应的位置,将其原来的元素进行覆盖(包括字符串结束符),这样原来字符串后面的元素就不会被访问到了(看下图)3. dst指针在传入的时候,必须已经有了确定的空间(数组或者动态开辟),因为我们要对dst对应的字符串进行修改,所以不能在dst的位置传入字符串常量。
4. 特别注意: 在拷贝的过程中,我们应该保证dst的空间应该足够容纳下src的字符串,其大小应该至少为strlen(src)+1(+1 是因为还有一个字符串结束符),否则如果src的长度比dst的空间要大,strcpy是不会检测是否超出dst的空间的,它会将不属于dst的后面的空间的数据都替换掉。
str1 = "abcgdef" str2 = abc
将str2拷贝到str1中(会发现只是将str1的值进行覆盖),前面的'\0'会使得后面的数据都不会访问到,因为字符串已经结束了。
2.2 strcat() -- 字符串拼接
原型: char *strcat(char* dst, char const* src);
将src的数据拼接在dst后面,返回指向dst的指针
例子: char[50] message;strcpy(message,"Hello");
strcat(message," World");
printf("%s\n",message); // Hello World
注意:
1. 如果参数指向的两个字符串发生重叠,结果是未定义的。
2. 同样,在将src拼接到dst中的时候,我们应该确保dst剩余的空间能够放下src的数据(当然包括字符串结束符),否则会发生和strcpy一样的问题。
2.3 strcmp() -- 字符串比较
原型: int strcmp(char const * s1, char const* s2);
比较两个字符串的大小,相同返回0, s1<s2返回负数,s1>s2返回正数
例: char* str1 = "abc";char* str2 = "efg";
strcmp(str1,str2); // 返回负数
注意:1. 小于的时候并不是返回-1,而是返回负数,因为其返回值是两个字符串的差值。同理,大 于也是一样。
2. strcmp不会修改字符串,所以我们不需要保证空间问题,但是我们需要保证两个字符串这都必须以'\0'结束,否则,strcmp()会一直向后比较,直到遇到'\0'位置,但是,此时超出了我们拥有的空间,后面的比较已经没有意义了。
3. 长度受限的字符串函数
上面介绍的函数,除了比较函数,其实都存在一个问题,函数都不检查目标字符串是否空间足够放得下源字符串,必须我们自己去保证,但是总有疏漏的时候,可能就会导致程序崩溃。
所以,又提出来了这些函数的安全版本,我们可以指定拷贝的字符的个数,进而减少相应的越界问题。
但是,这些函数的使用,并没有彻底的解决问题,只是相对上面的函数而言的,这个在vs中使用这些函数,如果SDL检查开启的情况下,是无法通过编译的,因为它也不安全。(这时候需要使用vs提供的安全版本)
这些函数还有一个用处(我们之前提到过): 就是可以帮助我们操作指定字节数的字符串。
这些函数的特点: 如果src的长度比len大,那么操作len字节的字符就结束,如果src的长度比len小,那么就值操作src对应长度的字节数。
3.1 strncpy()
原型: char * strncpy(char *dst, char const *src, size_t len);
使用方式和strcpy类似(返回值和前两个参数),只是我们可以通过第三个参数传入拷贝字符串的字节数
例子: char arr[10] = {0};strncpy(arr,"abcdef",3); // 拷贝三个字节的字符到arr中: abc
注意:
1. 两个字符串的空间不能重叠。
2. 一定要注意复制完之后dst必须以'\0'结尾,否则会不是字符串了。
所以: 当len>strlen(src)的时候,那么会将src全部拷贝到dst中,包括字符串结束符。但是,当len>=strlen(src)的时候,其只会拷贝len指定的长度到dst中,这样它的字符串结束符是不会被拷贝到dst,这时候就会出问题,就是字符串在相应的位置不会结束,会访问到后面的数据。
解决方法:1). 如果dst对应字符串中没有数据,那么我们可以将其都设置为'\0'。
2). 我们可以在使用strncpy的时候,多考虑一步,指定的拷贝长度能够拷贝到'\0'3). 就是在拷贝结束之后,手动将最后一个字符设置为'\0';
3. 你会发现即使有了第三个参数的限定,其实也并不是很安全,因为我们依然需要保证第三个参数或者src的长度不能超过dst。
3.2 strncat()
原型和strcat类型,只是有了第三个参数,指定拷贝字节数。 用法也是类似的。
注意:1. 使用strncat()函数也需要注意在拼接的时候是否src的字符串结束符也被拼接到src中了,如果没有就需要我们手动解决。(就是上面说到的)
2. 两字符串的空间依然不能重叠。
3.3 strncmp()
和上面两个是同理的。
4. vs的安全版本
前面说到在vs中使用上面的操作函数会出错,你要么使用vs提供的安全版本,要么将SDL检查关闭。
那么vs的安全版本如何使用呢?其实很简单,它只是多了一个参数,因为上面我们指定的长度len必须保证比dst的长度小,这一点还必须是我们自己来保证。也容易出错。
vs的安全版本在dst参数后,传入dst所能存放的最大字节数的字符,这样如果拷贝的长度超过最大字节数,那么他就只会拷贝到最大字节数。(其余的也同理)
例子: 其余的函数都是一样的char arr[20];
strncpy_s(arr,20,"abcdef",5);
5. 基础字符串的查找
5.1 strchr(),strrchr()查找一个字符
原型: char *strchr(char const *str, int ch); // 从正向查找对应字符,返回指向对应字符第一次出现的位置的指针,如果没找到,返回NULL。
char *strrchr(char const *str, int ch); // 从逆向查找对应字符,返回指向对应字符第一次出现的位置的指针(也就是在字符串中最后出现的位置),没有找到返回NULL。
例: char* ch = strchr("abc",'a');printf("%c\n",*ch); // 输出'a'
5.2 strpbrk()查找任何几个字符
原型: char* strpbrk(char const* str, char const *group); // 函数可以查找任何一组字符第一次在字符串中出现的位置,返回指向str中第一个匹配group中任何一个字符的字符位置。 group指定的所有字符都没有找到,那么就返回NULL。
例: char arr1[] = "abcdefg";char arr2[] = "kfeag";
char *ch = strpbrk(arr1,arr2); // 因为在指定的字符中,在str中第一个出现的是'a',所以ch为指向字符'a'的指针。
5.3 strstr()查找一个子串
原型: char *strstr(char const *s1, char const *s2); // 这个函数在s1中查找整个s2第一次出现的起始位置,并返回一个指向该位置的指针。 如果s2没有出现在s1任何一个位置,那么就返回NULL。
注意: 如果第二个字符串是一个空字符串,那么就返回s1。
例: char* str = strstr("abcdabc","abc"); // 返回第一次出现abc的起始位置的指针。
char* str = strstr("abcdabc",""); // 因为s2为空串,所以返回指向s1的指针。
注意: 在标准库中,没有strrpbrk()和strrstr() ,当然可以自己实现。
6. 高级字符串查找
6.1 strspn(),strcspn()查找一个字符串前缀,可用于跳过字符串前面的空白字符
原型: size_t strspn(char const* str, char const *group); // group字符串指定一个或者多个字符,strspn返回str起始部分匹配group中任意字符的字符数。
size_t strcspn(char const* str, char const *group); // group字符串指定一个或者多个字符,strspn返回str起始部分不匹配group中任意字符的字符数。
注意: 此函数是在str的起始位置去找,用下面的例子说明。
例:例1:
char buffer[] = "12,35,64,Hello,World";
size_t count = strspn(buffer, "2310456798");
printf("%zd\n", count); // 输出结果为2
分析:
我们给定了一个字符数组buffer,然后使用strspn()函数去查找buffer从起始位置开始包含的函数第二个参数中指定的字符个数。会发现,我们此处第二个参数指定的字符为'0'-'9'。
从buffer起始位置开始找,'1','2'都是第二个字符串的字符,但是第三个字符','在第二个字符组中就没有了,所以返回的是2。(从起始位置开始和group中指定字符匹配的字符个数)
例2:也是一种用法,跳过字符串前面的空白字符。char buffer[] = " 12,35,64,Hello,World";
size_t count = strspn(buffer, "\n\t\v\r\f");
printf("%zd\n", count); // 输出的结果就是buffer对应字符串前面的空白字符个数。
所以,我们可以将buffer+count,那么就可以找到字符串第一个非空白字符的位置了。
strcspn()的用法和strspn类似,只是strcspn返回的是从str开始位置与group中指定的字符不匹配的个数。
6.2 strtok()查找标记 -- 也就是根据指定的分隔符将字符串分割
请查看: c/c++函数: strtok() ,strtok_s()
7. stderror()打印错误信息
请查看: strerror,perror,errno